johannes updated this revision to Diff 111328.
johannes edited the summary of this revision.
johannes added a comment.
accept a commit range
https://reviews.llvm.org/D36686
Files:
tools/clang-diff/ClangDiff.cpp
Index: tools/clang-diff/ClangDiff.cpp
===================================================================
--- tools/clang-diff/ClangDiff.cpp
+++ tools/clang-diff/ClangDiff.cpp
@@ -16,6 +16,7 @@
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Program.h"
using namespace llvm;
using namespace clang;
@@ -33,9 +34,9 @@
cl::desc("Print the internal representation of the AST as JSON."),
cl::init(false), cl::cat(ClangDiffCategory));
-static cl::opt<bool>
- PrintMatches("dump-matches", cl::desc("Print the matched nodes."),
- cl::init(false), cl::cat(ClangDiffCategory));
+static cl::opt<bool> PrintMatches("dump-matches",
+ cl::desc("Print the matched nodes."),
+ cl::init(false), cl::cat(ClangDiffCategory));
static cl::opt<bool> HtmlDiff("html",
cl::desc("Output a side-by-side diff in HTML."),
@@ -55,6 +56,12 @@
cl::Optional, cl::init(""),
cl::cat(ClangDiffCategory));
+static cl::opt<std::string>
+ GitRevision("git-rev",
+ cl::desc("Compare a file between a revision range (<rev>..HEAD "
+ "is assumed if a single revision is given."),
+ cl::Optional, cl::init(""), cl::cat(ClangDiffCategory));
+
static cl::opt<int> MaxSize("s", cl::desc("<maxsize>"), cl::Optional,
cl::init(-1), cl::cat(ClangDiffCategory));
@@ -438,6 +445,19 @@
}
}
+std::string Exec(const char *Command) {
+ char Buffer[128];
+ std::string Result;
+ std::shared_ptr<FILE> Pipe(popen(Command, "r"), pclose);
+ if (!Pipe)
+ return Result;
+ while (!feof(Pipe.get())) {
+ if (fgets(Buffer, 128, Pipe.get()) != nullptr)
+ Result += Buffer;
+ }
+ return Result;
+}
+
int main(int argc, const char **argv) {
std::string ErrorMessage;
std::unique_ptr<CompilationDatabase> CommonCompilations =
@@ -473,13 +493,55 @@
return 0;
}
- if (DestinationPath.empty()) {
+ if (DestinationPath.empty() && GitRevision.empty()) {
llvm::errs() << "Error: Exactly two paths are required.\n";
return 1;
}
- std::unique_ptr<ASTUnit> Src = getAST(CommonCompilations, SourcePath);
- std::unique_ptr<ASTUnit> Dst = getAST(CommonCompilations, DestinationPath);
+ std::unique_ptr<ASTUnit> Src, Dst;
+
+ if (!GitRevision.empty()) {
+ std::string Git;
+ auto ErrorOrGit = llvm::sys::findProgramByName("git");
+ if (!ErrorOrGit) {
+ llvm::errs() << "Error: Could not find git executable.\n";
+ return 1;
+ }
+ Git = ErrorOrGit.get();
+ if (GitRevision.find("..") == std::string::npos)
+ GitRevision += "..HEAD";
+ size_t Dots = GitRevision.find("..");
+ GitRevision.replace(Dots, 2, " ");
+ GitRevision += " HEAD";
+ std::string RevParseCommand = "git rev-parse " + GitRevision;
+ std::string Revisions = Exec(RevParseCommand.data());
+ std::transform(Revisions.begin(), Revisions.end(), Revisions.begin(),
+ [](char C) { return C == '\n' ? '\0' : C; });
+ auto SrcRev = Revisions.data();
+ size_t Offset = Revisions.find('\0') + 1;
+ auto DstRev = Revisions.data() + Offset;
+ auto UserRev = Revisions.data() + Revisions.find('\0', Offset) + 1;
+ const char *Checkout[] = {"git", "checkout", nullptr, nullptr};
+ auto checkout = [&](const char *Rev) {
+ Checkout[2] = Rev;
+ if (llvm::sys::ExecuteAndWait(Git, Checkout)) {
+ llvm::errs() << "Error: Failed to checkout " << Rev << "\n";
+ return false;
+ }
+ return true;
+ };
+ if (!checkout(SrcRev))
+ return 1;
+ Src = getAST(CommonCompilations, SourcePath);
+ if (!checkout(DstRev))
+ return 1;
+ Dst = getAST(CommonCompilations, SourcePath);
+ checkout(UserRev);
+ } else {
+ Src = getAST(CommonCompilations, SourcePath);
+ Dst = getAST(CommonCompilations, DestinationPath);
+ }
+
if (!Src || !Dst)
return 1;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits