From 7a88ce07abcf707c05aabaa35dd87caff76dae69 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Tue, 10 Jul 2018 21:08:50 +0300 Subject: [PATCH] [vcs-log] avoid walking graph with cycles indefinitely Commit graphs can have cycles in them due to grafts usage. During walking such graphs entering the same commits twice needs to be avoided. In order to do so, after a commit was pushed to the stack, it is removed from newCommitsMap that acts as a pool of not processed commits. IDEA-195247 --- .../src/com/intellij/vcs/log/data/VcsLogJoiner.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java index f1b1fd5bec1d..b463cae2c059 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java @@ -23,6 +23,9 @@ import org.jetbrains.annotations.NotNull; import java.util.*; +import static com.intellij.util.ObjectUtils.notNull; +import static com.intellij.util.containers.ContainerUtil.getFirstItem; + /** * Attaches the block of latest commits, which was read from the VCS, to the existing log structure. * @@ -202,14 +205,14 @@ public class VcsLogJoiner> { private void insertAllUseStack() { while (!newCommitsMap.isEmpty()) { - commitsStack.push(newCommitsMap.values().iterator().next()); + visitCommit(notNull(getFirstItem(newCommitsMap.values()))); while (!commitsStack.isEmpty()) { Commit currentCommit = commitsStack.peek(); boolean allParentsWereAdded = true; for (CommitId parentHash : currentCommit.getParents()) { Commit parentCommit = newCommitsMap.get(parentHash); if (parentCommit != null) { - commitsStack.push(parentCommit); + visitCommit(parentCommit); allParentsWereAdded = false; break; } @@ -232,12 +235,16 @@ public class VcsLogJoiner> { } list.add(insertIndex, currentCommit); - newCommitsMap.remove(currentCommit.getId()); commitsStack.pop(); } } } + private void visitCommit(@NotNull Commit commit) { + commitsStack.push(commit); + newCommitsMap.remove(commit.getId()); + } + @NotNull public List getResultList() { insertAllUseStack();