我尝试使用 Process Builder 来执行 git 命令。 但它似乎对任何命令都不起作用。
git log
给我正确的结果。
git shortlog -s
但以超时结束!
在终端中运行的两个命令都提供了正确的结果! 我已经在 Win 和 Mac 上测试过了。
有谁知道我该如何调试它,或者我的错误在哪里?
或者也许是不同的解决方案? 目的是将提交者读出到 git 存储库中的特定文件。
事实上 Git 命令是 git shortlog -s -p FeilePath
?
我的测试代码:
@Test
public void testCommandListDir() {
File execDir = new File("./");
String returnValue = "";
try {
returnValue = runCommand(execDir, 10, TimeUnit.SECONDS, "git", "log");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
assertTrue(returnValue.contains("+ try and error for git shortlog"));
}
@Test
public void testCommandGitShortlog() {
File execDir = new File("./");
String returnValue = "";
try {
returnValue = runCommand(execDir, 10, TimeUnit.SECONDS, "git", "shortlog", "-s");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
assertTrue(returnValue.equals(""));
}
public static String runCommand(File directory, long timeout, TimeUnit unit, String... command) throws IOException, InterruptedException {
StringBuilder sb = new StringBuilder();
ProcessBuilder pb = new ProcessBuilder(command)
.redirectErrorStream(true).directory(directory);
Process p = pb.start();
InputStream is = p.getInputStream();
InputStream es = p.getErrorStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
BufferedReader bre = new BufferedReader(new InputStreamReader(es));
String in;
boolean timeOut = false;
if (!p.waitFor(timeout, unit)) {
//timeout - kill the process.
p.destroy(); // consider using destroyForcibly instead
timeOut = true;
}
if (timeOut) {
//write time out msg
sb.append("RunCommand time out! after " + timeout + " " + unit.toString() + "\n");
sb.append(" directory: " + directory.getAbsolutePath() + "\n");
sb.append(" command: " + command + "\n");
} else {
while ((in = br.readLine()) != null) {
sb.append(in + "\n");
}
while ((in = bre.readLine()) != null) {
sb.append(in + "\n");
}
}
return sb.toString();
}
最佳答案
如果我没理解错的话,你正在尝试你的目标是git blame <filepath>
.
我建议使用 Git API for Java (JGit)。在这个cookbook ,有几个关于如何开始的例子。
更具体地说,您可以在给定的提交中归咎于给定的文件,如下所示:
private BlameResult blameCommit(String path, RevCommit commitToBlame) throws GitAPIException {
BlameCommand blamer = new BlameCommand(<yourRepository>);
ObjectId commitToBlameID = commitToBlame.getId();
blamer.setStartCommit(commitToBlameID);
blamer.setFilePath(path);
return blamer.call();
}
...或者在给定的时间范围内递归,像这样:
public List<Blame> recuriveBlame(String path, RevCommit beginRevision, RevCommit endRevision) throws IOException, GitAPIException {
if (path == null
|| beginRevision == null
|| endRevision == null) {
return null;
}
List<Blame> result = new ArrayList<Blame>();
try (RevWalk rw = new RevWalk(this.repo)) {
rw.markStart(rw.parseCommit(this.beginRevision));
rw.markUninteresting(rw.parseCommit(this.endRevision));
for (RevCommit curr; (curr = rw.next()) != null;){
result.add(new Blame(curr, blameCommit(path, curr)));
}
}
return result;
}
... 并获取给定提交中给定文件的给定行的提交者,例如 this :
public void printCommitter(Repository repo, ObjectID commitID, String filename){
int lines = countFiles(repos, commitID, filename);
for (int i = 0; i < lines; i++) {
PersonIdent committer = blame.getSourceCommitter(i);
System.out.println("Committer of the line: " + i + ": " + committer.getName());
}
}
ps:请注意,您可能需要进行小的更改才能运行此代码。例如,countFiles(...)
是here .
https://stackoverflow.com/questions/33296443/