diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/BranchFilterController.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/BranchFilterController.java index 6311a96081b0..b27506cfb533 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/BranchFilterController.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/BranchFilterController.java @@ -20,7 +20,7 @@ import com.intellij.vcs.log.graph.api.elements.GraphElement; import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo; import com.intellij.vcs.log.graph.impl.facade.CascadeController; import com.intellij.vcs.log.graph.impl.facade.LinearGraphController; -import com.intellij.vcs.log.graph.impl.facade.ReachableNodes; +import com.intellij.vcs.log.graph.utils.GraphUtilKt; import com.intellij.vcs.log.graph.utils.UnsignedBitSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,7 +35,7 @@ public class BranchFilterController extends CascadeController { @NotNull PermanentGraphInfo permanentGraphInfo, @Nullable Set idsOfVisibleBranches) { super(delegateLinearGraphController, permanentGraphInfo); - myVisibility = ReachableNodes.getReachableNodes(myPermanentGraphInfo.getLinearGraph(), idsOfVisibleBranches); + myVisibility = GraphUtilKt.getReachableNodes(myPermanentGraphInfo.getLinearGraph(), idsOfVisibleBranches); myCollapsedGraph = update(); } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/CollapsedController.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/CollapsedController.java index cac8f4c1b984..dabf2f2fa6c0 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/CollapsedController.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/CollapsedController.java @@ -24,7 +24,7 @@ import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo; import com.intellij.vcs.log.graph.impl.facade.CascadeController; import com.intellij.vcs.log.graph.impl.facade.GraphChanges; import com.intellij.vcs.log.graph.impl.facade.LinearGraphController; -import com.intellij.vcs.log.graph.impl.facade.ReachableNodes; +import com.intellij.vcs.log.graph.utils.GraphUtilKt; import com.intellij.vcs.log.graph.utils.UnsignedBitSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,7 +38,7 @@ public class CollapsedController extends CascadeController { @NotNull final PermanentGraphInfo permanentGraphInfo, @Nullable Set idsOfVisibleBranches) { super(delegateLinearGraphController, permanentGraphInfo); - UnsignedBitSet initVisibility = ReachableNodes.getReachableNodes(permanentGraphInfo.getLinearGraph(), idsOfVisibleBranches); + UnsignedBitSet initVisibility = GraphUtilKt.getReachableNodes(permanentGraphInfo.getLinearGraph(), idsOfVisibleBranches); myCollapsedGraph = CollapsedGraph.newInstance(getDelegateController().getCompiledGraph(), initVisibility); } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/FilteredController.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/FilteredController.java index b1c452249274..57bf1d0913d3 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/FilteredController.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/FilteredController.java @@ -20,6 +20,7 @@ import com.intellij.vcs.log.graph.api.elements.GraphElement; import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo; import com.intellij.vcs.log.graph.collapsing.CollapsedGraph; import com.intellij.vcs.log.graph.collapsing.DottedFilterEdgesGenerator; +import com.intellij.vcs.log.graph.utils.DfsWalk; import com.intellij.vcs.log.graph.utils.LinearGraphUtils; import com.intellij.vcs.log.graph.utils.UnsignedBitSet; import org.jetbrains.annotations.NotNull; @@ -44,13 +45,13 @@ public class FilteredController extends CascadeController { UnsignedBitSet initVisibility = new UnsignedBitSet(); if (visibleHeadsIds != null) { - ReachableNodes getter = new ReachableNodes(LinearGraphUtils.asLiteLinearGraph(myPermanentGraphInfo.getLinearGraph())); - getter.walkDown(visibleHeadsIds, node -> { + new DfsWalk(visibleHeadsIds, myPermanentGraphInfo.getLinearGraph()).walk(true, node -> { if (matchedIds.contains(node)) initVisibility.set(node, true); + return true; }); } else { - for (Integer matchedId: matchedIds) initVisibility.set(matchedId, true); + for (Integer matchedId : matchedIds) initVisibility.set(matchedId, true); } myCollapsedGraph = CollapsedGraph.newInstance(delegateLinearGraphController.getCompiledGraph(), initVisibility); diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/ReachableNodes.kt b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/ReachableNodes.kt index 32e623edf1c1..c80b31b42400 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/ReachableNodes.kt +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/ReachableNodes.kt @@ -17,14 +17,14 @@ package com.intellij.vcs.log.graph.impl.facade import com.intellij.util.Consumer -import com.intellij.vcs.log.graph.api.LinearGraph import com.intellij.vcs.log.graph.api.LiteLinearGraph -import com.intellij.vcs.log.graph.utils.* +import com.intellij.vcs.log.graph.utils.DfsWalk +import com.intellij.vcs.log.graph.utils.Flags import com.intellij.vcs.log.graph.utils.impl.BitSetFlags import java.util.* class ReachableNodes(private val graph: LiteLinearGraph) { - private val flags: Flags = BitSetFlags(graph.nodesCount()) + private val visited: Flags = BitSetFlags(graph.nodesCount()) fun getContainingBranches(nodeIndex: Int, branchNodeIndexes: Collection): Set { val result = HashSet() @@ -45,46 +45,9 @@ class ReachableNodes(private val graph: LiteLinearGraph) { } fun walk(startNodes: Collection, goDown: Boolean, consumer: (Int) -> Boolean) { - synchronized(flags) { - - flags.setAll(false) - for (start in startNodes) { - if (start < 0) continue - if (flags.get(start)) continue - flags.set(start, true) - if (!consumer(start)) return - - walk(start) nextNode@{ currentNode -> - for (downNode in graph.getNodes(currentNode, if (goDown) LiteLinearGraph.NodeFilter.DOWN else LiteLinearGraph.NodeFilter.UP)) { - if (!flags.get(downNode)) { - flags.set(downNode, true) - if (!consumer(downNode)) return@nextNode Dfs.NextNode.EXIT - return@nextNode downNode - } - } - - Dfs.NextNode.NODE_NOT_FOUND - } - } - } - } - - companion object { - @JvmStatic - fun getReachableNodes(graph: LinearGraph, headNodeIndexes: Set?): UnsignedBitSet { - if (headNodeIndexes == null) { - val nodesVisibility = UnsignedBitSet() - nodesVisibility.set(0, graph.nodesCount() - 1, true) - return nodesVisibility - } - - val result = UnsignedBitSet() - val reachableNodes = ReachableNodes(LinearGraphUtils.asLiteLinearGraph(graph)) - reachableNodes.walk(headNodeIndexes, true) { node: Int -> - result.set(node, true) - true - } - return result + synchronized(visited) { + visited.setAll(false) + DfsWalk(startNodes, graph, visited).walk(goDown, consumer) } } } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/BfsUtil.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/BfsUtil.java deleted file mode 100644 index 451378210d18..000000000000 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/BfsUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.vcs.log.graph.utils; - -import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.graph.api.LiteLinearGraph; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; - -public class BfsUtil { - public static int getCorrespondingParent(@NotNull LiteLinearGraph graph, int startNode, int endNode, @NotNull Flags visited) { - List candidates = graph.getNodes(startNode, LiteLinearGraph.NodeFilter.DOWN); - if (candidates.size() == 1) return candidates.get(0); - if (candidates.contains(endNode)) return endNode; - - List> queues = new ArrayList<>(candidates.size()); - for (int candidate : candidates) { - queues.add(ContainerUtil.newLinkedList(candidate)); - } - - int emptyCount; - visited.setAll(false); - do { - emptyCount = 0; - for (Queue queue : queues) { - if (queue.isEmpty()) { - emptyCount++; - } - else { - boolean found = runNextBfsStep(graph, queue, visited, endNode); - if (found) { - return candidates.get(queues.indexOf(queue)); - } - } - } - } - while (emptyCount < queues.size()); - - return candidates.get(0); - } - - private static boolean runNextBfsStep(@NotNull LiteLinearGraph graph, @NotNull Queue queue, @NotNull Flags visited, int target) { - while (!queue.isEmpty()) { - Integer node = queue.poll(); - if (!visited.get(node)) { - visited.set(node, true); - List next = graph.getNodes(node, LiteLinearGraph.NodeFilter.DOWN); - if (next.contains(target)) return true; - queue.addAll(next); - return false; - } - } - return false; - } -} diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/BfsUtil.kt b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/BfsUtil.kt new file mode 100644 index 000000000000..2a3903ae63d4 --- /dev/null +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/BfsUtil.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log.graph.utils + +import com.intellij.util.containers.ContainerUtil +import com.intellij.vcs.log.graph.api.LiteLinearGraph + +class BfsWalk(val start: Int, private val graph: LiteLinearGraph, private val visited: Flags) { + private val queue = ContainerUtil.newLinkedList(start) + + fun isFinished() = queue.isEmpty() + + fun step(): List { + while (!queue.isEmpty()) { + val node = queue.poll() + if (!visited.get(node)) { + visited.set(node, true) + val next = graph.getNodes(node, LiteLinearGraph.NodeFilter.DOWN) + queue.addAll(next) + return next + } + } + return emptyList() + } + + fun walk() { + while (!isFinished()) { + step() + } + } +} \ No newline at end of file diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/DfsUtil.kt b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/DfsUtil.kt index ec7525bda59a..6f1c517ac54b 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/DfsUtil.kt +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/DfsUtil.kt @@ -16,8 +16,8 @@ package com.intellij.vcs.log.graph.utils -import com.intellij.openapi.util.Ref import com.intellij.util.containers.IntStack +import com.intellij.vcs.log.graph.api.LinearGraph import com.intellij.vcs.log.graph.api.LiteLinearGraph import com.intellij.vcs.log.graph.utils.impl.BitSetFlags @@ -33,6 +33,54 @@ object Dfs { } } +private fun walk(start: Int, stack: IntStack, nextNodeFun: (Int) -> Int) { + stack.push(start) + + while (!stack.empty()) { + val nextNode = nextNodeFun(stack.peek()) + if (nextNode == Dfs.NextNode.EXIT) return + if (nextNode != Dfs.NextNode.NODE_NOT_FOUND) { + stack.push(nextNode) + } + else { + stack.pop() + } + } + stack.clear() +} + +fun walk(start: Int, nextNodeFun: (Int) -> Int) { + walk(start, IntStack(), nextNodeFun) +} + +class DfsWalk(private val startNodes: Collection, private val graph: LiteLinearGraph, private val visited: Flags) { + private val stack = IntStack() + + constructor(startNodes: Collection, linearGraph: LinearGraph) : + this(startNodes, LinearGraphUtils.asLiteLinearGraph(linearGraph), BitSetFlags(linearGraph.nodesCount())) + + fun walk(goDown: Boolean, consumer: (Int) -> Boolean) { + for (start in startNodes) { + if (start < 0) continue + if (visited.get(start)) continue + visited.set(start, true) + if (!consumer(start)) return + + walk(start, stack) nextNode@{ currentNode -> + for (downNode in graph.getNodes(currentNode, if (goDown) LiteLinearGraph.NodeFilter.DOWN else LiteLinearGraph.NodeFilter.UP)) { + if (!visited.get(downNode)) { + visited.set(downNode, true) + if (!consumer(downNode)) return@nextNode Dfs.NextNode.EXIT + return@nextNode downNode + } + } + + Dfs.NextNode.NODE_NOT_FOUND + } + } + } +} + /* * Depth-first walk for a graph. For each node, walks both into upward and downward siblings. * Tries to preserve direction of travel: when a node is entered from up-sibling, goes to the down-siblings first. @@ -87,46 +135,4 @@ private fun isDown(stack: IntStack): Boolean { val previousNode = getPreviousNode(stack) if (previousNode == Dfs.NextNode.NODE_NOT_FOUND) return true return previousNode < currentNode -} - -fun LiteLinearGraph.isAncestor(lowerNode: Int, upperNode: Int): Boolean { - val visited = BitSetFlags(nodesCount(), false) - - val result = Ref.create(false) - walk(lowerNode) { currentNode -> - visited.set(currentNode, true) - - if (currentNode == upperNode) { - result.set(true) - return@walk Dfs.NextNode.EXIT - } - if (currentNode > upperNode) { - for (nextNode in getNodes(currentNode, LiteLinearGraph.NodeFilter.UP)) { - if (!visited.get(nextNode)) { - return@walk nextNode - } - } - } - - Dfs.NextNode.NODE_NOT_FOUND - } - - return result.get() -} - -fun walk(startRowIndex: Int, nextNodeFun: (Int) -> Int) { - val stack = IntStack() - stack.push(startRowIndex) - - while (!stack.empty()) { - val nextNode = nextNodeFun(stack.peek()) - if (nextNode == Dfs.NextNode.EXIT) return - if (nextNode != Dfs.NextNode.NODE_NOT_FOUND) { - stack.push(nextNode) - } - else { - stack.pop() - } - } - stack.clear() -} +} \ No newline at end of file diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/GraphUtil.kt b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/GraphUtil.kt new file mode 100644 index 000000000000..e089eea9294b --- /dev/null +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/GraphUtil.kt @@ -0,0 +1,68 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.vcs.log.graph.utils + +import com.intellij.openapi.util.Ref +import com.intellij.vcs.log.graph.api.LinearGraph +import com.intellij.vcs.log.graph.api.LiteLinearGraph +import com.intellij.vcs.log.graph.utils.impl.BitSetFlags + +fun LinearGraph.getReachableNodes(headNodes: Set?): UnsignedBitSet { + if (headNodes == null) { + val nodesVisibility = UnsignedBitSet() + nodesVisibility.set(0, nodesCount() - 1, true) + return nodesVisibility + } + + val result = UnsignedBitSet() + DfsWalk(headNodes, this).walk(true) { node: Int -> + result.set(node, true) + true + } + return result +} + +fun LiteLinearGraph.isAncestor(lowerNode: Int, upperNode: Int): Boolean { + val visited = BitSetFlags(nodesCount(), false) + + val result = Ref.create(false) + walk(lowerNode) { currentNode -> + visited.set(currentNode, true) + + if (currentNode == upperNode) { + result.set(true) + return@walk Dfs.NextNode.EXIT + } + if (currentNode > upperNode) { + for (nextNode in getNodes(currentNode, LiteLinearGraph.NodeFilter.UP)) { + if (!visited.get(nextNode)) { + return@walk nextNode + } + } + } + + Dfs.NextNode.NODE_NOT_FOUND + } + + return result.get() +} + +fun LiteLinearGraph.getCorrespondingParent(startNode: Int, endNode: Int, visited: Flags): Int { + val candidates = getNodes(startNode, LiteLinearGraph.NodeFilter.DOWN) + if (candidates.size == 1) return candidates[0] + if (candidates.contains(endNode)) return endNode + + val bfsWalks = candidates.mapTo(mutableListOf()) { BfsWalk(it, this, visited) } + + visited.setAll(false) + do { + for (walk in bfsWalks) { + if (walk.step().contains(endNode)) { + return walk.start + } + } + bfsWalks.removeIf { it.isFinished() } + } + while (bfsWalks.isNotEmpty()) + + return candidates[0] +} \ No newline at end of file diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/impl/BitSetFlags.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/impl/BitSetFlags.java index 933a0dbeb4e7..8cb3dc8a645e 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/impl/BitSetFlags.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/utils/impl/BitSetFlags.java @@ -20,6 +20,7 @@ import com.intellij.vcs.log.graph.utils.Flags; import org.jetbrains.annotations.NotNull; import java.util.BitSet; +import java.util.Objects; public class BitSetFlags implements Flags { @@ -65,4 +66,23 @@ public class BitSetFlags implements Flags { if (index < 0) throw new IndexOutOfBoundsException("index is " + index + " which is less then zero"); if (index >= mySize) throw new IndexOutOfBoundsException("index is " + index + " and set size is " + mySize); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BitSetFlags flags = (BitSetFlags)o; + return mySize == flags.mySize && + myBitSet.equals(flags.myBitSet); + } + + @Override + public int hashCode() { + return Objects.hash(mySize, myBitSet); + } + + @Override + public String toString() { + return myBitSet + ", size = " + mySize; + } } diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/impl/BfsTests.kt b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/impl/BfsTests.kt new file mode 100644 index 000000000000..472671da66b8 --- /dev/null +++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/impl/BfsTests.kt @@ -0,0 +1,93 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.vcs.log.graph.impl + +import com.intellij.vcs.log.graph.TestGraphBuilder +import com.intellij.vcs.log.graph.asString +import com.intellij.vcs.log.graph.graph +import com.intellij.vcs.log.graph.utils.BfsWalk +import com.intellij.vcs.log.graph.utils.LinearGraphUtils +import com.intellij.vcs.log.graph.utils.getCorrespondingParent +import com.intellij.vcs.log.graph.utils.impl.BitSetFlags +import org.junit.Test +import kotlin.test.assertEquals + +class BfsTests { + + private fun assertCorrespondingParent(startNode: Int, endNode: Int, expectedParent: Int, graphBuilder: TestGraphBuilder.() -> Unit) { + val graph = graph(graphBuilder) + val actualParent = LinearGraphUtils.asLiteLinearGraph(graph).getCorrespondingParent(startNode, endNode, BitSetFlags(graph.nodesCount())) + assertEquals(expectedParent, actualParent, + "Incorrect parent found when walking from ${startNode} to ${endNode} in ${graph.asString(true)}") + } + + @Test + fun `one parent`() { + assertCorrespondingParent(0, 5, 1) { + 0(1) + 1(2) + 2(3, 4) + 3(5) + 4(5) + 5() + } + } + + @Test + fun `target parent`() { + assertCorrespondingParent(0, 2, 2) { + 0(1, 2) + 1(3) + 2(3) + 3() + } + } + + @Test + fun `merge commit`() { + assertCorrespondingParent(0, 4, 2) { + 0(1, 2) + 1(3) + 2(3, 4) + 3() + 4() + } + } + + @Test + fun `test visited`() { + val graph = graph { + 0(3) + 1(3) + 2(4) + 3(4) + 4(5, 6) + 5(7) + 6(8) + 7() + 8() + } + val nodesCount = graph.nodesCount() + val visited = BitSetFlags(nodesCount) + + BfsWalk(0, LinearGraphUtils.asLiteLinearGraph(graph), visited).walk() + assertEquals(BitSetFlags(nodesCount).setAll(0, 3, 4, 5, 6, 7, 8), visited) + visited.setAll(false) + + BfsWalk(3, LinearGraphUtils.asLiteLinearGraph(graph), visited).walk() + assertEquals(BitSetFlags(nodesCount).setAll(3, 4, 5, 6, 7, 8), visited) + visited.setAll(false) + + BfsWalk(5, LinearGraphUtils.asLiteLinearGraph(graph), visited).walk() + assertEquals(BitSetFlags(nodesCount).setAll(5, 7), visited) + visited.setAll(false) + + BfsWalk(8, LinearGraphUtils.asLiteLinearGraph(graph), visited).walk() + assertEquals(BitSetFlags(nodesCount).setAll(8), visited) + visited.setAll(false) + } + + private fun BitSetFlags.setAll(vararg values: Int): BitSetFlags { + values.forEach { this[it] = true } + return this + } +} \ No newline at end of file diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistory.kt b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistory.kt index 60b1405add61..4aaf3df4f1d5 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistory.kt +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistory.kt @@ -19,12 +19,8 @@ import com.intellij.vcs.log.graph.api.permanent.PermanentCommitsInfo import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo import com.intellij.vcs.log.graph.collapsing.CollapsedGraph import com.intellij.vcs.log.graph.impl.facade.* -import com.intellij.vcs.log.graph.utils.BfsUtil.getCorrespondingParent -import com.intellij.vcs.log.graph.utils.Dfs -import com.intellij.vcs.log.graph.utils.LinearGraphUtils +import com.intellij.vcs.log.graph.utils.* import com.intellij.vcs.log.graph.utils.impl.BitSetFlags -import com.intellij.vcs.log.graph.utils.isAncestor -import com.intellij.vcs.log.graph.utils.walk import gnu.trove.* import java.util.* import java.util.function.BiConsumer @@ -202,7 +198,7 @@ internal class FileHistoryRefiner(private val visibleLinearGraph: LinearGraph, namesData.getPathInParentRevision(previousCommit, permanentCommitsInfo.getCommitId(parentIndex), previousPath.filePath) } val path = findPathWithoutConflict(previousNodeId, pathGetter) - path ?: pathGetter(getCorrespondingParent(permanentLinearGraph, previousNodeId, currentNodeId, visibilityBuffer)) + path ?: pathGetter(permanentLinearGraph.getCorrespondingParent(previousNodeId, currentNodeId, visibilityBuffer)) } else { val pathGetter = { parentIndex: Int -> @@ -210,7 +206,7 @@ internal class FileHistoryRefiner(private val visibleLinearGraph: LinearGraph, } val path = findPathWithoutConflict(currentNodeId, pathGetter) // since in reality there is no edge between the nodes, but the whole path, we need to know, which parent is affected by this path - path ?: pathGetter(getCorrespondingParent(permanentLinearGraph, currentNodeId, previousNodeId, visibilityBuffer)) + path ?: pathGetter(permanentLinearGraph.getCorrespondingParent(currentNodeId, previousNodeId, visibilityBuffer)) } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/ReachableNodesUtil.kt b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/ReachableNodesUtil.kt index 41dde0bbd782..16d4105ad1d0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/ReachableNodesUtil.kt +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/ReachableNodesUtil.kt @@ -5,16 +5,14 @@ import com.intellij.openapi.util.Ref import com.intellij.vcs.log.data.DataPack import com.intellij.vcs.log.graph.api.LinearGraph import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo -import com.intellij.vcs.log.graph.impl.facade.ReachableNodes import com.intellij.vcs.log.graph.impl.facade.VisibleGraphImpl -import com.intellij.vcs.log.graph.utils.LinearGraphUtils +import com.intellij.vcs.log.graph.utils.DfsWalk import com.intellij.vcs.log.visible.VisiblePack fun LinearGraph.findAncestorNode(startNodeId: Int, condition: (Int) -> Boolean): Int? { val resultNodeId = Ref() - val reachableNodes = ReachableNodes(LinearGraphUtils.asLiteLinearGraph(this)) - reachableNodes.walk(setOf(startNodeId), true) { currentNodeId -> + DfsWalk(setOf(startNodeId), this).walk(true) { currentNodeId: Int -> if (condition(currentNodeId)) { resultNodeId.set(currentNodeId) false // stop walk, we have found it