diff --git a/platform/vcs-log/impl/src/META-INF/vcs-log.xml b/platform/vcs-log/impl/src/META-INF/vcs-log.xml
index 4f29c871f8ba..0ebca68491a2 100644
--- a/platform/vcs-log/impl/src/META-INF/vcs-log.xml
+++ b/platform/vcs-log/impl/src/META-INF/vcs-log.xml
@@ -53,7 +53,9 @@
+ text="Show History as Graph" description="Show History as Graph" internal="true"/>
+
@@ -74,10 +76,12 @@
+
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogFullDetailsIndex.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogFullDetailsIndex.java
index 4ffe35533079..1ac482522e6f 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogFullDetailsIndex.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogFullDetailsIndex.java
@@ -17,7 +17,6 @@ package com.intellij.vcs.log.data.index;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
import com.intellij.util.Consumer;
import com.intellij.util.PathUtilRt;
import com.intellij.util.indexing.*;
@@ -26,6 +25,7 @@ import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.util.PersistentUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@@ -149,6 +149,11 @@ public class VcsLogFullDetailsIndex implements Disposable {
return new File(subdir, safeLogId + "." + version);
}
+ @Nullable
+ protected Collection getKeysForCommit(int commit) throws IOException {
+ return myMapReduceIndex.getInputsIndex().get(commit);
+ }
+
private class MyMapReduceIndex extends MapReduceIndex {
public MyMapReduceIndex(@NotNull DataIndexer indexer,
@@ -160,6 +165,11 @@ public class VcsLogFullDetailsIndex implements Disposable {
externalizer, 5000));
}
+ @NotNull
+ public PersistentHashMap> getInputsIndex() {
+ return myInputsIndex;
+ }
+
public boolean isIndexed(int commitId) throws IOException {
return myInputsIndex.containsMapping(commitId);
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogMessagesTrigramIndex.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogMessagesTrigramIndex.java
index 4e286fa3bfca..b96dda768209 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogMessagesTrigramIndex.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogMessagesTrigramIndex.java
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
+import java.util.Collection;
import java.util.Map;
public class VcsLogMessagesTrigramIndex extends VcsLogFullDetailsIndex {
@@ -97,6 +98,26 @@ public class VcsLogMessagesTrigramIndex extends VcsLogFullDetailsIndex {
myNoTrigramsCommits.markCorrupted();
}
+ @NotNull
+ public String getTrigramInfo(int commit) throws IOException {
+ if (myNoTrigramsCommits.containsMapping(commit)) {
+ return "No trigrams";
+ }
+
+ Collection keys = getKeysForCommit(commit);
+ assert keys != null;
+
+ StringBuilder builder = new StringBuilder();
+ for (Integer key : keys) {
+ builder.append((char)(key >> 16));
+ builder.append((char)((key >> 8) % 256));
+ builder.append((char)(key % 256));
+ builder.append(" ");
+ }
+
+ return builder.toString();
+ }
+
public static class TrigramMessageIndexer implements DataIndexer {
@NotNull
@Override
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPathsIndex.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPathsIndex.java
index daf5ac4f09ac..fa4dc6b372a8 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPathsIndex.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPathsIndex.java
@@ -168,6 +168,20 @@ public class VcsLogPathsIndex extends VcsLogFullDetailsIndex {
myEmptyCommits.markCorrupted();
}
+ @NotNull
+ public String getPathInfo(int commit) throws IOException {
+ if (myEmptyCommits.containsMapping(commit)) {
+ return "No paths";
+ }
+ Collection keys = getKeysForCommit(commit);
+ assert keys != null;
+ StringBuilder builder = new StringBuilder();
+ for (int key : keys) {
+ builder.append(myPathsIndexer.getPathsEnumerator().valueOf(key)).append("\n");
+ }
+ return builder.toString();
+ }
+
private static class PathsIndexer implements DataIndexer {
@NotNull private final PersistentEnumeratorBase myPathsEnumerator;
@NotNull private final Set myRoots;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java
index 80a8c762e9c1..ddebff28b9d1 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogPersistentIndex.java
@@ -374,6 +374,44 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
}
}
+ public void printDebugInfoForCommit(@NotNull CommitId commitId) {
+ int commit = myHashMap.getCommitIndex(commitId.getHash(), commitId.getRoot());
+ if (!isIndexed(commit)) {
+ LOG.info("Commit " + commitId.getHash().asString() + " is not indexed.");
+ }
+ else {
+ StringBuilder builder = new StringBuilder();
+ try {
+ builder.append("Commit ").append(commitId.getHash().asString()).append(" index info:\n");
+
+ builder.append("Message:\n").append(myMessagesIndex.get(commit)).append("\n");
+ if (myTrigramIndex != null) {
+ builder.append("Trigrams:\n").append(myTrigramIndex.getTrigramInfo(commit)).append("\n");
+ }
+ else {
+ builder.append("Trigrams index is null");
+ }
+ if (myUserIndex != null) {
+ builder.append("User:\n").append(myUserIndex.getUserInfo(commit)).append("\n");
+ }
+ else {
+ builder.append("User index is null");
+ }
+ if (myPathsIndex != null) {
+ builder.append("Paths:\n").append(myPathsIndex.getPathInfo(commit)).append("\n");
+ }
+ else {
+ builder.append("Paths index is null");
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+
+ LOG.info(builder.toString());
+ }
+ }
+
private class MyIndexingTask extends Task.Backgroundable {
private static final int MAGIC_NUMBER = 150000;
private final Map myCommits;
@@ -506,8 +544,8 @@ public class VcsLogPersistentIndex implements VcsLogIndex, Disposable {
flush();
}
-
}
+
private static class CommitsCounter {
@NotNull public final ProgressIndicator indicator;
public final int allCommits;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogUserIndex.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogUserIndex.java
index f7ed31cc5cd3..5338d9a2f79d 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogUserIndex.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/index/VcsLogUserIndex.java
@@ -18,6 +18,7 @@ package com.intellij.vcs.log.data.index;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Consumer;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.DataIndexer;
import com.intellij.util.indexing.ScalarIndexExtension;
@@ -31,6 +32,7 @@ import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
+import java.util.Collection;
import java.util.Map;
import java.util.Set;
@@ -59,6 +61,14 @@ public class VcsLogUserIndex extends VcsLogFullDetailsIndex {
return getCommitsWithAnyKey(ids);
}
+ @NotNull
+ public String getUserInfo(int commit) throws IOException {
+ Collection keys = getKeysForCommit(commit);
+ assert keys != null;
+ assert keys.size() == 1;
+ return ObjectUtils.assertNotNull(myUserRegistry.getUserById(ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(keys)))).toString();
+ }
+
private static class UserIndexer implements DataIndexer {
@NotNull private final VcsUserRegistryImpl myRegistry;
@NotNull private Consumer myFatalErrorConsumer = LOG::error;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/PrintIndexInfoAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/PrintIndexInfoAction.java
new file mode 100644
index 000000000000..6af11fef8d8a
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/PrintIndexInfoAction.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2016 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.ui.actions;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.vcs.log.CommitId;
+import com.intellij.vcs.log.VcsLog;
+import com.intellij.vcs.log.VcsLogDataKeys;
+import com.intellij.vcs.log.data.VcsLogData;
+import com.intellij.vcs.log.data.index.VcsLogIndex;
+import com.intellij.vcs.log.data.index.VcsLogPersistentIndex;
+import com.intellij.vcs.log.impl.VcsProjectLog;
+
+import java.util.List;
+
+public class PrintIndexInfoAction extends DumbAwareAction {
+ @Override
+ public void update(AnActionEvent e) {
+ Presentation presentation = e.getPresentation();
+ if (!Registry.is("vcs.log.highlight.not.indexed")) {
+ presentation.setEnabledAndVisible(false);
+ }
+ else {
+ Project project = e.getProject();
+ VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG);
+ if (project == null || log == null) {
+ presentation.setEnabledAndVisible(false);
+ }
+ else {
+ VcsLogData dataManager = VcsProjectLog.getInstance(project).getDataManager();
+ if (dataManager == null) {
+ presentation.setEnabledAndVisible(false);
+ }
+ else {
+ VcsLogIndex index = dataManager.getIndex();
+ if (!(index instanceof VcsLogPersistentIndex)) {
+ presentation.setEnabledAndVisible(false);
+ }
+ else {
+ presentation.setEnabledAndVisible(!log.getSelectedCommits().isEmpty());
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getProject();
+ VcsLog log = e.getData(VcsLogDataKeys.VCS_LOG);
+ if (project == null || log == null) {
+ return;
+ }
+ VcsLogData dataManager = VcsProjectLog.getInstance(project).getDataManager();
+ if (dataManager == null) return;
+ VcsLogIndex index = dataManager.getIndex();
+ if (!(index instanceof VcsLogPersistentIndex)) return;
+
+ List commits = log.getSelectedCommits();
+ for (CommitId commit : commits) {
+ ((VcsLogPersistentIndex)index).printDebugInfoForCommit(commit);
+ }
+ VcsBalloonProblemNotifier.showOverChangesView(project, "Index information for " +
+ commits.size() + " " +
+ StringUtil.pluralize("commit", commits.size()) +
+ " was written into log file", MessageType.INFO);
+ }
+}