JGit:RevWalk 顺序覆盖起点
JGit: RevWalk order overriding starting point
我正在将 JGit 用于我的一个项目,该项目涉及大量使用 git。
我的目标是使用 RevWalk
能够按时间顺序迭代存储库中的提交,从特定提交开始。我已经设法分别实现了它们:
- 应用
RevSort.REVERSE
的时间顺序
- 调用起点
RevWalk.markStart(RevCommit c)
我的问题是,当我尝试将两者结合时,似乎 RevSort 覆盖了 markStart,并且 RevWalk 总是在我指定的提交的提交开始时结束。
这段代码展示了我所得到的:
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,按时间顺序排列。我希望能够使用 markStart
和 sort
通过以下方式实现:
@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());
这与我想要获得的相反。
这是有意为之的行为吗?如果是,我还能用什么其他方式解决这个问题?
JGit API 没有给出组合 sort 和 markStart 的禁忌症。 JGit 源代码也没有显示任何表面问题。在我看来,直接解决这个问题需要源代码级调试。您将需要 JGit 源代码并需要 运行 在调试器中运行您的示例。
或者,您可以使用没有排序的 Spliterator 将 RevWalk 流式传输到 RevCommit:getCommitTime() 上比较的排序输出,如下所示:
StreamSupport.stream(walk.spliterator())
.sorted(RevCommit::getCommitTime())
.toList();
在 Git 中,提交只有指向其 parent(s) 的链接。 commitB
不知道其继任者 commitC
和 commitD
。
因此历史只能向后遍历,从给定的提交到它的parent、grand-pareents等。没有要遍历的信息相反的方向。
在您的示例中,RevWalk
将从 commitB
走到 commitÀ
。 REVERSE
排序只会影响迭代器的行为方式,但不能 forward.
如果您真的想查找 commitB
和 HEAD
之间的提交,您需要从 HEAD
开始。或者,更一般地说,您需要从所有已知的分支提示开始,找到可能导致 commitB
.
的多条路径
我正在将 JGit 用于我的一个项目,该项目涉及大量使用 git。
我的目标是使用 RevWalk
能够按时间顺序迭代存储库中的提交,从特定提交开始。我已经设法分别实现了它们:
- 应用
RevSort.REVERSE
的时间顺序
- 调用起点
RevWalk.markStart(RevCommit c)
我的问题是,当我尝试将两者结合时,似乎 RevSort 覆盖了 markStart,并且 RevWalk 总是在我指定的提交的提交开始时结束。
这段代码展示了我所得到的:
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,按时间顺序排列。我希望能够使用 markStart
和 sort
通过以下方式实现:
@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());
这与我想要获得的相反。 这是有意为之的行为吗?如果是,我还能用什么其他方式解决这个问题?
JGit API 没有给出组合 sort 和 markStart 的禁忌症。 JGit 源代码也没有显示任何表面问题。在我看来,直接解决这个问题需要源代码级调试。您将需要 JGit 源代码并需要 运行 在调试器中运行您的示例。
或者,您可以使用没有排序的 Spliterator 将 RevWalk 流式传输到 RevCommit:getCommitTime() 上比较的排序输出,如下所示:
StreamSupport.stream(walk.spliterator())
.sorted(RevCommit::getCommitTime())
.toList();
在 Git 中,提交只有指向其 parent(s) 的链接。 commitB
不知道其继任者 commitC
和 commitD
。
因此历史只能向后遍历,从给定的提交到它的parent、grand-pareents等。没有要遍历的信息相反的方向。
在您的示例中,RevWalk
将从 commitB
走到 commitÀ
。 REVERSE
排序只会影响迭代器的行为方式,但不能 forward.
如果您真的想查找 commitB
和 HEAD
之间的提交,您需要从 HEAD
开始。或者,更一般地说,您需要从所有已知的分支提示开始,找到可能导致 commitB
.