mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[file-history] when revision filter in revision history is not set, jump to specified or nearest commit
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
package com.intellij.vcs.log.history
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.vcs.FilePath
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.containers.Stack
|
||||
@@ -51,7 +50,7 @@ internal class FileHistoryBuilder(private val startCommit: Int?,
|
||||
val visibleLinearGraph = controller.compiledGraph
|
||||
|
||||
val row = startCommit?.let {
|
||||
findAncestorRowAffectingFile(startCommit, startPath, visibleLinearGraph, permanentGraphInfo, fileNamesData)
|
||||
findAncestorRowAffectingFile(startCommit, visibleLinearGraph, permanentGraphInfo)
|
||||
} ?: 0
|
||||
if (row >= 0) {
|
||||
val refiner = FileHistoryRefiner(visibleLinearGraph, permanentGraphInfo, fileNamesData)
|
||||
@@ -66,6 +65,14 @@ internal class FileHistoryBuilder(private val startCommit: Int?,
|
||||
return fileNamesData.buildPathsMap()
|
||||
}
|
||||
|
||||
private fun findAncestorRowAffectingFile(commitId: Int,
|
||||
visibleLinearGraph: LinearGraph,
|
||||
permanentGraphInfo: PermanentGraphInfo<Int>): Int {
|
||||
return findVisibleAncestorRow(commitId, visibleLinearGraph, permanentGraphInfo) { nodeId ->
|
||||
fileNamesData.affects(permanentGraphInfo.permanentCommitsInfo.getCommitId(nodeId), startPath)
|
||||
} ?: -1
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(FileHistoryBuilder::class.java)
|
||||
}
|
||||
@@ -110,33 +117,6 @@ private fun hideTrivialMerge(collapsedGraph: CollapsedGraph, graph: LiteLinearGr
|
||||
}
|
||||
}
|
||||
|
||||
internal fun findAncestorRowAffectingFile(commitId: Int,
|
||||
filePath: FilePath,
|
||||
visibleLinearGraph: LinearGraph,
|
||||
permanentGraphInfo: PermanentGraphInfo<Int>,
|
||||
fileNamesData: FileNamesData): Int {
|
||||
val resultNodeId = Ref<Int>()
|
||||
|
||||
val commitsInfo = permanentGraphInfo.permanentCommitsInfo
|
||||
val reachableNodes = ReachableNodes(LinearGraphUtils.asLiteLinearGraph(permanentGraphInfo.linearGraph))
|
||||
reachableNodes.walk(setOf(commitsInfo.getNodeId(commitId)), true) { currentNode ->
|
||||
val id = commitsInfo.getCommitId(currentNode)
|
||||
if (fileNamesData.affects(id, filePath)) {
|
||||
resultNodeId.set(currentNode)
|
||||
false // stop walk, we have found it
|
||||
}
|
||||
else {
|
||||
true // continue walk
|
||||
}
|
||||
}
|
||||
|
||||
if (!resultNodeId.isNull) {
|
||||
return visibleLinearGraph.getNodeIndex(resultNodeId.get())!!
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
internal class FileHistoryRefiner(private val visibleLinearGraph: LinearGraph,
|
||||
permanentGraphInfo: PermanentGraphInfo<Int>,
|
||||
private val namesData: FileNamesData) : DfsUtil.NodeVisitor {
|
||||
|
||||
@@ -33,12 +33,8 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsFullCommitDetails;
|
||||
import com.intellij.vcs.log.VcsLogFilterCollection;
|
||||
import com.intellij.vcs.log.VcsLogFilterUi;
|
||||
import com.intellij.vcs.log.data.LoadingDetails;
|
||||
import com.intellij.vcs.log.data.VcsLogData;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.*;
|
||||
import com.intellij.vcs.log.data.index.IndexDataGetter;
|
||||
import com.intellij.vcs.log.impl.CommonUiProperties;
|
||||
import com.intellij.vcs.log.impl.VcsLogContentUtil;
|
||||
@@ -72,6 +68,7 @@ public class FileHistoryUi extends AbstractVcsLogUi {
|
||||
@NotNull private final FileHistoryFilterUi myFilterUi;
|
||||
@NotNull private final FilePath myPath;
|
||||
@Nullable private final Hash myRevision;
|
||||
@NotNull private final VirtualFile myRoot;
|
||||
@NotNull private final FileHistoryPanel myFileHistoryPanel;
|
||||
@NotNull private final IndexDataGetter myIndexDataGetter;
|
||||
@NotNull private final MyPropertiesChangeListener myPropertiesChangeListener;
|
||||
@@ -88,6 +85,7 @@ public class FileHistoryUi extends AbstractVcsLogUi {
|
||||
|
||||
myIndexDataGetter = ObjectUtils.assertNotNull(logData.getIndex().getDataGetter());
|
||||
myRevision = revision;
|
||||
myRoot = root;
|
||||
myFilterUi = new FileHistoryFilterUi(path, revision, root, uiProperties);
|
||||
myPath = path;
|
||||
myFileHistoryPanel = new FileHistoryPanel(this, logData, myVisiblePack, path);
|
||||
@@ -250,14 +248,20 @@ public class FileHistoryUi extends AbstractVcsLogUi {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FilePath getPath() {
|
||||
return myPath;
|
||||
public void jumpToNearestCommit(@NotNull Hash hash) {
|
||||
jumpTo(hash, (model, h) -> {
|
||||
if (!myLogData.getStorage().containsCommit(new CommitId(h, myRoot))) return GraphTableModel.COMMIT_NOT_FOUND;
|
||||
int commitIndex = myLogData.getCommitIndex(h, myRoot);
|
||||
Integer rowIndex = myVisiblePack.getVisibleGraph().getVisibleRowIndex(commitIndex);
|
||||
if (rowIndex == null) {
|
||||
rowIndex = ReachableNodesUtilKt.findVisibleAncestorRow(commitIndex, myVisiblePack);
|
||||
}
|
||||
return rowIndex == null ? GraphTableModel.COMMIT_DOES_NOT_MATCH : rowIndex;
|
||||
}, SettableFuture.create());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Hash getRevision() {
|
||||
return myRevision;
|
||||
public boolean matches(@NotNull FilePath targetPath, @Nullable Hash targetRevision) {
|
||||
return myPath.equals(targetPath) && Objects.equals(myRevision, targetRevision);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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.history
|
||||
|
||||
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.visible.VisiblePack
|
||||
|
||||
fun findMatchingAncestorNodeId(commitId: Int, permanentGraphInfo: PermanentGraphInfo<Int>, condition: (Int) -> Boolean): Int? {
|
||||
val resultNodeId = Ref<Int>()
|
||||
|
||||
val startNodeId = permanentGraphInfo.permanentCommitsInfo.getNodeId(commitId)
|
||||
val reachableNodes = ReachableNodes(LinearGraphUtils.asLiteLinearGraph(permanentGraphInfo.linearGraph))
|
||||
reachableNodes.walk(setOf(startNodeId), true) { currentNodeId ->
|
||||
if (condition(currentNodeId)) {
|
||||
resultNodeId.set(currentNodeId)
|
||||
false // stop walk, we have found it
|
||||
}
|
||||
else {
|
||||
true // continue walk
|
||||
}
|
||||
}
|
||||
return resultNodeId.get()
|
||||
}
|
||||
|
||||
fun findVisibleAncestorRow(commitId: Int, visiblePack: VisiblePack): Int? {
|
||||
val dataPack = visiblePack.dataPack
|
||||
val visibleGraph = visiblePack.visibleGraph
|
||||
if (dataPack is DataPack && dataPack.permanentGraph is PermanentGraphInfo<*> && visibleGraph is VisibleGraphImpl) {
|
||||
return findVisibleAncestorRow(commitId, visibleGraph.linearGraph, dataPack.permanentGraph as PermanentGraphInfo<Int>) { _ -> true }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun findVisibleAncestorRow(commitId: Int,
|
||||
visibleLinearGraph: LinearGraph,
|
||||
permanentGraphInfo: PermanentGraphInfo<Int>,
|
||||
condition: (Int) -> Boolean): Int? {
|
||||
val nodeId = findMatchingAncestorNodeId(commitId, permanentGraphInfo) { nodeId ->
|
||||
condition(nodeId) && visibleLinearGraph.getNodeIndex(nodeId) != null
|
||||
} ?: return null
|
||||
return visibleLinearGraph.getNodeIndex(nodeId)
|
||||
}
|
||||
+10
-5
@@ -22,6 +22,7 @@ import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsLogFileHistoryProvider;
|
||||
import com.intellij.vcs.log.VcsLogFilterCollection;
|
||||
import com.intellij.vcs.log.data.VcsLogData;
|
||||
import com.intellij.vcs.log.impl.HashImpl;
|
||||
import com.intellij.vcs.log.impl.VcsLogContentUtil;
|
||||
@@ -30,8 +31,6 @@ import com.intellij.vcs.log.impl.VcsProjectLog;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class VcsLogFileHistoryProviderImpl implements VcsLogFileHistoryProvider {
|
||||
@NotNull
|
||||
public static final String TAB_NAME = "History";
|
||||
@@ -52,12 +51,18 @@ public class VcsLogFileHistoryProviderImpl implements VcsLogFileHistoryProvider
|
||||
@Override
|
||||
public void showFileHistory(@NotNull Project project, @NotNull FilePath path, @Nullable String revisionNumber) {
|
||||
Hash hash = (revisionNumber != null) ? HashImpl.build(revisionNumber) : null;
|
||||
if (!VcsLogContentUtil.findAndSelectContent(project, FileHistoryUi.class,
|
||||
ui -> ui.getPath().equals(path) && Objects.equals(ui.getRevision(), hash))) {
|
||||
FileHistoryUi fileHistoryUi = VcsLogContentUtil.findAndSelect(project, FileHistoryUi.class,
|
||||
ui -> ui.matches(path, hash));
|
||||
if (fileHistoryUi == null) {
|
||||
VcsLogManager logManager = VcsProjectLog.getInstance(project).getLogManager();
|
||||
assert logManager != null;
|
||||
String suffix = hash != null ? " (" + hash.toShortString() + ")" : "";
|
||||
VcsLogContentUtil.openLogTab(project, logManager, TAB_NAME, path.getName() + suffix, new FileHistoryUiFactory(path, hash), true);
|
||||
fileHistoryUi = VcsLogContentUtil.openLogTab(project, logManager, TAB_NAME, path.getName() + suffix,
|
||||
new FileHistoryUiFactory(path, hash), true);
|
||||
}
|
||||
|
||||
if (hash != null && fileHistoryUi.getFilterUi().getFilters().get(VcsLogFilterCollection.REVISION_FILTER) == null) {
|
||||
fileHistoryUi.jumpToNearestCommit(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,13 @@ public class VcsLogContentUtil {
|
||||
public static <U extends AbstractVcsLogUi> boolean findAndSelectContent(@NotNull Project project,
|
||||
@NotNull Class<U> clazz,
|
||||
@NotNull Condition<U> condition) {
|
||||
return findAndSelect(project, clazz, condition) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <U extends AbstractVcsLogUi> U findAndSelect(@NotNull Project project,
|
||||
@NotNull Class<U> clazz,
|
||||
@NotNull Condition<U> condition) {
|
||||
ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.VCS);
|
||||
|
||||
ContentManager manager = toolWindow.getContentManager();
|
||||
@@ -76,10 +83,12 @@ public class VcsLogContentUtil {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (component == null) return false;
|
||||
if (component == null) return null;
|
||||
|
||||
if (!toolWindow.isVisible()) toolWindow.activate(null);
|
||||
return ContentUtilEx.selectContent(manager, component, true);
|
||||
if (!ContentUtilEx.selectContent(manager, component, true)) return null;
|
||||
//noinspection unchecked
|
||||
return (U)getLogUi(component);
|
||||
}
|
||||
|
||||
public static boolean selectLogUi(@NotNull Project project, @NotNull VcsLogUi ui) {
|
||||
|
||||
Reference in New Issue
Block a user