Adding git support to the ant SvnInfo task.
git svn users should now be able to correctly label a build with accurate svn information.
Review by: fabbott
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5008 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/CommandRunner.java b/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/CommandRunner.java
index ff47993..8f9881e 100644
--- a/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/CommandRunner.java
+++ b/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/CommandRunner.java
@@ -30,9 +30,11 @@
/**
* Returns the output of running a command as a string. Will fail if the
- * invoked process returns a non-zero status code.
+ * invoked process returns a non-zero status code and
+ * <code>checkStatusCode</code> is <code>true</code>.
*/
- public static String getCommandOutput(File workDir, String... cmd) {
+ public static String getCommandOutput(boolean checkStatusCode, File workDir,
+ String... cmd) {
Process process = runCommandIgnoringErr(workDir, cmd);
StringBuilder output = new StringBuilder();
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(
@@ -43,7 +45,7 @@
output.append('\n');
}
int statusCode = process.waitFor();
- if (statusCode != 0) {
+ if (checkStatusCode && statusCode != 0) {
throw new BuildException("Non-zero status code result (" + statusCode
+ ") running command: " + makeCmdString(cmd));
}
@@ -58,6 +60,14 @@
}
/**
+ * Returns the output of running a command as a string. Will fail if the
+ * invoked process returns a non-zero status code.
+ */
+ public static String getCommandOutput(File workDir, String... cmd) {
+ return getCommandOutput(true, workDir, cmd);
+ }
+
+ /**
* Runs the specified command and returns the {@link Process}. The caller
* must handle both the output and error streams to avoid blocking the
* underlying process.
diff --git a/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/SvnInfo.java b/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/SvnInfo.java
index 706fc54..10d7b87 100644
--- a/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/SvnInfo.java
+++ b/build-tools/ant-gwt/src/com/google/gwt/ant/taskdefs/SvnInfo.java
@@ -79,6 +79,69 @@
+ URL_REGEX + ")\\s*");
/**
+ * Returns true if this git working copy matches the specified svn revision,
+ * and also has no local modifications.
+ */
+ static boolean doesGitWorkingCopyMatchSvnRevision(File dir, String svnRevision) {
+ String workingRev = getGitWorkingRev(dir);
+ String targetRev = getGitRevForSvnRev(dir, svnRevision);
+ if (!workingRev.equals(targetRev)) {
+ return false;
+ }
+ String status = getGitStatus(dir);
+ return status.contains("nothing to commit (working directory clean)");
+ }
+
+ /**
+ * Returns the git commit number matching the specified svn revision.
+ */
+ static String getGitRevForSvnRev(File dir, String svnRevision) {
+ String output = CommandRunner.getCommandOutput(dir, "git", "svn",
+ "find-rev", "r" + svnRevision);
+ output = output.trim();
+ if (output.length() == 0) {
+ throw new BuildException("git svn find-rev didn't give any answer");
+ }
+ return output;
+ }
+
+ /**
+ * Runs "git status" and returns the result.
+ */
+ static String getGitStatus(File dir) {
+ // git status returns 1 for a status code, so just don't check it.
+ String output = CommandRunner.getCommandOutput(false, dir, "git", "status");
+ if (output.length() == 0) {
+ throw new BuildException("git status didn't give any answer");
+ }
+ return output;
+ }
+
+ /**
+ * Runs "git svn info", returning the output as a string.
+ */
+ static String getGitSvnInfo(File dir) {
+ String output = CommandRunner.getCommandOutput(dir, "git", "svn", "info");
+ if (output.length() == 0) {
+ throw new BuildException("git svn info didn't give any answer");
+ }
+ return output;
+ }
+
+ /**
+ * Returns the current git commit number of the working copy.
+ */
+ static String getGitWorkingRev(File dir) {
+ String output = CommandRunner.getCommandOutput(dir, "git", "rev-list",
+ "--max-count=1", "HEAD");
+ output = output.trim();
+ if (output.length() == 0) {
+ throw new BuildException("git rev-list didn't give any answer");
+ }
+ return output;
+ }
+
+ /**
* Runs "svn info", returning the output as a string.
*/
static String getSvnInfo(File dir) {
@@ -101,6 +164,17 @@
return output;
}
+ static boolean looksLikeGit(File dir) {
+ dir = dir.getAbsoluteFile();
+ while (dir != null) {
+ if (new File(dir, ".git").isDirectory()) {
+ return true;
+ }
+ dir = dir.getParentFile();
+ }
+ return false;
+ }
+
/**
* Returns <code>true</code> if the specified directory looks like an svn
* working copy.
@@ -189,13 +263,20 @@
}
Info info;
- if (!looksLikeSvn(workDirFile)) {
- info = new Info("unknown", "unknown");
- } else {
+ if (looksLikeSvn(workDirFile)) {
info = parseInfo(getSvnInfo(workDirFile));
// Use svnversion to get a more exact revision string.
info.revision = getSvnVersion(workDirFile);
+ } else if (looksLikeGit(workDirFile)) {
+ info = parseInfo(getGitSvnInfo(workDirFile));
+
+ // Add a 'M' tag if this working copy is not pristine.
+ if (!doesGitWorkingCopyMatchSvnRevision(workDirFile, info.revision)) {
+ info.revision += "M";
+ }
+ } else {
+ info = new Info("unknown", "unknown");
}
getProject().setNewProperty(outprop, info.branch + "@" + info.revision);
diff --git a/build-tools/ant-gwt/test/com/google/gwt/ant/taskdefs/SvnInfoTest.java b/build-tools/ant-gwt/test/com/google/gwt/ant/taskdefs/SvnInfoTest.java
index 02ccdb2..2d09fd7 100644
--- a/build-tools/ant-gwt/test/com/google/gwt/ant/taskdefs/SvnInfoTest.java
+++ b/build-tools/ant-gwt/test/com/google/gwt/ant/taskdefs/SvnInfoTest.java
@@ -32,6 +32,79 @@
private static final File dir = new File(".");
/**
+ * A cached copy of 'git svn info' so we don't have to keep running it (makes
+ * the tests run faster).
+ */
+ private static String gitSvnInfo = null;
+
+ /**
+ * Check that this is a valid git rev.
+ */
+ private static void assertIsValidGitRev(String rev) {
+ assertNotNull(rev);
+ assertEquals(rev, 40, rev.length());
+ for (char ch : rev.toCharArray()) {
+ assertTrue(isHexDigit(ch));
+ }
+ }
+
+ private static String getGitSvnInfo() {
+ if (gitSvnInfo == null) {
+ gitSvnInfo = SvnInfo.getGitSvnInfo(dir);
+ }
+ return gitSvnInfo;
+ }
+
+ private static boolean isHexDigit(char ch) {
+ return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')
+ || (ch >= 'a' && ch <= 'f');
+ }
+
+ /**
+ * Test that doesGitWorkingCopyMatchSvnRevision finishes.
+ */
+ public void testDoesGitWorkingCopyMatchSvnRevision() {
+ if (SvnInfo.looksLikeGit(dir)) {
+ Info info = SvnInfo.parseInfo(getGitSvnInfo());
+ SvnInfo.doesGitWorkingCopyMatchSvnRevision(dir, info.revision);
+ }
+ }
+
+ /**
+ * Test that getGitRevForSvnRev returns a 40-character git hash.
+ */
+ public void testGetGitRevForSvnRev() {
+ if (SvnInfo.looksLikeGit(dir)) {
+ Info info = SvnInfo.parseInfo(getGitSvnInfo());
+ String rev = SvnInfo.getGitRevForSvnRev(dir, info.revision);
+ assertIsValidGitRev(rev);
+ }
+ }
+
+ public void testGetGitStatus() {
+ if (SvnInfo.looksLikeGit(dir)) {
+ String status = SvnInfo.getGitStatus(dir);
+ assertNotNull(status);
+ assertTrue(!"".equals(status));
+ }
+ }
+
+ public void testGetGitSvnInfo() {
+ if (SvnInfo.looksLikeGit(dir)) {
+ String info = getGitSvnInfo();
+ assertNotNull(info);
+ assertTrue(!"".equals(info));
+ }
+ }
+
+ public void testGetGitSvnWorkingRev() {
+ if (SvnInfo.looksLikeGit(dir)) {
+ String rev = SvnInfo.getGitWorkingRev(dir);
+ assertIsValidGitRev(rev);
+ }
+ }
+
+ /**
* If this is an svn working copy, just verify that "svn info" succeeds and
* returns something.
*/