diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/CascadeController.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/CascadeController.java index 681aa4f2618f..9067c3a4b26a 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/CascadeController.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/CascadeController.java @@ -15,6 +15,7 @@ */ package com.intellij.vcs.log.graph.impl.facade; +import com.intellij.util.Function; 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.print.elements.PrintElementWithGraphElement; @@ -44,6 +45,20 @@ public abstract class CascadeController implements LinearGraphController { return LinearGraphUtils.DEFAULT_GRAPH_ANSWER; } + @Nullable + GraphChanges performAction(@NotNull Function> action) { + GraphChanges graphChanges = action.fun(this); + if (graphChanges != null) return graphChanges; + + if (myDelegateController instanceof CascadeController) { + GraphChanges result = ((CascadeController)myDelegateController).performAction(action); + if (result != null) { + return delegateGraphChanged(new LinearGraphController.LinearGraphAnswer(result)).getGraphChanges(); + } + } + return null; + } + @Nullable private PrintElementWithGraphElement convertToDelegate(@Nullable PrintElementWithGraphElement element) { if (element == null) return null; 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 b89a4e4a7443..c772d4c22c79 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 @@ -75,4 +75,9 @@ public class FilteredController extends CascadeController { public LinearGraph getCompiledGraph() { return myCollapsedGraph.getCompiledGraph(); } + + @NotNull + public CollapsedGraph getCollapsedGraph() { + return myCollapsedGraph; + } } diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/GraphModificationUtil.kt b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/GraphModificationUtil.kt new file mode 100644 index 000000000000..a82abbca8809 --- /dev/null +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/GraphModificationUtil.kt @@ -0,0 +1,24 @@ +// 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.facade + +import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo +import com.intellij.vcs.log.graph.collapsing.DottedFilterEdgesGenerator + +fun hideInplace(graphController: LinearGraphController, + permanentGraphInfo: PermanentGraphInfo, + toHide: Set): Boolean { + if (graphController is CascadeController) { + val result = graphController.performAction action@{ cc -> + if (cc is FilteredController) { + val rowsToHide = permanentGraphInfo.permanentCommitsInfo.convertToNodeIds(toHide).mapNotNullTo(mutableSetOf()) { + cc.compiledGraph.getNodeIndex(it) + } + DottedFilterEdgesGenerator.hideInplace(cc.collapsedGraph, rowsToHide) + return@action GraphChangesUtil.SOME_CHANGES + } + return@action null + } + return result != null + } + return false +} \ No newline at end of file diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/PermanentGraphImpl.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/PermanentGraphImpl.java index 506402de71ef..ec2097097795 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/PermanentGraphImpl.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/PermanentGraphImpl.java @@ -39,6 +39,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiConsumer; public class PermanentGraphImpl implements PermanentGraph, PermanentGraphInfo { @NotNull private final PermanentCommitsInfoImpl myPermanentCommitsInfo; @@ -133,13 +134,23 @@ public class PermanentGraphImpl implements PermanentGraph, P return new CollapsedController(baseController, this, null); } + @NotNull + public VisibleGraph createVisibleGraph(@NotNull SortType sortType, + @Nullable Set visibleHeads, + @Nullable Set matchingCommits, + @NotNull BiConsumer> preprocessor) { + LinearGraphController controller = createFilteredController(createBaseController(sortType), sortType, visibleHeads, matchingCommits); + preprocessor.accept(controller, this); + return new VisibleGraphImpl<>(controller, this, myGraphColorManager); + } + @NotNull @Override public VisibleGraph createVisibleGraph(@NotNull SortType sortType, @Nullable Set visibleHeads, @Nullable Set matchingCommits) { - LinearGraphController controller = createFilteredController(createBaseController(sortType), sortType, visibleHeads, matchingCommits); - return new VisibleGraphImpl<>(controller, this, myGraphColorManager); + return createVisibleGraph(sortType, visibleHeads, matchingCommits, (controller, info) -> { + }); } @NotNull diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/VisibleGraphImpl.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/VisibleGraphImpl.java index a8d09a84a36a..c892dd7959a3 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/VisibleGraphImpl.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/VisibleGraphImpl.java @@ -86,7 +86,12 @@ public class VisibleGraphImpl implements VisibleGraph { return new ActionControllerImpl(); } - private void updatePrintElementGenerator() { + @NotNull + public LinearGraphController getGraphController() { + return myGraphController; + } + + void updatePrintElementGenerator() { myPrintElementManager = new PrintElementManagerImpl(myGraphController.getCompiledGraph(), myPermanentGraph, myColorManager); myPrintElementGenerator = new PrintElementGeneratorImpl(myGraphController.getCompiledGraph(), myPrintElementManager, myShowLongEdges); } 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 e00286c69dd7..593959438952 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 @@ -54,7 +54,7 @@ internal class FileHistoryRefiner(private val visibleLinearGraph: LinearGraph, private val paths = Stack() private val visibilityBuffer = BitSetFlags(permanentLinearGraph.nodesCount()) // a reusable buffer for bfs val pathsForCommits = ContainerUtil.newHashMap() - private val excluded = ContainerUtil.newHashSet() + val excluded = ContainerUtil.newHashSet() fun refine(row: Int, startPath: FilePath): Boolean { if (namesData.hasRenames) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt index 2cd695cc0661..cb575f21b92e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/history/FileHistoryFilterer.kt @@ -33,8 +33,9 @@ import com.intellij.vcs.log.graph.GraphCommitImpl import com.intellij.vcs.log.graph.PermanentGraph import com.intellij.vcs.log.graph.VisibleGraph import com.intellij.vcs.log.graph.api.LiteLinearGraph -import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo +import com.intellij.vcs.log.graph.impl.facade.PermanentGraphImpl import com.intellij.vcs.log.graph.impl.facade.VisibleGraphImpl +import com.intellij.vcs.log.graph.impl.facade.hideInplace import com.intellij.vcs.log.graph.utils.LinearGraphUtils import com.intellij.vcs.log.impl.HashImpl import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl @@ -44,6 +45,7 @@ import com.intellij.vcs.log.util.VcsLogUtil import com.intellij.vcs.log.visible.CommitCountStage import com.intellij.vcs.log.visible.VcsLogFilterer import com.intellij.vcs.log.visible.VcsLogFiltererImpl +import com.intellij.vcs.log.visible.VcsLogFiltererImpl.matchesNothing import com.intellij.vcs.log.visible.VisiblePack import com.intellij.vcsUtil.VcsUtil @@ -171,31 +173,36 @@ internal class FileHistoryFilterer(logData: VcsLogData) : VcsLogFilterer { filters: VcsLogFilterCollection): VisiblePack { val matchingHeads = vcsLogFilterer.getMatchingHeads(dataPack.refsModel, setOf(root), filters) val data = indexDataGetter.buildFileNamesData(filePath) - var visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, data.commits) - var pathsMap: Map? = null - if (visibleGraph.visibleCommitCount > 0) { - if (visibleGraph is VisibleGraphImpl<*>) { - val visibleLinearGraph = (visibleGraph as VisibleGraphImpl).linearGraph - val permanentGraphInfo: PermanentGraphInfo = visibleGraph.permanentGraph - - val hash = hash ?: getHead(dataPack) - val row = hash?.let { - findAncestorRowAffectingFile(storage.getCommitIndex(it, root), filePath, visibleLinearGraph, permanentGraphInfo, data) - } ?: 0 - if (row >= 0) { - val refiner = FileHistoryRefiner(visibleLinearGraph, permanentGraphInfo, data) - if (refiner.refine(row, filePath)) { - // creating a vg is the most expensive task, so trying to avoid that when unnecessary - visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, refiner.pathsForCommits.keys) - pathsMap = refiner.pathsForCommits - } - } - } + val permanentGraph = dataPack.permanentGraph + if (permanentGraph !is PermanentGraphImpl) { + val visibleGraph = vcsLogFilterer.createVisibleGraph(dataPack, sortType, matchingHeads, data.commits) + return FileHistoryVisiblePack(dataPack, visibleGraph, false, filters, data.buildPathsMap()) } - if (pathsMap == null) { - pathsMap = data.buildPathsMap() + if (matchesNothing(matchingHeads) || matchesNothing(data.commits)) { + return VisiblePack.EMPTY + } + + val pathsMap = mutableMapOf() + val visibleGraph = permanentGraph.createVisibleGraph(sortType, matchingHeads, + data.commits) preprocess@{ controller, permanentGraphInfo -> + val visibleLinearGraph = controller.compiledGraph + val hash = hash ?: getHead(dataPack) + val row = hash?.let { + findAncestorRowAffectingFile(storage.getCommitIndex(it, root), filePath, visibleLinearGraph, permanentGraphInfo, data) + } ?: 0 + if (row >= 0) { + val refiner = FileHistoryRefiner(visibleLinearGraph, permanentGraphInfo, data) + if (refiner.refine(row, filePath)) { + // creating a vg is the most expensive task, so trying to avoid that when unnecessary + val hidden = hideInplace(controller, permanentGraphInfo, refiner.excluded) + if (!hidden) LOG.error("Could not hide excluded commits from history for " + filePath.path) + pathsMap.putAll(refiner.pathsForCommits) + return@preprocess + } + } + pathsMap.putAll(data.buildPathsMap()) } if (!filePath.isDirectory) reindexFirstCommitsIfNeeded(visibleGraph) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/VcsLogFiltererImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/VcsLogFiltererImpl.java index 3a292db2c643..cc9a05ad1fb9 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/VcsLogFiltererImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/visible/VcsLogFiltererImpl.java @@ -164,7 +164,7 @@ public class VcsLogFiltererImpl implements VcsLogFilterer { return false; } - private static boolean matchesNothing(@Nullable Collection matchingSet) { + public static boolean matchesNothing(@Nullable Collection matchingSet) { return matchingSet != null && matchingSet.isEmpty(); }