Я пытаюсь реализовать 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.markStart(RevCommit c), возвращается RevWalk.next(). Далее я покажу, как я пытался использовать фильтр:

    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. Есть ли другой способ сделать это? Или что я упустил или сделал не так?

1
Alcemir Santos 20 Апр 2016 в 01:05

2 ответа

Лучший ответ

Это было мое решение, но вариант @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, что так же просто, как ответ @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());
}
0
Alcemir Santos 22 Апр 2016 в 13:51

Я только что опубликовал фрагмент на jgit-cookbook, в котором показан один из способов сделать это:

Обычно вы можете начать обход с одной фиксации и запускать ее, пока не найдете второй или пока не закончатся коммиты в ветке.

Обратите внимание, что здесь вы перемещаетесь назад во времени, так как Git сохраняет связи между коммитами, т.е. мы начинаем с «to», что является более новым коммитом, и идем, пока не дойдем до «from».

        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();
        }
2
centic 20 Апр 2016 в 17:54