VIVO-29 Obtain revisión info from Git

Subversion is no longer relevant.
This commit is contained in:
j2blake 2013-08-26 17:37:32 -04:00
parent e2b5c71874
commit dcda958d8d
2 changed files with 253 additions and 353 deletions

View file

@ -1,123 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.revisioninfo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Parse the response that we got from SVN info.
*
* Not thread-safe.
*/
public class InfoResponseParser {
private static final Pattern URL_PATTERN = Pattern.compile("URL: (\\S+)");
private static final Pattern ROOT_PATTERN = Pattern
.compile("Repository Root: (\\S+)");
private static final String TRUNK_PREFIX = "/trunk";
private static final String TAGS_PREFIX = "/tags/";
private static final String BRANCHES_PREFIX = "/branches/";
private final String infoResponse;
private String path;
public InfoResponseParser(String infoResponse) {
this.infoResponse = infoResponse;
}
public String parse() {
try {
path = figurePath();
if (isTrunkPath()) {
return "trunk";
} else if (isTagPath()) {
return "tag " + getTagName();
} else if (isBranchPath()) {
return "branch " + getBranchName();
} else {
return null;
}
} catch (Exception e) {
System.err.println(e);
return null;
}
}
private String figurePath() throws Exception {
if (infoResponse == null) {
throw new Exception("infoResponse is null.");
}
String url = getUrlFromResponse();
String root = getRootFromResponse();
if (!url.startsWith(root)) {
throw new Exception("url doesn't start with root.");
}
return url.substring(root.length());
}
private String getUrlFromResponse() throws Exception {
return findNonEmptyMatch(URL_PATTERN, 1);
}
private String getRootFromResponse() throws Exception {
return findNonEmptyMatch(ROOT_PATTERN, 1);
}
private String findNonEmptyMatch(Pattern pattern, int groupIndex)
throws Exception {
Matcher matcher = pattern.matcher(infoResponse);
if (!matcher.find()) {
throw new Exception("no match with '" + pattern + "'. Is your Subversion client out of date?");
}
String value = matcher.group(groupIndex);
if ((value == null) || (value.isEmpty())) {
throw new Exception("match with '" + pattern + "' is empty.");
}
return value;
}
private boolean isTrunkPath() {
return path.startsWith(TRUNK_PREFIX);
}
private boolean isTagPath() {
return path.startsWith(TAGS_PREFIX);
}
private String getTagName() {
return getFirstLevel(discardPrefix(path, TAGS_PREFIX));
}
private boolean isBranchPath() {
return path.startsWith(BRANCHES_PREFIX);
}
private String getBranchName() {
return getFirstLevel(discardPrefix(path, BRANCHES_PREFIX));
}
private String discardPrefix(String string, String prefix) {
if (string.length() < prefix.length()) {
return "";
} else {
return string.substring(prefix.length());
}
}
private String getFirstLevel(String string) {
int slashHere = string.indexOf('/');
if (slashHere == -1) {
return string;
} else {
return string.substring(0, slashHere);
}
}
}

View file

@ -1,230 +1,253 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.revisioninfo; package edu.cornell.mannlib.vitro.utilities.revisioninfo;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import edu.cornell.mannlib.vitro.utilities.revisioninfo.ProcessRunner.ProcessException; import edu.cornell.mannlib.vitro.utilities.revisioninfo.ProcessRunner.ProcessException;
/** /**
* Get release and revision information to display on screen. Put this * Get release and revision information to display on screen. Put this
* information into a single line and append it to the specified file. * information into a single line and append it to the specified file.
* *
* Ask Subversion for the information. If Subversion is available, and if this * Ask Git for the information. If Git is available, and if this is a working
* is a working directory, then we can build the info from the responses we get * directory, then we can build the info from the responses we get from
* from "svn info" and "svnversion". * "git describe", "git symbolic-ref" and "git log".
* *
* If that doesn't work, read the information from the "revisionInfo" file in * If that doesn't work, read the information from the "revisionInfo" file in
* the product directory. Presumably, that file was created when the source was * the product directory. Presumably, that file was created when the source was
* exported from Subversion. * exported from Git.
* *
* If that doesn't work either, return something like this: * If that doesn't work either, return something like this:
* "productName ~ unknown ~ unknown" * "productName ~ unknown ~ unknown"
*/ */
public class RevisionInfoBuilder { public class RevisionInfoBuilder {
/** /**
* Indicates a problem with the command-line arguments. * Indicates a problem with the command-line arguments.
*/ */
private static class UsageException extends Exception { private static class UsageException extends Exception {
UsageException(String message) { UsageException(String message) {
super(message); super(message);
} }
} }
/** /**
* An object that holds the revision information and a message about how we * An object that holds the revision information and a message about how we
* obtained it. * obtained it.
*/ */
private static class Results { private static class Results {
final String message; final String message;
final String infoLine; final String infoLine;
Results(String message, String infoLine) { Results(String message, String infoLine) {
this.message = message; this.message = message;
this.infoLine = infoLine; this.infoLine = infoLine;
} }
public String toString() { @Override
return message + ": " + infoLine; public String toString() {
} return message + ": " + infoLine;
} }
}
private static final String SVN_DIRECTORY_NAME = ".svn";
private static final String[] SVNVERSION_COMMAND = { "svnversion", "." }; private static final String GIT_DIRECTORY_NAME = ".git";
private static final String[] SVN_INFO_COMMAND = { "svn", "info" }; private static final String[] GIT_DESCRIBE_COMMAND = { "git", "describe" };
private static final String INFO_LINE_DELIMITER = " ~ "; private static final String[] GIT_SREF_COMMAND = { "git", "symbolic-ref",
private static final String REVISION_INFO_FILENAME = "revisionInfo"; "HEAD" };
private static final String[] GIT_LOG_COMMAND = { "git", "log",
private final String productName; "--pretty=format:%h", "-1" };
private final File productDirectory; private static final String INFO_LINE_DELIMITER = " ~ ";
private final File resultFile; private static final String REVISION_INFO_FILENAME = "revisionInfo";
private Results results; private final String productName;
private final File productDirectory;
public RevisionInfoBuilder(String[] args) throws UsageException { private final File resultFile;
if (args.length != 3) {
throw new UsageException( private Results results;
"RevisionInfoBuilder requires 3 arguments, not "
+ args.length); public RevisionInfoBuilder(String[] args) throws UsageException {
} if (args.length != 3) {
throw new UsageException(
productName = args[0]; "RevisionInfoBuilder requires 3 arguments, not "
productDirectory = new File(args[1]); + args.length);
resultFile = new File(args[2]); }
if (!productDirectory.isDirectory()) { productName = args[0];
throw new UsageException("Directory '" productDirectory = new File(args[1]);
+ productDirectory.getAbsolutePath() + "' does not exist."); resultFile = new File(args[2]);
}
if (!productDirectory.isDirectory()) {
if (!resultFile.getParentFile().exists()) { throw new UsageException("Directory '"
throw new UsageException("Result file '" + productDirectory.getAbsolutePath() + "' does not exist.");
+ resultFile.getAbsolutePath() }
+ "' does not exist, and we can't create it "
+ "because it's parent directory doesn't exist either."); if (!resultFile.getParentFile().exists()) {
} throw new UsageException("Result file '"
} + resultFile.getAbsolutePath()
+ "' does not exist, and we can't create it "
private void buildInfo() { + "because it's parent directory doesn't exist either.");
results = buildInfoFromSubversion(); }
if (results == null) { }
results = buildInfoFromFile();
} private void buildInfo() {
if (results == null) { results = buildInfoFromGit();
results = buildDummyInfo(); if (results == null) {
} results = buildInfoFromFile();
} }
if (results == null) {
private Results buildInfoFromSubversion() { results = buildDummyInfo();
if (!isThisASubversionWorkspace()) { }
System.out.println("Not a Subversion workspace"); }
return null;
} private Results buildInfoFromGit() {
if (!isThisAGitWorkspace()) {
String release = assembleReleaseNameFromSubversion(); System.out.println("Not a git workspace");
if (release == null) { return null;
System.out.println("Couldn't get release name from Subversion"); }
return null;
} String release = assembleReleaseNameFromGit();
if (release == null) {
String revision = obtainRevisionLevelFromSubversion(); System.out.println("Couldn't get release name from Git");
if (revision == null) { }
System.out.println("Couldn't get revision level from Subversion");
return null; String revision = obtainCommitIdFromGit();
} if (revision == null) {
System.out.println("Couldn't get commit ID from Git");
return new Results("Info from Subversion", buildLine(release, revision)); }
}
if ((revision == null) && (release == null)) {
private boolean isThisASubversionWorkspace() { return null;
File svnDirectory = new File(productDirectory, SVN_DIRECTORY_NAME); }
return svnDirectory.isDirectory();
} return new Results("Info from Git", buildLine(release, revision));
}
private String assembleReleaseNameFromSubversion() {
String infoResponse = runSubProcess(SVN_INFO_COMMAND); private boolean isThisAGitWorkspace() {
return new InfoResponseParser(infoResponse).parse(); File gitDirectory = new File(productDirectory, GIT_DIRECTORY_NAME);
} return gitDirectory.isDirectory();
}
private String obtainRevisionLevelFromSubversion() {
String response = runSubProcess(SVNVERSION_COMMAND); private String assembleReleaseNameFromGit() {
return (response == null) ? null : response.trim(); String describeResponse = runSubProcess(GIT_DESCRIBE_COMMAND);
} String srefResponse = runSubProcess(GIT_SREF_COMMAND);
return parseReleaseName(describeResponse, srefResponse);
private String runSubProcess(String[] cmdArray) { }
List<String> command = Arrays.asList(cmdArray);
try { private String obtainCommitIdFromGit() {
ProcessRunner runner = new ProcessRunner(); String logResponse = runSubProcess(GIT_LOG_COMMAND);
runner.setWorkingDirectory(productDirectory); return parseLogResponse(logResponse);
}
runner.run(command);
private String parseReleaseName(String describeResponse, String srefResponse) {
int rc = runner.getReturnCode(); if (describeResponse != null) {
if (rc != 0) { return describeResponse.trim() + " tag";
throw new ProcessRunner.ProcessException("Return code from " } else if (srefResponse != null) {
+ command + " was " + rc); return srefResponse.substring(srefResponse.lastIndexOf('/') + 1)
} .trim() + " branch";
} else {
String output = runner.getStdOut(); return null;
// System.err.println(command + " response was '" + output + "'"); }
return output; }
} catch (ProcessException e) {
return null; private String parseLogResponse(String logResponse) {
} return logResponse;
} }
private Results buildInfoFromFile() { private String runSubProcess(String[] cmdArray) {
try { List<String> command = Arrays.asList(cmdArray);
File revisionInfoFile = new File(productDirectory, try {
REVISION_INFO_FILENAME); ProcessRunner runner = new ProcessRunner();
BufferedReader reader = new BufferedReader(new FileReader( runner.setWorkingDirectory(productDirectory);
revisionInfoFile));
runner.run(command);
String release = reader.readLine();
if (release == null) { int rc = runner.getReturnCode();
throw new EOFException("No release line in file."); if (rc != 0) {
} throw new ProcessRunner.ProcessException("Return code from "
+ command + " was " + rc);
String revision = reader.readLine(); }
if (revision == null) {
throw new EOFException("No revision line in file."); String output = runner.getStdOut();
} // System.err.println(command + " response was '" + output + "'");
return output;
return new Results("Info from file", buildLine(release, revision)); } catch (ProcessException e) {
} catch (IOException e) { // System.out.println(e);
System.out.println("No information from file: " + e); return null;
return null; }
} }
}
private Results buildInfoFromFile() {
private Results buildDummyInfo() { try {
String line = buildLine(null, null); File revisionInfoFile = new File(productDirectory,
return new Results("Using dummy info", line); REVISION_INFO_FILENAME);
} BufferedReader reader = new BufferedReader(new FileReader(
revisionInfoFile));
private String buildLine(String release, String revision) {
if (release == null) { String release = reader.readLine();
release = "unknown"; if (release == null) {
} throw new EOFException("No release line in file.");
if (revision == null) { }
revision = "unknown";
} String revision = reader.readLine();
return productName + INFO_LINE_DELIMITER + release.trim() if (revision == null) {
+ INFO_LINE_DELIMITER + revision.trim(); throw new EOFException("No revision line in file.");
} }
private void writeLine() throws IOException { return new Results("Info from file", buildLine(release, revision));
Writer writer = null; } catch (IOException e) {
writer = new FileWriter(resultFile, true); System.out.println("No information from file: " + e);
writer.write(results.infoLine + "\n"); return null;
writer.close(); }
}
System.out.println(results);
} private Results buildDummyInfo() {
String line = buildLine(null, null);
public static void main(String[] args) { return new Results("Using dummy info", line);
try { }
RevisionInfoBuilder builder = new RevisionInfoBuilder(args);
builder.buildInfo(); private String buildLine(String release, String revision) {
builder.writeLine(); if (release == null) {
} catch (UsageException e) { release = "unknown";
System.err.println(e); }
System.err.println("usage: RevisionInfoBuilder [product_name] " if (revision == null) {
+ "[product_directory] [output_file]"); revision = "unknown";
System.exit(1); }
} catch (Exception e) { return productName + INFO_LINE_DELIMITER + release.trim()
e.printStackTrace(); + INFO_LINE_DELIMITER + revision.trim();
System.exit(1); }
}
} private void writeLine() throws IOException {
Writer writer = null;
} writer = new FileWriter(resultFile, true);
writer.write(results.infoLine + "\n");
writer.close();
System.out.println(results);
}
public static void main(String[] args) {
try {
RevisionInfoBuilder builder = new RevisionInfoBuilder(args);
builder.buildInfo();
builder.writeLine();
} catch (UsageException e) {
System.err.println(e);
System.err.println("usage: RevisionInfoBuilder [product_name] "
+ "[product_directory] [output_file]");
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}