summaryrefslogtreecommitdiff
path: root/platform/vcs-log/impl
diff options
context:
space:
mode:
Diffstat (limited to 'platform/vcs-log/impl')
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java13
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java26
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java25
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java89
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java4
-rw-r--r--platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java141
-rw-r--r--platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt468
-rw-r--r--platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java8
-rw-r--r--platform/vcs-log/impl/vcs-log-impl.iml1
9 files changed, 570 insertions, 205 deletions
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
index 6ed592f10939..fc51742b5318 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
@@ -30,9 +30,7 @@ import java.util.*;
* @author Kirill Likhodedov
*/
public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
- private final static int BOUND_SAVED_LOG = 10000;
- public final static String NOT_ENOUGH_FIRST_BLOCK = "Not enough first block";
public final static String ILLEGAL_DATA_RELOAD_ALL = "All data is illegal - request reload all";
/**
@@ -100,12 +98,10 @@ public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
Commit commit = commits.get(lastIndex);
if (searchHashes.size() == 0)
return lastIndex;
- if (lastIndex > BOUND_SAVED_LOG)
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
searchHashes.remove(commit.getId());
}
if (searchHashes.size() != 0)
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
+ throw new VcsLogRefreshNotEnoughDataException();
return lastIndex;
}
@@ -157,16 +153,13 @@ public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
private void markRealRedNode(@NotNull CommitId node) {
if (!currentRed.remove(node))
- throw new IllegalStateException(NOT_ENOUGH_FIRST_BLOCK);
+ throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL); // never happened
allRedCommit.add(node);
}
private int getFirstSaveIndex() {
for (int lastIndex = 0; lastIndex < savedLog.size(); lastIndex++) {
Commit commit = savedLog.get(lastIndex);
- if (lastIndex > BOUND_SAVED_LOG)
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
-
boolean isGreen = currentGreen.contains(commit.getId());
if (isGreen) {
currentRed.remove(commit.getId());
@@ -180,7 +173,7 @@ public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
if (currentRed.isEmpty())
return lastIndex + 1;
}
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
+ throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL); // see VcsLogJoinerTest#illegalStateExceptionTest
}
public Set<CommitId> getAllRedCommit() {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
index 7006408943a8..072e0e26ace1 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
@@ -1,36 +1,36 @@
package com.intellij.vcs.log.data;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.TimedVcsCommit;
+import com.intellij.vcs.log.graph.GraphCommit;
import org.jetbrains.annotations.NotNull;
import java.util.*;
-public class VcsLogMultiRepoJoiner {
+public class VcsLogMultiRepoJoiner<CommitId> {
@NotNull
- public List<? extends TimedVcsCommit> join(@NotNull Collection<List<? extends TimedVcsCommit>> logsFromRepos) {
+ public List<? extends GraphCommit<CommitId>> join(@NotNull Collection<List<? extends GraphCommit<CommitId>>> logsFromRepos) {
if (logsFromRepos.size() == 1) {
return logsFromRepos.iterator().next();
}
int size = 0;
- for (List<? extends TimedVcsCommit> repo : logsFromRepos) {
+ for (List<? extends GraphCommit<CommitId>> repo : logsFromRepos) {
size += repo.size();
}
- List<TimedVcsCommit> result = new ArrayList<TimedVcsCommit>(size);
+ List<GraphCommit<CommitId>> result = new ArrayList<GraphCommit<CommitId>>(size);
- Map<TimedVcsCommit, Iterator<? extends TimedVcsCommit>> nextCommits = ContainerUtil.newHashMap();
- for (List<? extends TimedVcsCommit> log : logsFromRepos) {
- Iterator<? extends TimedVcsCommit> iterator = log.iterator();
+ Map<GraphCommit<CommitId>, Iterator<? extends GraphCommit<CommitId>>> nextCommits = ContainerUtil.newHashMap();
+ for (List<? extends GraphCommit<CommitId>> log : logsFromRepos) {
+ Iterator<? extends GraphCommit<CommitId>> iterator = log.iterator();
if (iterator.hasNext()) {
nextCommits.put(iterator.next(), iterator);
}
}
while (!nextCommits.isEmpty()) {
- TimedVcsCommit lastCommit = findLatestCommit(nextCommits.keySet());
- Iterator<? extends TimedVcsCommit> iterator = nextCommits.get(lastCommit);
+ GraphCommit<CommitId> lastCommit = findLatestCommit(nextCommits.keySet());
+ Iterator<? extends GraphCommit<CommitId>> iterator = nextCommits.get(lastCommit);
result.add(lastCommit);
nextCommits.remove(lastCommit);
@@ -43,10 +43,10 @@ public class VcsLogMultiRepoJoiner {
}
@NotNull
- private static TimedVcsCommit findLatestCommit(@NotNull Set<TimedVcsCommit> commits) {
+ private GraphCommit<CommitId> findLatestCommit(@NotNull Set<GraphCommit<CommitId>> commits) {
long maxTimeStamp = Long.MIN_VALUE;
- TimedVcsCommit lastCommit = null;
- for (TimedVcsCommit commit : commits) {
+ GraphCommit<CommitId> lastCommit = null;
+ for (GraphCommit<CommitId> commit : commits) {
if (commit.getTimestamp() >= maxTimeStamp) {
maxTimeStamp = commit.getTimestamp();
lastCommit = commit;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java
new file mode 100644
index 000000000000..9863be8d0304
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log.data;
+
+public class VcsLogRefreshNotEnoughDataException extends RuntimeException {
+
+ private final static String NOT_ENOUGH_FIRST_BLOCK = "Not enough first block";
+
+ public VcsLogRefreshNotEnoughDataException() {
+ super(NOT_ENOUGH_FIRST_BLOCK);
+ }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
index 0c25d7f5709d..12996f91c116 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
@@ -96,11 +96,11 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
Map<VirtualFile, Collection<VcsRef>> refs = loadRefsFromVcs(myProviders);
Set<VirtualFile> roots = myProviders.keySet();
Map<VirtualFile, VcsLogProvider.Requirements> requirements = prepareSimpleRequirements(roots, myRecentCommitCount);
- Map<VirtualFile, List<? extends TimedVcsCommit>> commits = loadRecentCommitsFromVcs(myProviders, requirements,
- myUserRegistry, myTopCommitsDetailsCache);
- List<? extends TimedVcsCommit> compoundLog = compound(commits.values());
- List<GraphCommit<Integer>> compactedLog = compactCommits(compoundLog, myHashMap);
- DataPack dataPack = DataPack.build(compactedLog, new RefsModel(refs, myHashMap.asIndexGetter()),
+ Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = loadRecentCommitsFromVcs(myProviders, requirements,
+ myUserRegistry, myTopCommitsDetailsCache,
+ myHashMap);
+ List<? extends GraphCommit<Integer>> compoundLog = compound(commits.values());
+ DataPack dataPack = DataPack.build(compoundLog, new RefsModel(refs, myHashMap.asIndexGetter()),
myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, false);
mySingleTaskController.request(RefreshRequest.RELOAD_ALL); // build/rebuild the full log in bg
return dataPack;
@@ -152,19 +152,21 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
@NotNull
- private static Map<VirtualFile, List<? extends TimedVcsCommit>> loadRecentCommitsFromVcs(@NotNull Map<VirtualFile, VcsLogProvider> providers,
- @NotNull final Map<VirtualFile, VcsLogProvider.Requirements> requirements,
- @NotNull final VcsUserRegistryImpl userRegistry,
- @NotNull final Map<Hash, VcsCommitMetadata> topCommitsDetailsCache)
- throws VcsException {
+ private static Map<VirtualFile, List<? extends GraphCommit<Integer>>> loadRecentCommitsFromVcs(
+ @NotNull Map<VirtualFile, VcsLogProvider> providers,
+ @NotNull final Map<VirtualFile, VcsLogProvider.Requirements> requirements,
+ @NotNull final VcsUserRegistryImpl userRegistry,
+ @NotNull final Map<Hash, VcsCommitMetadata> topCommitsDetailsCache,
+ @NotNull final VcsLogHashMap hashMap) throws VcsException
+ {
final StopWatch sw = StopWatch.start("loading commits");
- final Map<VirtualFile, List<? extends TimedVcsCommit>> commits = ContainerUtil.newHashMap();
+ final Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = ContainerUtil.newHashMap();
new ProviderIterator() {
@Override
public void each(@NotNull VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
List<? extends VcsCommitMetadata> metadatas = provider.readFirstBlock(root, requirements.get(root));
storeUsersAndDetails(metadatas, userRegistry, topCommitsDetailsCache);
- commits.put(root, metadatas);
+ commits.put(root, compactCommits(metadatas, hashMap));
sw.rootCompleted(root);
}
}.iterate(providers);
@@ -177,9 +179,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
* Compounds logs from different repositories into a single multi-repository log.
*/
@NotNull
- private static List<? extends TimedVcsCommit> compound(@NotNull Collection<List<? extends TimedVcsCommit>> commits) {
+ private static List<? extends GraphCommit<Integer>> compound(@NotNull Collection<List<? extends GraphCommit<Integer>>> commits) {
StopWatch sw = StopWatch.start("multi-repo join");
- List<? extends TimedVcsCommit> joined = new VcsLogMultiRepoJoiner().join(commits);
+ List<? extends GraphCommit<Integer>> joined = new VcsLogMultiRepoJoiner<Integer>().join(commits);
sw.report();
return joined;
}
@@ -192,8 +194,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull
@Override
public GraphCommit<Integer> fun(@NotNull TimedVcsCommit commit) {
- return new GraphCommitImpl<Integer>(hashMap.getCommitIndex(commit.getId()),
- ContainerUtil.map(commit.getParents(), hashMap.asIndexGetter()), commit.getTimestamp());
+ return compactCommit(commit, hashMap);
}
});
hashMap.flush();
@@ -201,6 +202,12 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
return map;
}
+ @NotNull
+ private static GraphCommitImpl<Integer> compactCommit(@NotNull TimedVcsCommit commit, @NotNull VcsLogHashMap hashMap) {
+ return new GraphCommitImpl<Integer>(hashMap.getCommitIndex(commit.getId()),
+ ContainerUtil.map(commit.getParents(), hashMap.asIndexGetter()), commit.getTimestamp());
+ }
+
private static void storeUsersAndDetails(@NotNull List<? extends VcsCommitMetadata> metadatas, @NotNull VcsUserRegistryImpl userRegistry,
@NotNull Map<Hash, VcsCommitMetadata> topCommitsDetailsCache) {
for (VcsCommitMetadata detail : metadatas) {
@@ -218,9 +225,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
private final Map<VirtualFile, LogAndRefs> myLoadedInfos = ContainerUtil.newHashMap();
private class LogAndRefs {
- List<? extends TimedVcsCommit> log;
+ List<? extends GraphCommit<Integer>> log;
Collection<VcsRef> refs;
- LogAndRefs(Collection<VcsRef> refs, List<? extends TimedVcsCommit> commits) {
+ LogAndRefs(Collection<VcsRef> refs, List<? extends GraphCommit<Integer>> commits) {
this.refs = refs;
this.log = commits;
}
@@ -266,16 +273,16 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
try {
if (permanentGraph != null) {
loadLogAndRefs(roots, currentRefs, myRecentCommitCount);
- List<? extends TimedVcsCommit> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(),
- new Function<LogAndRefs, List<? extends TimedVcsCommit>>() {
+ List<? extends GraphCommit<Integer>> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(),
+ new Function<LogAndRefs, List<? extends GraphCommit<Integer>>>() {
@Override
- public List<? extends TimedVcsCommit> fun(LogAndRefs refs) {
+ public List<? extends GraphCommit<Integer>> fun(
+ LogAndRefs refs) {
return refs.log;
}
}));
- List<GraphCommit<Integer>> preparedLog = compactCommits(compoundLog, myHashMap);
Map<VirtualFile, Collection<VcsRef>> allNewRefs = getAllNewRefs(myLoadedInfos, currentRefs);
- List<GraphCommit<Integer>> joinedFullLog = join(preparedLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs);
+ List<GraphCommit<Integer>> joinedFullLog = join(compoundLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs);
if (joinedFullLog != null) {
return DataPack.build(joinedFullLog, new RefsModel(allNewRefs, myHashMap.asIndexGetter()),
myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, true);
@@ -310,8 +317,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
Map<VirtualFile, VcsLogProvider> providers = getProviders(roots);
Map<VirtualFile, Collection<VcsRef>> refs = loadRefsFromVcs(providers);
Map<VirtualFile, VcsLogProvider.Requirements> requirements = prepareRequirements(roots, commitCount, prevRefs, refs);
- Map<VirtualFile, List<? extends TimedVcsCommit>> commits = loadRecentCommitsFromVcs(providers, requirements,
- myUserRegistry, myTopCommitsDetailsCache);
+ Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = loadRecentCommitsFromVcs(providers, requirements,
+ myUserRegistry, myTopCommitsDetailsCache,
+ myHashMap);
for (VirtualFile root : roots) {
myLoadedInfos.put(root, new LogAndRefs(refs.get(root), commits.get(root)));
}
@@ -345,7 +353,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
@Nullable
- private List<GraphCommit<Integer>> join(@NotNull List<GraphCommit<Integer>> recentCommits, @NotNull List<GraphCommit<Integer>> fullLog,
+ private List<GraphCommit<Integer>> join(@NotNull List<? extends GraphCommit<Integer>> recentCommits, @NotNull List<GraphCommit<Integer>> fullLog,
@NotNull Map<VirtualFile, Collection<VcsRef>> previousRefs,
@NotNull Map<VirtualFile, Collection<VcsRef>> newRefs) {
StopWatch sw = StopWatch.start("joining new commits");
@@ -365,18 +373,20 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
sw.report();
return commits;
}
+ catch (VcsLogRefreshNotEnoughDataException e) {
+ LOG.error(e); // collecting information : how often this situation happens, do we need to try to load more or can safely reload all
+ }
catch (IllegalStateException e) {
- LOG.info(e);
- return null;
+ LOG.error(e);
}
+ return null;
}
@NotNull
private Pair<PermanentGraph<Integer>, Map<VirtualFile, Collection<VcsRef>>> loadFullLog() throws VcsException {
StopWatch sw = StopWatch.start("full log reload");
- Collection<List<? extends TimedVcsCommit>> commits = readFullLogFromVcs();
- List<? extends TimedVcsCommit> compoundLog = compound(commits);
- List<GraphCommit<Integer>> graphCommits = compactCommits(compoundLog, myHashMap);
+ Collection<List<? extends GraphCommit<Integer>>> commits = readFullLogFromVcs();
+ List<? extends GraphCommit<Integer>> graphCommits = compound(commits);
Map<VirtualFile, Collection<VcsRef>> refMap = loadRefsFromVcs(myProviders);
PermanentGraph<Integer> permanentGraph = DataPack.buildPermanentGraph(graphCommits, new RefsModel(refMap, myHashMap.asIndexGetter()),
myHashMap.asIndexGetter(),
@@ -386,24 +396,31 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
@NotNull
- private Collection<List<? extends TimedVcsCommit>> readFullLogFromVcs() throws VcsException {
+ private Collection<List<? extends GraphCommit<Integer>>> readFullLogFromVcs() throws VcsException {
final StopWatch sw = StopWatch.start("read full log from VCS");
- final Collection<List<? extends TimedVcsCommit>> commits = ContainerUtil.newArrayList();
+ final Collection<List<? extends GraphCommit<Integer>>> logs = ContainerUtil.newArrayList();
new ProviderIterator() {
@Override
void each(@NotNull VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
- commits.add(provider.readAllHashes(root, new Consumer<VcsUser>() {
+ final List<GraphCommit<Integer>> graphCommits = ContainerUtil.newArrayList();
+ provider.readAllHashes(root, new Consumer<VcsUser>() {
@Override
public void consume(@NotNull VcsUser user) {
myUserRegistry.addUser(user);
}
- }));
+ }, new Consumer<TimedVcsCommit>() {
+ @Override
+ public void consume(TimedVcsCommit commit) {
+ graphCommits.add(compactCommit(commit, myHashMap));
+ }
+ });
+ logs.add(graphCommits);
sw.rootCompleted(root);
}
}.iterate(myProviders);
myUserRegistry.flush();
sw.report();
- return commits;
+ return logs;
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
index ec74038a66e4..4f0e44cbd3d2 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
@@ -58,7 +58,7 @@ public class GraphColorManagerImpl implements GraphColorManager<Integer> {
if (isEmptyRefs(refs, headCommit)) {
return DEFAULT_COLOR;
}
- VcsRef firstRef = ContainerUtil.sorted(refs, getRefManager(refs).getComparator()).get(0);
+ VcsRef firstRef = Collections.min(refs, getRefManager(refs).getComparator());
// TODO dark variant
return firstRef.getName().hashCode();
}
@@ -67,7 +67,7 @@ public class GraphColorManagerImpl implements GraphColorManager<Integer> {
if (refs.isEmpty()) {
if (!myErrorWasReported.containsKey(head)) {
myErrorWasReported.put(head, head);
- LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
+ LOG.warn("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
}
return true;
}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java
deleted file mode 100644
index 63e54b910bfc..000000000000
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.intellij.vcs.log.data;
-
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.Hash;
-import com.intellij.vcs.log.TimedCommitParser;
-import com.intellij.vcs.log.TimedVcsCommit;
-import com.intellij.vcs.log.impl.HashImpl;
-import org.junit.Test;
-
-import java.util.Collection;
-import java.util.List;
-
-import static java.util.Arrays.asList;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Kirill Likhodedov
- */
-public class VcsLogJoinerTest {
-
- public void runTest(List<String> initial, List<String> updateBlock, List<String> oldRefs, List<String> newRefs, String expected) {
- List<TimedVcsCommit> savedLog = TimedCommitParser.log(ArrayUtil.toStringArray(initial));
- List<? extends TimedVcsCommit> firstBlock = TimedCommitParser.log(ArrayUtil.toStringArray(updateBlock));
- Collection<Hash> vcsOldRefs = ContainerUtil.map(oldRefs, new Function<String, Hash>() {
- @Override
- public Hash fun(String s) {
- return HashImpl.build(s);
- }
- });
- Collection<Hash> vcsNewRefs = ContainerUtil.map(newRefs, new Function<String, Hash>() {
- @Override
- public Hash fun(String s) {
- return HashImpl.build(s);
- }
- });
-
- List<? extends TimedVcsCommit> result = new VcsLogJoiner<Hash, TimedVcsCommit>().addCommits(savedLog, vcsOldRefs, firstBlock, vcsNewRefs).getFirst();
- assertEquals(expected, toStr(result));
- }
-
- @Test
- public void simpleTest() {
- runTest(
- asList("4|-a2|-a1", "3|-b1|-a", "2|-a1|-a", "1|-a|-"),
- asList("5|-f|-b1", "6|-e|-a2"),
- asList("a2", "b1"),
- asList("f", "e"),
- "e, f, a2, b1, a1, a"
- );
- }
-
- @Test
- public void oneNodeTest() {
- runTest(
- asList("3|-a1|-"),
- asList("3|-a1|-"),
- asList("a1"),
- asList("a1"),
- "a1"
- );
- }
-
- @Test
- public void oneNodeResetTest() {
- runTest(
- asList("3|-a1|-a2", "2|-a2|-"),
- asList("2|-a2|-"),
- asList("a2", "a1"),
- asList("a2"),
- "a2"
- );
- }
-
- @Test
- public void oneNodeReset2Test() {
- runTest(
- asList("3|-a1|-a2", "2|-a2|-"),
- asList("2|-a2|-"),
- asList("a1"),
- asList("a2"),
- "a2"
- );
- }
-
- @Test
- public void simpleRemoveCommitsTest() {
- runTest(
- asList("4|-a2|-a1", "3|-b1|-a", "2|-a1|-a", "1|-a|-"),
- asList("5|-f|-b1", "6|-e|-a1"),
- asList("a2"),
- asList("f", "e"),
- "e, f, b1, a1, a"
- );
- }
-
- @Test
- public void removeCommitsTest() {
- runTest(
- asList("5|-a5|-a4", "4|-a4|-a2 a3", "3|-a3|-a1", "2|-a2|-a1", "1|-a1|-"),
- asList("6|-a6|-a3"),
- asList("a5"),
- asList("a6"),
- "a6, a3, a1"
- );
- }
-
- @Test
- public void removeCommitsTest2() {
- runTest(
- asList("2|-a2|-a1", "1|-a1|-"),
- asList("5|-a5|-a4", "3|-a3|-a2", "4|-a4|-a3"),
- asList("a2"),
- asList("a5"),
- "a5, a4, a3, a2, a1"
- );
- }
-
- @Test
- public void removeCommitsTest3() {
- runTest(
- asList("3|-a3|-a2", "2|-a2|-a1", "1|-a1|-"),
- asList("2|-a2|-a1"),
- asList("a3"),
- asList("a2"),
- "a2, a1"
- );
- }
-
- private static String toStr(List<? extends TimedVcsCommit> commits) {
- StringBuilder s = new StringBuilder();
- for (TimedVcsCommit commit : commits) {
- if (s.length() != 0) {
- s.append(", ");
- }
- s.append(commit.getId().asString());
- }
- return s.toString();
- }
-}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt
new file mode 100644
index 000000000000..ed4218473984
--- /dev/null
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log.data
+
+import org.junit.Test
+import java.util.ArrayList
+import com.intellij.vcs.log.TimedCommitParser
+import com.intellij.util.ArrayUtil
+import com.intellij.vcs.log.impl.HashImpl
+import com.intellij.vcs.log.TimedVcsCommit
+import com.intellij.vcs.log.Hash
+import org.junit.Assert.*
+
+
+class VcsLogJoinerTest {
+
+ class StringArrayBuilder() {
+ val result = ArrayList<String>()
+
+ fun String.plus() = result.add(this)
+
+ fun Collection<String>.plus() = result.addAll(this)
+ }
+
+ class TestRunner() {
+ private var fullLog: List<String>? = null
+ private var recentCommits: List<String>? = null
+ private var oldRefs: List<String>? = null
+ private var newRefs: List<String>? = null
+ private var expected: String? = null
+
+ private fun build(f: StringArrayBuilder.() -> Unit): List<String> {
+ val stringArrayBuilder = StringArrayBuilder()
+ stringArrayBuilder.f()
+ return stringArrayBuilder.result
+ }
+
+ fun fullLog(f: StringArrayBuilder.() -> Unit) {fullLog = build(f)}
+
+ fun recentCommits(f: StringArrayBuilder.() -> Unit) {recentCommits = build(f)}
+
+ fun oldRefs(f: StringArrayBuilder.() -> Unit) {oldRefs = build(f)}
+
+ fun newRefs(f: StringArrayBuilder.() -> Unit) {newRefs = build(f)}
+
+ fun expected(f: StringArrayBuilder.() -> Unit) {expected = build(f).join(separator = "\n")}
+
+ fun run() {
+ val vcsFullLog = TimedCommitParser.log(fullLog!!)
+ val vcsRecentCommits = TimedCommitParser.log(recentCommits!!)
+ val vcsOldRefs = oldRefs!!.map { HashImpl.build(it) }
+ val vcsNewRefs = newRefs!!.map { HashImpl.build(it) }
+
+ val result = VcsLogJoiner<Hash, TimedVcsCommit>().addCommits(vcsFullLog, vcsOldRefs, vcsRecentCommits, vcsNewRefs).getFirst()!!
+ val actual = result.map { it.getId().asString() }.join(separator = "\n")
+ assertEquals(expected, actual)
+ }
+ }
+
+ fun runTest(f: TestRunner.() -> Unit) {
+ val testRunner = TestRunner()
+ testRunner.f()
+ testRunner.run()
+ }
+
+ val BIG_TIME = 100000000
+
+ Test fun simple() {
+ runTest {
+ fullLog {
+ +"4|-a2|-a1"
+ +"3|-b1|-a"
+ +"2|-a1|-a"
+ +"1|-a|-"
+ }
+ recentCommits {
+ +"5|-f|-b1"
+ +"6|-e|-a2"
+ }
+ oldRefs {
+ +"a2"
+ +"b1"
+ }
+ newRefs {
+ +"f"
+ +"e"
+ }
+ expected {
+ +"e"
+ +"f"
+ +"a2"
+ +"b1"
+ +"a1"
+ +"a"
+ }
+ }
+ }
+
+ Test fun oneNode() {
+ runTest {
+ fullLog {
+ +"3|-a1|-"
+ }
+ recentCommits {
+ +"3|-a1|-"
+ }
+ oldRefs {
+ +"a1"
+ }
+ newRefs {
+ +"a1"
+ }
+ expected {
+ +"a1"
+ }
+ }
+ }
+
+ Test fun oneNodeReset() {
+ runTest {
+ fullLog {
+ +"3|-a1|-a2"
+ +"2|-a2|-"
+ }
+ recentCommits {
+ +"2|-a2|-"
+ }
+ oldRefs {
+ +"a2"
+ +"a1"
+ }
+ newRefs {
+ +"a2"
+ }
+ expected {
+ +"a2"
+ }
+ }
+ }
+
+ Test fun oneNodeReset2() {
+ runTest {
+ fullLog {
+ +"3|-a1|-a2"
+ +"2|-a2|-"
+ }
+ recentCommits {
+ +"2|-a2|-"
+ }
+ oldRefs {
+ +"a1"
+ }
+ newRefs {
+ +"a2"
+ }
+ expected {
+ +"a2"
+ }
+ }
+ }
+
+ Test fun simpleRemoveCommits() {
+ runTest {
+ fullLog {
+ +"4|-a2|-a1"
+ +"3|-b1|-a"
+ +"2|-a1|-a"
+ +"1|-a|-"
+ }
+ recentCommits {
+ +"5|-f|-b1"
+ +"6|-e|-a1"
+ }
+ oldRefs {
+ +"a2"
+ }
+ newRefs {
+ +"f"
+ +"e"
+ }
+ expected {
+ +"e"
+ +"f"
+ +"b1"
+ +"a1"
+ +"a"
+ }
+ }
+ }
+
+ Test fun removeCommits() {
+ runTest {
+ fullLog {
+ +"5|-a5|-a4"
+ +"4|-a4|-a2 a3"
+ +"3|-a3|-a1"
+ +"2|-a2|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"6|-a6|-a3"
+ }
+ oldRefs {
+ +"a5"
+ }
+ newRefs {
+ +"a6"
+ }
+ expected {
+ +"a6"
+ +"a3"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeCommits2() {
+ runTest {
+ fullLog {
+ +"2|-a2|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"5|-a5|-a4"
+ +"3|-a3|-a2"
+ +"4|-a4|-a3"
+ }
+ oldRefs {
+ +"a2"
+ }
+ newRefs {
+ +"a5"
+ }
+ expected {
+ +"a5"
+ +"a4"
+ +"a3"
+ +"a2"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeCommits3() {
+ runTest {
+ fullLog {
+ +"3|-a3|-a2"
+ +"2|-a2|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"2|-a2|-a1"
+ }
+ oldRefs {
+ +"a3"
+ }
+ newRefs {
+ +"a2"
+ }
+ expected {
+ +"a2"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeOldBranch() {
+ runTest {
+ fullLog {
+ +"100|-e1|-e10"
+ +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+ +"5|-e100001|-a1"
+ +"4|-b2|-b1"
+ +"3|-b1|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"100|-e1|-e10"
+ }
+ oldRefs {
+ +"e1"
+ +"b2"
+ }
+ newRefs {
+ "e1"
+ }
+ expected {
+ +"e1"
+ +(10..100000).map { "e$it" }
+ +"e100001"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun addToOldBranch() {
+ runTest {
+ fullLog {
+ +"100|-e1|-e10"
+ +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+ +"5|-e100001|-a1"
+ +"4|-b2|-b1"
+ +"3|-b1|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"50|-b4|-b3"
+ +"49|-b3|-b2"
+ }
+ oldRefs {
+ +"e1"
+ +"b2"
+ }
+ newRefs {
+ +"e1"
+ +"b4"
+ }
+ expected {
+ +"e1"
+ +(10..100000).map { "e$it" }
+ +"b4"
+ +"b3"
+ +"e100001"
+ +"b2"
+ +"b1"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeLongBranch() {
+ runTest {
+ fullLog {
+ +"100|-e1|-e10"
+ +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+ +"5|-e100001|-a1"
+ +"4|-b2|-b1"
+ +"3|-b1|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"50|-b4|-b3"
+ +"49|-b3|-b2"
+ }
+ oldRefs {
+ +"e1"
+ +"b2"
+ }
+ newRefs {
+ +"b4"
+ }
+ expected {
+ +"b4"
+ +"b3"
+ +"b2"
+ +"b1"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun notEnoughDataExceptionTest() {
+ try {
+ runTest {
+ fullLog {
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"3|-a3|-a2"
+ }
+ oldRefs {
+ +"a1"
+ }
+ newRefs {
+ +"a3"
+ }
+ }
+ } catch (e: VcsLogRefreshNotEnoughDataException) {
+ return
+ }
+ fail()
+ }
+
+ Test fun illegalStateExceptionTest() {
+ try {
+ runTest {
+ fullLog {
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"1|-a1|-"
+ }
+ oldRefs {
+ +"a1"
+ +"a2"
+ }
+ newRefs {
+ +"a1"
+ }
+ }
+ } catch (e: IllegalStateException) {
+ return
+ }
+ fail()
+ }
+
+ Test fun removeParallelBranch() {
+ runTest {
+ fullLog {
+ +"4|-a4|-a1"
+ +"3|-a3|-a2"
+ +"2|-a2|-"
+ +"1|-a1|-"
+ }
+ recentCommits {
+
+ }
+ oldRefs {
+ +"a4"
+ +"a3"
+ }
+ newRefs {
+ +"a3"
+ }
+ expected {
+ +"a3"
+ +"a2"
+ }
+ }
+ }
+
+ Test fun removeAll() {
+ runTest {
+ fullLog {
+ +"4|-a4|-a1"
+ +"3|-a3|-a2"
+ +"2|-a2|-"
+ +"1|-a1|-"
+ }
+ recentCommits {
+
+ }
+ oldRefs {
+ +"a4"
+ +"a3"
+ }
+ newRefs {
+
+ }
+ expected {
+
+ }
+ }
+ }
+}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
index d3709b2d8f55..850478b048dc 100644
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
@@ -93,9 +93,9 @@ public class TestVcsLogProvider implements VcsLogProvider {
return ContainerUtil.map(myCommits.subList(0, requirements.getCommitCount()), myCommitToMetadataConvertor);
}
- @NotNull
@Override
- public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
+ public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+ @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
try {
myFullLogSemaphore.acquire();
}
@@ -103,7 +103,9 @@ public class TestVcsLogProvider implements VcsLogProvider {
throw new RuntimeException(e);
}
assertRoot(root);
- return myCommits;
+ for (TimedVcsCommit commit : myCommits) {
+ commitConsumer.consume(commit);
+ }
}
private void assertRoot(@NotNull VirtualFile root) {
diff --git a/platform/vcs-log/impl/vcs-log-impl.iml b/platform/vcs-log/impl/vcs-log-impl.iml
index 5668888806ac..304affc03123 100644
--- a/platform/vcs-log/impl/vcs-log-impl.iml
+++ b/platform/vcs-log/impl/vcs-log-impl.iml
@@ -21,6 +21,7 @@
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="vcs-log-graph-api" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
</component>
</module>