diff options
Diffstat (limited to 'platform/vcs-log/impl/src/com')
5 files changed, 96 insertions, 61 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; } |