如何定义一个 "In between" JGit RevFilter?

How to define a "In between" JGit RevFilter?

我正在尝试实现一个 RevFilter 以通过 RevWalk#setRevFilter() 使用。以下是我尝试过的内容:

private class InBetweenRevFilter extends RevFilter {

    private AnyObjectId end;
    private AnyObjectId begin;

    public InBetweenRevFilter(AnyObjectId begin, AnyObjectId end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    public RevFilter clone() {
        return this;
    }

    @Override
    public boolean include(RevWalk walker, RevCommit c)
            throws StopWalkException, MissingObjectException,
            IncorrectObjectTypeException, IOException {
        RevCommit from = walker.parseCommit(begin);
        RevCommit to = walker.parseCommit(end);
        return (walker.isMergedInto(from, c) && walker.isMergedInto(c, to));
    }
}

过滤器的结果应该是在 begin 之后和 end 之前推送的提交。问题是,当我设置此过滤器时,RevWalk.next() 仅返回标记为 RevWalk.markStart(RevCommit c) 起点的提交。在下文中,我展示了我是如何尝试使用过滤器的:

    RevWalk walk = new RevWalk(getRepository());
    RevCommit beginCommit = walk.parseCommit(getRepository().resolve(start));
    RevCommit endCommit = walk.parseCommit(getRepository().resolve(end));
    walk.setRevFilter(new InBetweenRevFilter(beginCommit.getId(), endCommit.getId()));
    walk.markStart(endCommit);
    for (RevCommit rev : walk) {
        System.out.println(rev.getFullMessage());
    }
    walk.close();

在本例中,只有来自 endCommit 的消息打印在控制台中。还有其他方法吗?或者,我错过了什么或做错了什么?

我刚刚在 jgit-cookbook 上发布了一个片段,展示了一种方法:

基本上,您可以从一个提交开始遍历,然后 运行 遍历直到找到第二个或分支上的提交 运行。

请注意,您在这里及时倒退,因为这是 Git 存储提交之间链接的方式,即我们从 "to" 开始,这是较新的提交,一直走到 [=19] =].

        String from = "3408efc41a51555d488d30d8a91ea560c5e13311";
        String to = "7228de6ebe2a3087118562414061af4e189624c0";

        // a RevWalk allows to walk over commits based on some filtering that is defined
        try (RevWalk walk = new RevWalk(repository)) {
            RevCommit commit = walk.parseCommit(repository.resolve(to));

            System.out.println("Walking all commits starting at " + to + " until we find " + from);
            walk.markStart(commit);
            int count = 0;
            for (RevCommit rev : walk) {
                System.out.println("Commit: " + rev);
                count++;

                if(rev.getId().getName().equals(from)) {
                    System.out.println("Found from, stopping walk");
                    break;
                }
            }
            System.out.println(count);

            walk.dispose();
        }

这是我的解决方案,但@centic 的解决方案似乎更简单。

public List<RevCommit> between(String start, String end) throws Exception {
    RevWalk walk = new RevWalk(getRepository());
    RevCommit beginCommit = walk.parseCommit(getRepository().resolve(start));
    RevCommit endCommit = walk.parseCommit(getRepository().resolve(end));
    walk.close();
    return commitsBetween(beginCommit, endCommit);
}

private List<RevCommit> commitsBetween(RevCommit begin, RevCommit end) throws Exception {
    List<RevCommit> commits = new LinkedList<>();
    RevWalk walk = new RevWalk(getRepository());
    RevCommit parent = walk.parseCommit(end.getParent(0).getId());

    if (parent.getName().equals(begin.getName())) {
        commits.add(end);
        walk.close();
        return commits;
    } else {
        commits.add(end);
        commits.addAll(commitsBetween(begin, parent));
        walk.close();
        return commits;
    }
}

更新: 我在 EGit/JGit 论坛中得到了这个 answer,它和@centic 的回答一样简单。

RevCommit begin = getBeginCommit();
RevCommit end = getEndCommit();

try (RevWalk rw = new RevWalk(getRepository())) {
    rw.markStart(rw.lookupCommit(begin));
    rw.markUninteresting(rw.lookupCommit(end));
    for (RevCommit curr; (curr = rw.next()) != null;)
        System.out.println("Inspecting entry: " + curr.getShortMessage());
}