JGit:RevWalk命令重写起点

时间:2015-08-05 20:13:59

标签: java jgit

我正在使用JGit进行涉及git的广泛使用的项目。

我的目标是使用RevWalk能够按时间顺序迭代存储库中的提交,从特定的提交开始。我已经成功地实现了这两个目标:

  • 应用RevSort.REVERSE
  • 按时间顺序排列
  • 致电RevWalk.markStart(RevCommit c)
  • 的起点

我的问题是,当我尝试将两者结合起来时,似乎RevSort会覆盖markStart,并且RevWalk总是从我已经指定的提交的提交开始处开始。< / p>

这段代码展示了我的所作所为:

import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;

import java.io.IOException;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.MissingObjectException;

public class Main {

    public static void main(String[] args) throws IOException, AmbiguousObjectException, MissingObjectException {
        final String repositoryPath = args[0];
        final String commitID = args[1];
        final Repository repository = new FileRepository(repositoryPath + "/.git");
        final RevWalk walk = new RevWalk(repository);
        walk.sort(RevSort.REVERSE);
        walk.markStart(walk.parseCommit(repository.resolve(commitID)));
        for (final RevCommit revCommit : walk) {
            System.err.println(revCommit.getId());
        }
    }

}

这应该从指定的提交开始以相反的顺序打印存储库的ID,但它只是忽略第二个设置并从初始提交开始。

更新:

我已经对问题进行了更多调查,结果表明,当将两个选项一起应用时(按任意顺序),markStart变为markStop。我认为这是由markStart始终首先执行并限制提交范围(使用过滤器),然后由RevSort反转。基本上,RevWalk正在迭代我感兴趣的补充提交集。

我是否应该假设我尝试做的事情不能以这种方式获得?在没有遍历整个存储库到达我的起点的情况下,我无法想到另一种方法来获取它,但这听起来非常低效。

更新2: 这里给出一个恰当的例子是我期望实现的目标。 假设我们有一个包含4个提交的存储库:A,B,C和D. 我只是按照时间顺序对B中对当前版本的评论感兴趣,不包括A.我希望能够使用markStartsort以下列方式实现这一目标:

@Test
public void testReverse2() throws Exception {
    final RevCommit commitA = this.git.commit().setMessage("Commit A").call();
    final RevCommit commitB = this.git.commit().setMessage("Commit B").call();
    final RevCommit commitC = this.git.commit().setMessage("Commit C").call();
    final RevCommit commitD = this.git.commit().setMessage("Commit D").call();

    final RevWalk revWalk = new RevWalk(this.git.getRepository());
    revWalk.markStart(revWalk.parseCommit(commitB));
    revWalk.sort(RevSort.REVERSE);

    assertEquals(commitB, revWalk.next());
    assertEquals(commitC, revWalk.next());
    assertEquals(commitD, revWalk.next());
    assertNull(revWalk.next());
    revWalk.close();
}

现在,从我所看到的情况来看,这并不起作用,因为markStart总是在sort之前执行,所以实际行为满足以下测试:

assertEquals(commitA, revWalk.next());
assertEquals(commitB, revWalk.next());
assertNull(revWalk.next());

这与我试图获得的相反。 这是一种有意的行为,如果是这样,我可以用其他方式解决问题吗?

2 个答案:

答案 0 :(得分:1)

在Git中,提交只有父母的链接。 commitB不知道其后继者commitCcommitD

因此,历史记录只能遍历向后,从给定的提交到其父级,宏大的事务等等。没有信息可以在相反的方向上遍历。

在您的示例中,RevWalk将从commitB走到commitÀREVERSE排序只会影响迭代器的行为方式但不能前进

如果您确实想要查找commitBHEAD之间的提交,则需要从HEAD开始。或者,更一般地说,您需要从所有已知的分支提示开始,以找到可能导致commitB的多个路径。

答案 1 :(得分:0)

JGit API没有提供组合sort和markStart的禁忌症。 JGit源代码也没有显示表面问题。在我看来,直接修复它需要源级调试。您需要JGit源代码并需要在调试器中运行您的示例。

或者,您可以使用Spliterator对RevWalk进行流式处理,而无需按照RevCommit:getCommitTime()对排序输出进行比较,如下所示:

StreamSupport.stream(walk.spliterator())
    .sorted(RevCommit::getCommitTime())
    .toList();