From be1f9289a1b46c8afdae95f307197f9d9c857051 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 13 Jan 2016 18:03:32 +0300 Subject: [PATCH] git: make GitFileAnnotation immutable --- .../annotate/GitAnnotationProvider.java | 49 +++++++++---------- .../git4idea/annotate/GitFileAnnotation.java | 46 +++++------------ 2 files changed, 36 insertions(+), 59 deletions(-) diff --git a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java index f38ea2b4461e..e09f2e8afad4 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java +++ b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java @@ -22,7 +22,6 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.annotate.*; @@ -37,6 +36,7 @@ import com.intellij.vcsUtil.VcsUtil; import git4idea.GitFileRevision; import git4idea.GitRevisionNumber; import git4idea.GitUtil; +import git4idea.annotate.GitFileAnnotation.LineInfo; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; import git4idea.history.GitHistoryUtils; @@ -46,10 +46,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class GitAnnotationProvider implements AnnotationProviderEx, VcsCacheableAnnotationProvider { private final Project myProject; @@ -145,22 +142,22 @@ public class GitAnnotationProvider implements AnnotationProviderEx, VcsCacheable h.endOptions(); h.addRelativePaths(repositoryFilePath); String output = h.run(); - GitFileAnnotation annotation = parseAnnotations(revision, file, output); - annotation.addLogEntries(revisions); - return annotation; + return parseAnnotations(revision, file, output, revisions); } @NotNull private GitFileAnnotation parseAnnotations(@Nullable VcsRevisionNumber revision, @NotNull VirtualFile file, - @NotNull String output) throws VcsException { - GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null ? null : revision); + @NotNull String output, + @NotNull List revisions) throws VcsException { class CommitInfo { Date date; String author; GitRevisionNumber revision; } try { + StringBuilder content = new StringBuilder(); + List lines = new ArrayList(); HashMap commits = new HashMap(); for (StringScanner s = new StringScanner(output); s.hasMoreData();) { // parse header line @@ -201,14 +198,21 @@ public class GitAnnotationProvider implements AnnotationProviderEx, VcsCacheable continue; } s.skipChars(1); - String line = s.line(true); - annotation.appendLineInfo(commit.date, commit.revision, commit.author, line, lineNum); + + int expectedLineNum = lines.size() + 1; + if (lineNum != expectedLineNum) { + throw new VcsException("Adding for info for line " + lineNum + " but we are expecting it to be for " + expectedLineNum); + } + + content.append(s.line(true)); + lines.add(new LineInfo(commit.date, commit.revision, commit.author)); } + return new GitFileAnnotation(myProject, file, revision, content.toString(), lines, revisions); } catch (Exception e) { LOG.error("Couldn't parse annotation: " + e, new Attachment("output.txt", output)); + throw new VcsException(e); } - return annotation; } @Override @@ -227,30 +231,23 @@ public class GitAnnotationProvider implements AnnotationProviderEx, VcsCacheable public FileAnnotation restore(@NotNull VcsAnnotation vcsAnnotation, @NotNull VcsAbstractHistorySession session, @NotNull String annotatedContent, - boolean forCurrentRevision, VcsRevisionNumber revisionNumber) { + boolean forCurrentRevision, + VcsRevisionNumber revisionNumber) { VirtualFile virtualFile = vcsAnnotation.getFilePath().getVirtualFile(); if (virtualFile == null) return null; - final GitFileAnnotation gitFileAnnotation = new GitFileAnnotation(myProject, virtualFile, revisionNumber); - gitFileAnnotation.addLogEntries(session.getRevisionList()); final VcsLineAnnotationData basicAnnotation = vcsAnnotation.getBasicAnnotation(); final int size = basicAnnotation.getNumLines(); - final Map historyAsMap = session.getHistoryAsMap(); - final List lines = StringUtil.split(StringUtil.convertLineSeparators(annotatedContent), "\n", false, false); + final Map historyAsMap = session.getHistoryAsMap(); + final List lines = new ArrayList(); for (int i = 0; i < size; i++) { final VcsRevisionNumber revision = basicAnnotation.getRevision(i); final VcsFileRevision vcsFileRevision = historyAsMap.get(revision); if (vcsFileRevision == null) { return null; } - try { - gitFileAnnotation.appendLineInfo(vcsFileRevision.getRevisionDate(), (GitRevisionNumber) revision, vcsFileRevision.getAuthor(), - lines.get(i), i + 1); - } - catch (VcsException e) { - return null; - } + lines.add(new LineInfo(vcsFileRevision.getRevisionDate(), (GitRevisionNumber)revision, vcsFileRevision.getAuthor())); } - return gitFileAnnotation; + return new GitFileAnnotation(myProject, virtualFile, revisionNumber, annotatedContent, lines, session.getRevisionList()); } public boolean isAnnotationValid(VcsFileRevision rev) { diff --git a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java index 0c1df6a50a5b..8de7c60416a4 100644 --- a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java +++ b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java @@ -16,7 +16,6 @@ package git4idea.annotate; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.annotate.*; import com.intellij.openapi.vcs.history.VcsFileRevision; @@ -33,13 +32,14 @@ import org.jetbrains.annotations.Nullable; import java.util.*; public class GitFileAnnotation extends FileAnnotation { - private final StringBuffer myContentBuffer = new StringBuffer(); // annotated content - private final ArrayList myLines = new ArrayList(); // The currently annotated lines private final Project myProject; - private final VcsRevisionNumber myBaseRevision; - @NotNull private final Map myRevisionMap = new HashMap(); @NotNull private final VirtualFile myFile; @NotNull private final GitVcs myVcs; + @Nullable private final VcsRevisionNumber myBaseRevision; + + @NotNull private final String myAnnotatedContent; + @NotNull private final List myLines; + @NotNull private final Map myRevisionMap = new HashMap(); private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.DATE, true) { @Override @@ -67,15 +67,18 @@ public class GitFileAnnotation extends FileAnnotation { public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, - final VcsRevisionNumber revision) { + @Nullable final VcsRevisionNumber revision, + @NotNull String annotatedContent, + @NotNull List lines, + @NotNull List revisions) { super(project); myProject = project; - myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject)); myFile = file; + myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject)); myBaseRevision = revision == null ? (myVcs.getDiffProvider().getCurrentRevision(file)) : revision; - } - public void addLogEntries(List revisions) { + myAnnotatedContent = annotatedContent; + myLines = lines; for (VcsFileRevision vcsFileRevision : revisions) { myRevisionMap.put(vcsFileRevision.getRevisionNumber(), vcsFileRevision); } @@ -108,7 +111,7 @@ public class GitFileAnnotation extends FileAnnotation { @Override public String getAnnotatedContent() { - return myContentBuffer.toString(); + return myAnnotatedContent; } @Override @@ -166,29 +169,6 @@ public class GitFileAnnotation extends FileAnnotation { return getLineRevisionNumber(lineNumber); } - /** - * Append line info - * - * @param date the revision date - * @param revision the revision number - * @param author the author - * @param line the line content - * @param lineNumber the line number for revision - * @throws VcsException in case when line could not be processed - */ - public void appendLineInfo(final Date date, - final GitRevisionNumber revision, - final String author, - final String line, - final long lineNumber) throws VcsException { - int expectedLineNo = myLines.size() + 1; - if (lineNumber != expectedLineNo) { - throw new VcsException("Adding for info for line " + lineNumber + " but we are expecting it to be for " + expectedLineNo); - } - myLines.add(new LineInfo(date, revision, author)); - myContentBuffer.append(line); - } - public int getNumLines() { return myLines.size(); }