johannes created this revision.

This adds a command line option "-git-rev=<commit>".
When it is used, only one filename is accepted.  The file in its version
in the specified revision is compared against the current version. Note
that this calls `git checkout` in the current directory.


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,11 @@
                                       cl::Optional, cl::init(""),
                                       cl::cat(ClangDiffCategory));
 
+static cl::opt<std::string>
+    GitRevision("git-rev", cl::desc("Compare the file from a checkout of this "
+                                    "revision with the current version."),
+                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 +444,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 +492,40 @@
     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 CurrentRevision, Git;
+    auto ErrorOrGit = llvm::sys::findProgramByName("git");
+    if (!ErrorOrGit) {
+      llvm::errs() << "Error: Could not find git executable.\n";
+      return 1;
+    }
+    Git = ErrorOrGit.get();
+    CurrentRevision = Exec("git rev-parse HEAD");
+    *std::find(CurrentRevision.begin(), CurrentRevision.end(), '\n') = '\0';
+    const char *Checkout[] = {"git", "checkout", GitRevision.data(), nullptr};
+    if (llvm::sys::ExecuteAndWait(Git, Checkout)) {
+      llvm::errs() << "Error: Failed to checkout " << GitRevision << "\n";
+      return 1;
+    }
+    Src = getAST(CommonCompilations, SourcePath);
+    Checkout[2] = CurrentRevision.data();
+    if (llvm::sys::ExecuteAndWait(Git, Checkout)) {
+      llvm::errs() << "Error: Failed to checkout " << CurrentRevision << "\n";
+      return 1;
+    }
+    Dst = getAST(CommonCompilations, SourcePath);
+  } else {
+    Src = getAST(CommonCompilations, SourcePath);
+    Dst = getAST(CommonCompilations, DestinationPath);
+  }
+
   if (!Src || !Dst)
     return 1;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to