14 #include <boost/algorithm/string/classification.hpp> 15 #include <boost/algorithm/string/predicate.hpp> 16 #include <boost/algorithm/string/split.hpp> 26 unsigned char fromHex(
char b)
31 return (b -
'A') + 0x0A;
33 return (b -
'a') + 0x0A;
36 unsigned char fromHex(
char msb,
char lsb)
38 return (fromHex(msb) << 4) + fromHex(lsb);
41 char toHex(
unsigned char b)
46 return 'a' + (b - 0xA);
49 void toHex(
unsigned char b,
char& msb,
char& lsb)
51 lsb = toHex(b & 0x0F);
62 POpenWrapper(
const std::string& cmd,
Git::Cache& cache) {
63 std::string s = sanitize(cmd);
67 for (Git::Cache::iterator i = cache.begin(); i != cache.end(); ++i)
72 cache.splice(cache.begin(), cache, i);
77 std::cerr << s << std::endl;
78 FILE *stream = popen((s +
" 2>&1").c_str(),
"r");
85 n = fread(buffer, 1, 30000, stream);
87 content_ += std::string(buffer, n);
90 status_ = pclose(stream);
94 cache.push_front(std::make_pair(s, content_));
101 std::string& readLine(std::string& r,
bool stripWhite =
true) {
105 && (idx_ < content_.length()) && isspace(content_[idx_]))
108 while (idx_ < content_.size() && content_[idx_] !=
'\n') {
113 if (idx_ < content_.size())
119 const std::string& contents()
const {
123 bool finished()
const {
124 return idx_ == content_.size();
127 int exitStatus()
const {
132 std::string content_;
137 std::string sanitize(
const std::string& cmd) {
143 std::string unsafe =
"<>&;|[$`";
145 for (
auto item : cmd) {
146 if (unsafe.find(item) == std::string::npos)
171 : std::runtime_error(msg)
179 if (
id.length() != 40)
182 for (
int i = 0; i < 20; ++i)
183 (*
this)[i] = fromHex(
id[2 * i],
id[2 * i + 1]);
188 std::string result(40,
'-');
190 for (
int i = 0; i < 20; ++i)
191 toHex((*
this)[i], result[2 * i], result[2 * i + 1]);
209 is_bare_ = !(stat((repositoryPath +
"/.git").c_str(), &sb) == 0 &&
210 S_ISDIR(sb.st_mode));
225 if (!
getCmdResult(
"cat-file -p " +
id.toString(), result, -1))
226 throw Exception(
"Git: could not cat '" +
id.toString() +
"'");
233 std::string sha1Commit;
240 std::string treeLine;
242 throw Exception(
"Git: could not parse tree from commit '" 245 std::vector<std::string> v;
246 boost::split(v, treeLine, boost::is_any_of(
" "));
248 throw Exception(
"Git: could not parse tree from commit '" 249 + commit.
toString() +
"': '" + treeLine +
"'");
255 std::string objectLine;
257 throw Exception(
"Git: could not read object %" 261 std::vector<std::string> v1,
v2;
262 boost::split(v1, objectLine, boost::is_any_of(
"\t"));
264 throw Exception(
"Git: could not parse tree object line: '" 266 boost::split(v2, v1[0], boost::is_any_of(
" "));
268 throw Exception(
"Git: could not parse tree object line: '" 271 const std::string& stype = v2[1];
275 else if (stype ==
"blob")
278 throw Exception(
"Git: Unknown type: " + stype);
306 if (p.exitStatus() != 0)
307 throw Exception(
"Git error: " + p.readLine(result));
310 result = p.contents();
315 for (
int i = 0; i < index; ++i) {
325 const std::string& tag)
const 329 if (p.exitStatus() != 0)
330 throw Exception(
"Git error: " + p.readLine(result));
332 while (!p.finished()) {
334 if (boost::starts_with(result, tag))
347 if (p.exitStatus() != 0)
348 throw Exception(
"Git error: " + p.readLine(r));
351 while (!p.finished()) {
364 if (p.exitStatus() != 0)
365 throw Exception(
"Git error: " + p.readLine(r));
void checkRepository() const
Checks the repository.
int getCmdResultLineCount(const std::string &cmd) const
Returns the number of lines in the output of a git command.
Object(const ObjectId &id, ObjectType type)
int treeSize(const ObjectId &tree) const
Return the number of objects inside a tree object.
std::string baseCmd() const
The git base command after which extra arguments are added.
Object treeGetObject(const ObjectId &tree, int index) const
Get some info on a tree object.
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.
bool is_bare_
Whether the repositoy is a bare repository.
std::string toString() const
Print as a 40-digit hexadecimal number.
std::list< std::pair< std::string, std::string > > Cache
void id(Action &action, V &value, const std::string &name="id", int size=-1)
WString asString(const cpp17::any &v, const WString &formatString=WString())
ObjectId getCommit(const std::string &revision) const
Get the commit for a particular revision.
ObjectType
Git object type.
std::string repository_
The path to the repository.
Cache cache_
A small LRU cache that stores results of git commands.
ObjectId getTreeFromCommit(const ObjectId &commit) const
Get the tree for a particular commit.
Exception(const std::string &msg)
Constructor.
ObjectId()
Default constructor.
ObjectId getCommitTree(const std::string &revision) const
Get the tree for a particular revision.
std::string catFile(const ObjectId &id) const
Return the raw contents of a git object.
void setRepositoryPath(const std::string &repository)
Set the git repository path.