From e13e5a7d43ef3905a6cf32a7aa4681a5a7984997 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 5 Sep 2016 13:01:12 +0300 Subject: [PATCH] git: fix "annotate previous revision" for renamed files In some cases (ex: when a file was split into two files), `git log` might detect more renames than `git blame`. In this case we will fallback to the old history-based approach. This might be not particulary right (ex: in tricky cases with multiple renames in multiple branches), but works good enough in general. --- .../git4idea/annotate/GitFileAnnotation.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java index 93bb1f47168f..1c5e1e2fa72e 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java +++ b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java @@ -38,6 +38,7 @@ import git4idea.GitFileRevision; import git4idea.GitRevisionNumber; import git4idea.GitVcs; import git4idea.i18n.GitBundle; +import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,6 +52,7 @@ public class GitFileAnnotation extends FileAnnotation { @NotNull private final List myLines; @Nullable private List myRevisions; + @Nullable private TObjectIntHashMap myRevisionMap; private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.DATE, true) { @Override @@ -113,6 +115,11 @@ public class GitFileAnnotation extends FileAnnotation { public void setRevisions(@NotNull List revisions) { myRevisions = revisions; + + myRevisionMap = new TObjectIntHashMap<>(); + for (int i = 0; i < myRevisions.size(); i++) { + myRevisionMap.put(myRevisions.get(i).getRevisionNumber(), i); + } } @Override @@ -292,7 +299,21 @@ public class GitFileAnnotation extends FileAnnotation { @Override public VcsFileRevision getPreviousRevision(int lineNumber) { LineInfo lineInfo = getLineInfo(lineNumber); - return lineInfo != null ? lineInfo.getPreviousFileRevision() : null; + if (lineInfo == null) return null; + + VcsFileRevision previousFileRevision = lineInfo.getPreviousFileRevision(); + if (previousFileRevision != null) return previousFileRevision; + + GitRevisionNumber revisionNumber = lineInfo.getRevisionNumber(); + if (myRevisions != null && myRevisionMap != null && + myRevisionMap.contains(revisionNumber)) { + int index = myRevisionMap.get(revisionNumber); + if (index + 1 < myRevisions.size()) { + return myRevisions.get(index + 1); + } + } + + return null; } @Nullable