14 #include <boost/algorithm/string/classification.hpp>
15 #include <boost/algorithm/string/predicate.hpp>
16 #include <boost/algorithm/string/split.hpp>
19 #include "Wt/cpp17/filesystem.hpp"
27 unsigned char fromHex(
char b)
32 return (b -
'A') + 0x0A;
34 return (b -
'a') + 0x0A;
37 unsigned char fromHex(
char msb,
char lsb)
39 return (fromHex(msb) << 4) + fromHex(lsb);
42 char toHex(
unsigned char b)
47 return 'a' + (b - 0xA);
50 void toHex(
unsigned char b,
char& msb,
char& lsb)
52 lsb = toHex(b & 0x0F);
63 POpenWrapper(
const std::string& cmd,
Git::Cache& cache) {
64 std::string s = sanitize(cmd);
68 for (Git::Cache::iterator i = cache.begin(); i != cache.end(); ++i)
73 cache.splice(cache.begin(), cache, i);
78 std::cerr << s << std::endl;
79 FILE *stream = popen((s +
" 2>&1").c_str(),
"r");
86 n = fread(buffer, 1, 30000, stream);
88 content_ += std::string(buffer, n);
91 status_ = pclose(stream);
95 cache.push_front(std::make_pair(s, content_));
102 std::string& readLine(std::string& r,
bool stripWhite =
true) {
106 && (idx_ < content_.length()) && isspace(content_[idx_]))
109 while (idx_ < content_.size() && content_[idx_] !=
'\n') {
114 if (idx_ < content_.size())
120 const std::string& contents()
const {
124 bool finished()
const {
125 return idx_ == content_.size();
128 int exitStatus()
const {
133 std::string content_;
138 std::string sanitize(
const std::string& cmd) {
144 std::string unsafe =
"<>&;|[$`";
146 for (
auto item : cmd) {
147 if (unsafe.find(item) == std::string::npos)
172 : std::runtime_error(msg)
180 if (
id.length() != 40)
183 for (
int i = 0; i < 20; ++i)
184 (*
this)[i] = fromHex(
id[2 * i],
id[2 * i + 1]);
189 std::string result(40,
'-');
191 for (
int i = 0; i < 20; ++i)
192 toHex((*
this)[i], result[2 * i], result[2 * i + 1]);
209 namespace fs = cpp17::filesystem;
210 #ifdef WT_FILESYSTEM_IMPL_BOOST
211 boost::system::error_code ignored;
213 std::error_code ignored;
215 is_bare_ = !fs::is_directory(fs::path(repositoryPath) /
".git", ignored);
230 if (!
getCmdResult(
"cat-file -p " +
id.toString(), result, -1))
231 throw Exception(
"Git: could not cat '" +
id.toString() +
"'");
238 std::string sha1Commit;
245 std::string treeLine;
247 throw Exception(
"Git: could not parse tree from commit '"
250 std::vector<std::string> v;
251 boost::split(v, treeLine, boost::is_any_of(
" "));
253 throw Exception(
"Git: could not parse tree from commit '"
254 + commit.
toString() +
"': '" + treeLine +
"'");
260 std::string objectLine;
262 throw Exception(
"Git: could not read object %"
266 std::vector<std::string> v1,
v2;
267 boost::split(v1, objectLine, boost::is_any_of(
"\t"));
269 throw Exception(
"Git: could not parse tree object line: '"
271 boost::split(
v2, v1[0], boost::is_any_of(
" "));
273 throw Exception(
"Git: could not parse tree object line: '"
276 const std::string& stype =
v2[1];
280 else if (stype ==
"blob")
283 throw Exception(
"Git: Unknown type: " + stype);
311 if (p.exitStatus() != 0)
312 throw Exception(
"Git error: " + p.readLine(result));
315 result = p.contents();
320 for (
int i = 0; i < index; ++i) {
330 const std::string& tag)
const
334 if (p.exitStatus() != 0)
335 throw Exception(
"Git error: " + p.readLine(result));
337 while (!p.finished()) {
339 if (boost::starts_with(result, tag))
352 if (p.exitStatus() != 0)
353 throw Exception(
"Git error: " + p.readLine(r));
356 while (!p.finished()) {
369 if (p.exitStatus() != 0)
370 throw Exception(
"Git error: " + p.readLine(r));
Exception(const std::string &msg)
Constructor.
std::string toString() const
Print as a 40-digit hexadecimal number.
ObjectId()
Default constructor.
Cache cache_
A small LRU cache that stores results of git commands.
std::list< std::pair< std::string, std::string > > Cache
ObjectId getCommit(const std::string &revision) const
Get the commit for a particular revision.
std::string repository_
The path to the repository.
ObjectId getTreeFromCommit(const ObjectId &commit) const
Get the tree for a particular commit.
std::string catFile(const ObjectId &id) const
Return the raw contents of a git object.
int getCmdResultLineCount(const std::string &cmd) const
Returns the number of lines in the output of a git command.
bool is_bare_
Whether the repositoy is a bare repository.
Object treeGetObject(const ObjectId &tree, int index) const
Get some info on a tree object.
void checkRepository() const
Checks the repository.
int treeSize(const ObjectId &tree) const
Return the number of objects inside a tree object.
void setRepositoryPath(const std::string &repository)
Set the git repository path.
ObjectType
Git object type.
bool getCmdResult(const std::string &cmd, std::string &result, const std::string &tag) const
Returns a line identified by a tag from the output of a git command.
std::string baseCmd() const
The git base command after which extra arguments are added.
ObjectId getCommitTree(const std::string &revision) const
Get the tree for a particular revision.
void id(Action &action, V &value, const std::string &name="id", int size=-1)
WString asString(const cpp17::any &v, const WString &formatString=WString())
Object(const ObjectId &id, ObjectType type)