使用GIT命令的ProcessBuilder未给出结果

wgx48brx  于 2023-05-12  发布在  Git
关注(0)|答案(2)|浏览(94)

我尝试使用Process Builder执行git命令。但它似乎没有工作的任何命令。
git log给出了正确的结果。
git shortlog -s但以超时结束!
在终端中运行的两个命令都提供了正确的结果!我在Mac和Win上测试过。
有没有人知道我该如何调试它,或者我的错误在哪里?
或者是另一种解决方案?目的是读取提交者到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();
    }
au9on6nz

au9on6nz1#

如果我理解正确的话,你的目标是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

w7t8yxp5

w7t8yxp52#

git shortlog的问题来自手册页(https://git-scm.com/docs/git-shortlog
如果命令行上没有传递任何修订,并且标准输入不是终端或者没有当前分支,git shortlog将输出从标准输入读取的日志摘要,而不引用当前仓库。
命令git shortlog -s -p FeilePath不包含修订范围,因此git将尝试从其stdin读取,而java程序没有提供任何内容可供读取。
在我正在做的类似的事情中,包括HEAD--all--branches main都可以工作,我假设任何有效的修订范围都可以。

相关问题