[vcs-log] walk through storage only once

This commit is contained in:
Julia Beliaeva
2018-01-21 19:30:20 +03:00
parent bfc3f0de67
commit 1c2a61ba32
5 changed files with 36 additions and 34 deletions
@@ -15,8 +15,8 @@
*/
package com.intellij.vcs.log.data;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.BiDirectionalEnumerator;
import com.intellij.vcs.log.CommitId;
import com.intellij.vcs.log.Hash;
@@ -45,18 +45,9 @@ public class InMemoryStorage implements VcsLogStorage {
return myCommitIdEnumerator.getValue(commitIndex);
}
@Nullable
@Override
public CommitId findCommitId(@NotNull final Condition<CommitId> condition) {
final CommitId[] result = new CommitId[]{null};
myCommitIdEnumerator.forEachValue(commitId -> {
if (condition.value(commitId)) {
result[0] = commitId;
return false;
}
return true;
});
return result[0];
public void iterateCommits(@NotNull Function<CommitId, Boolean> consumer) {
myCommitIdEnumerator.forEachValue(commitId -> !consumer.fun(commitId));
}
@Override
@@ -16,7 +16,9 @@
package com.intellij.vcs.log.data;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.vcs.log.CommitId;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsRef;
@@ -49,13 +51,28 @@ public interface VcsLogStorage {
@Nullable
CommitId getCommitId(int commitIndex);
/**
* Iterates over known commit ids. Stops when consumer returns true.
*/
void iterateCommits(@NotNull Function<CommitId, Boolean> consumer);
/**
* Iterates over known commit ids to find the first one which satisfies given condition.
*
* @return matching commit or null if no commit matches the given condition
*/
@Nullable
CommitId findCommitId(@NotNull Condition<CommitId> condition);
default CommitId findCommitId(@NotNull Condition<CommitId> condition) {
Ref<CommitId> hashRef = Ref.create();
iterateCommits(commitId -> {
boolean matches = condition.value(commitId);
if (matches) {
hashRef.set(commitId);
}
return matches;
});
return hashRef.get();
}
/**
* Returns an integer index that is a unique identifier for a reference.
@@ -126,26 +126,18 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
}
@Override
@Nullable
public CommitId findCommitId(@NotNull final Condition<CommitId> condition) {
public void iterateCommits(@NotNull Function<CommitId, Boolean> consumer) {
checkDisposed();
try {
final Ref<CommitId> hashRef = Ref.create();
myCommitIdEnumerator.iterateData(new CommonProcessors.FindProcessor<CommitId>() {
@Override
protected boolean accept(CommitId commitId) {
boolean matches = condition.value(commitId);
if (matches) {
hashRef.set(commitId);
}
return matches;
return consumer.fun(commitId);
}
});
return hashRef.get();
}
catch (IOException e) {
myExceptionReporter.consume(this, e);
return null;
}
}
@@ -246,10 +238,8 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
throw new UnsupportedOperationException("Illegal access to empty hash map by index " + commitIndex);
}
@Nullable
@Override
public CommitId findCommitId(@NotNull Condition<CommitId> string) {
return null;
public void iterateCommits(@NotNull Function<CommitId, Boolean> consumer) {
}
@Override
@@ -43,7 +43,6 @@ import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.CommitId;
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.data.CommitIdByStringCondition;
import com.intellij.vcs.log.data.VcsLogData;
import com.intellij.vcs.log.ui.VcsLogColorManager;
import com.intellij.vcs.log.ui.frame.CommitPresentationUtil.CommitPresentation;
@@ -182,13 +181,19 @@ public class DetailsPanel extends JPanel implements EditorColorsListener, Dispos
if (!unResolvedHashes.isEmpty()) {
myResolveIndicator = BackgroundTaskUtil.executeOnPooledThread(this, () -> {
Map<String, CommitId> resolvedHashes = ContainerUtil.newHashMap();
myLogData.getStorage().iterateCommits(commitId -> {
Set<String> found = ContainerUtil.newHashSet();
for (String hashString : unResolvedHashes) {
for (String hashString : unResolvedHashes) {
CommitId commitId = myLogData.getStorage().findCommitId(new CommitIdByStringCondition(hashString));
if (commitId != null) {
resolvedHashes.put(hashString, commitId);
if (StringUtil.startsWithIgnoreCase(commitId.getHash().asString(), hashString)) {
resolvedHashes.put(hashString, commitId);
found.add(hashString);
// do not break, check all hashes (we can have several substrings of the same hash)
}
}
}
unResolvedHashes.removeAll(found);
return unResolvedHashes.isEmpty();
});
List<CommitPresentation> resolvedPresentations = ContainerUtil.map2List(presentations,
presentation -> presentation.resolve(resolvedHashes));
@@ -17,7 +17,6 @@ package com.intellij.vcs.log.visible
import com.intellij.mock.MockVirtualFile
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.util.Condition
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.Consumer
import com.intellij.util.Function
@@ -239,7 +238,7 @@ class VisiblePackBuilderTest {
override fun getRefIndex(ref: VcsRef): Int = refsReversed[ref]!!
override fun findCommitId(condition: Condition<CommitId>): CommitId? = throw UnsupportedOperationException()
override fun iterateCommits(consumer: Function<CommitId, Boolean>) = throw UnsupportedOperationException()
override fun flush() {
}