[log] Optimize ref searching in GraphBuilder.append

* Initially populate a Hash -> VcsRefs multimap and just get values
  while building.
* Pass all VcsRefs to the Branch instead of just the first one,
  so that the Branch could select the one which fits best for it
  needs (for identifying the color - it is any non-tag).
This commit is contained in:
Kirill Likhodedov
2013-09-28 17:45:22 +04:00
parent 94c7a4110c
commit 16b2e102e2
2 changed files with 45 additions and 31 deletions
@@ -1,29 +1,44 @@
package com.intellij.vcs.log.graph.elements;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author erokhins
*/
public final class Branch {
private final Hash upCommitHash;
private final Hash downCommitHash;
@Nullable private final VcsRef myRef;
@Nullable private final VcsRef myColoredRef;
@NotNull private final VirtualFile myRepositoryRoot;
public Branch(@NotNull Hash upCommitHash, @NotNull Hash downCommitHash, @Nullable VcsRef ref, @NotNull VirtualFile repositoryRoot) {
public Branch(@NotNull Hash upCommitHash, @NotNull Hash downCommitHash, @NotNull Collection<VcsRef> refs,
@NotNull VirtualFile repositoryRoot) {
this.upCommitHash = upCommitHash;
this.downCommitHash = downCommitHash;
myRef = ref;
myRepositoryRoot = repositoryRoot;
myColoredRef = findRefForBranchColor(refs);
}
public Branch(@NotNull Hash commit, @Nullable VcsRef ref, @NotNull VirtualFile repositoryRoot) {
this(commit, commit, ref, repositoryRoot);
@Nullable
private static VcsRef findRefForBranchColor(@NotNull Collection<VcsRef> refs) {
return ContainerUtil.find(refs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return ref.getType().isBranch();
}
});
}
public Branch(@NotNull Hash commit, @NotNull Collection<VcsRef> refs, @NotNull VirtualFile repositoryRoot) {
this(commit, commit, refs, repositoryRoot);
}
@NotNull
@@ -37,10 +52,10 @@ public final class Branch {
}
public int getBranchNumber() {
if (myRef == null || !myRef.getType().isBranch()) {
if (myColoredRef == null) {
return upCommitHash.hashCode() + 73 * downCommitHash.hashCode();
}
return myRef.getName().hashCode();
return myColoredRef.getName().hashCode();
}
@Override
@@ -72,8 +87,4 @@ public final class Branch {
return myRepositoryRoot;
}
@Nullable
public VcsRef getRef() {
return myRef;
}
}
@@ -1,19 +1,17 @@
package com.intellij.vcs.log.graph.mutable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.VcsCommit;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsCommit;
import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.graph.elements.Branch;
import com.intellij.vcs.log.graph.mutable.elements.MutableNode;
import com.intellij.vcs.log.graph.mutable.elements.MutableNodeRow;
import com.intellij.vcs.log.graph.mutable.elements.UsualEdge;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -51,7 +49,7 @@ public class GraphBuilder {
private final MutableGraph graph;
private final Map<Hash, MutableNode> underdoneNodes;
private Map<Hash, Integer> commitHashLogIndexes;
private Collection<VcsRef> myRefs;
private MultiMap<Hash, VcsRef> myRefsOfHashes;
private MutableNodeRow nextRow;
@@ -65,7 +63,17 @@ public class GraphBuilder {
this.graph = graph;
this.underdoneNodes = underdoneNodes;
this.nextRow = nextRow;
myRefs = refs;
myRefsOfHashes = prepareRefsMap(refs);
}
@NotNull
private static MultiMap<Hash, VcsRef> prepareRefsMap(@NotNull Collection<VcsRef> refs) {
MultiMap<Hash, VcsRef> map = MultiMap.create();
for (VcsRef ref : refs) {
map.putValue(ref.getCommitHash(), ref);
}
return map;
}
public GraphBuilder(int lastLogIndex, Map<Hash, Integer> commitHashLogIndexes, MutableGraph graph, Collection<VcsRef> refs) {
@@ -87,30 +95,25 @@ public class GraphBuilder {
}
}
@Nullable
public VcsRef findRefForHash(@NotNull final Hash hash) {
return ContainerUtil.find(myRefs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return ref.getCommitHash().equals(hash);
}
});
@NotNull
private Collection<VcsRef> findRefForHash(@NotNull final Hash hash) {
return myRefsOfHashes.get(hash);
}
private MutableNode addCurrentCommitAndFinishRow(@NotNull Hash commitHash) {
MutableNode node = underdoneNodes.remove(commitHash);
if (node == null) {
VcsRef ref = findRefForHash(commitHash);
Collection<VcsRef> refs = findRefForHash(commitHash);
VirtualFile repositoryRoot;
if (ref == null) {
if (refs.isEmpty()) {
// should never happen, but fallback gently.
LOG.error("Ref should exist for this node. Hash: " + commitHash);
repositoryRoot = NullVirtualFile.INSTANCE;
}
else {
repositoryRoot = ref.getRoot();
repositoryRoot = refs.iterator().next().getRoot();
}
node = createNode(commitHash, new Branch(commitHash, ref, repositoryRoot));
node = createNode(commitHash, new Branch(commitHash, refs, repositoryRoot));
}
node.setType(COMMIT_NODE);
node.setNodeRow(nextRow);
@@ -163,8 +166,8 @@ public class GraphBuilder {
}
else {
for (Hash parentHash : parents) {
VcsRef ref = findRefForHash(node.getCommitHash());
addParent(node, parentHash, new Branch(node.getCommitHash(), parentHash, ref, branch.getRepositoryRoot()));
Collection<VcsRef> refs = findRefForHash(node.getCommitHash());
addParent(node, parentHash, new Branch(node.getCommitHash(), parentHash, refs, branch.getRepositoryRoot()));
}
}
}