package org.tmatesoft.svn.core.test;
import org.tmatesoft.svn.cli.SVNCommandLine;
import org.tmatesoft.svn.cli.svn.SVN;
import org.tmatesoft.svn.core.SVNException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PythonTestsGitCommitInfo {
static {
registerOptionsWorkaround();
}
private static Pattern WORKING_COPY_PATH_PATTERN = Pattern.compile(".*/working_copies/((\\w|-|\\.)+)($|\\s|/).*");
private static Pattern COMMIT_MESSAGE_PATTERN = Pattern.compile("(\\w+)( -m '.*')? (\\w+)( -m '.*')? .*/(\\w+)_tests-(\\d+).*");
public static PythonTestsGitCommitInfo loadFromCommit(GitRepositoryAccess gitRepositoryAccess, GitObjectId commitId) throws SVNException {
PythonTestsGitCommitInfo commitInfo = new PythonTestsGitCommitInfo(gitRepositoryAccess, commitId);
commitInfo.load();
return commitInfo;
}
private final GitRepositoryAccess gitRepositoryAccess;
private final GitObjectId commitId;
private String commitMessage;
private String canonicalizedCommitMessage;
private String command;
private String subcommand;
private String testCase;
private int testNumber;
private String workingCopyName;
private PythonTestsGitCommitInfo(GitRepositoryAccess gitRepositoryAccess, GitObjectId commitId) {
this.gitRepositoryAccess = gitRepositoryAccess;
this.commitId = commitId;
}
private void load() throws SVNException {
this.commitMessage = gitRepositoryAccess.getCommitMessage(commitId);
this.canonicalizedCommitMessage = canonicalizeCommitMessage(commitMessage);
final Matcher matcher = COMMIT_MESSAGE_PATTERN.matcher(commitMessage);
if (matcher.matches()) {
this.command = matcher.group(1);
this.subcommand = matcher.group(3);
this.testCase = matcher.group(5);
try {
this.testNumber = Integer.parseInt(matcher.group(6));
} catch (NumberFormatException e) {
this.testNumber = -1;
}
} else {
this.command = null;
this.subcommand = null;
this.testCase = null;
this.testNumber = -1;
}
this.workingCopyName = detectWorkingCopyDirectory(commitMessage);
}
public GitObjectId getCommitId() {
return commitId;
}
public String getCommitMessage() {
return commitMessage;
}
public String getCanonicalizedCommitMessage() {
return canonicalizedCommitMessage;
}
public String getCommand() {
return command;
}
public String getSubcommand() {
return subcommand;
}
public String getTestCase() {
return testCase;
}
public int getTestNumber() {
return testNumber;
}
public String getWorkingCopyName() {
return workingCopyName;
}
private String canonicalizeCommitMessage(String commitMessage) {
return commitMessage.replaceAll("/localhost:\\d+/", "/localhost/");
}
private String detectWorkingCopyDirectory(String commitMessage) throws SVNException {
//remove not-yet-supported options
commitMessage = commitMessage.replace("--ignore-uuid", "");
commitMessage = commitMessage.replace("--bdb-txn-nosync", "");
commitMessage = commitMessage.replace("--copy-info", "");
commitMessage = commitMessage.replace("--force-uuid", "");
try {
final SVNCommandLine commandLine = new SVNCommandLine();
commandLine.init(splitIntoArguments(commitMessage));
final Collection arguments = commandLine.getArguments();
final Iterator argumentsIterator = arguments.iterator();
final String commandName = argumentsIterator.hasNext() ? (String) argumentsIterator.next() : null;
while (argumentsIterator.hasNext()) {
final String argument = (String) argumentsIterator.next();
final Matcher matcher = WORKING_COPY_PATH_PATTERN.matcher(argument);
if (matcher.matches()) {
// System.out.println(commitId + " Working copy pattern matching " + argument);
return matcher.group(1);
} else {
// System.out.println(commitId + " Doesn't match " + argument + "(" + commitMessage + ")");
}
} }
catch (Throwable th) {
System.out.println("Bad commmit message " + commitMessage);
throw new RuntimeException(th);
}
return null;
}
private static String[] splitIntoArguments(String commitMessage) {
final List<String> arguments = new ArrayList<String>();
StringBuilder argumentBuilder = new StringBuilder();
Character currentQuoteCharacter = null;
for (int i = 0; i < commitMessage.length(); i++) {
final char c = commitMessage.charAt(i);
switch (c) {
case '\"':
case '\'':
if (currentQuoteCharacter == null) {
currentQuoteCharacter = c;
} else if (currentQuoteCharacter == c) {
currentQuoteCharacter = null;
} else {
argumentBuilder.append(c);
}
break;
case ' ':
case '\t':
if (currentQuoteCharacter == null) {
if (argumentBuilder.length() > 0) {
arguments.add(argumentBuilder.toString());
argumentBuilder = new StringBuilder();
}
} else {
argumentBuilder.append(c);
}
break;
default:
argumentBuilder.append(c);
break;
}
}
if (argumentBuilder.length() > 0) {
arguments.add(argumentBuilder.toString());
}
return arguments.toArray(new String[]{});
}
private static void registerOptionsWorkaround() {
//TODO: in perfect world registerOptions() method should be static
new SVN(){
@Override
protected void registerOptions() {
super.registerOptions();
}
}.registerOptions();
}
}