[vcs-log] internal action for printing index information for commits into log file

This commit is contained in:
Julia Beliaeva
2016-09-20 00:15:17 +03:00
parent b5777a1e26
commit be6a964063
7 changed files with 188 additions and 3 deletions
@@ -53,7 +53,9 @@
<action class="com.intellij.vcs.log.ui.actions.CloseLogTabAction" id="Vcs.Log.CloseLogTabAction"/>
<action class="com.intellij.vcs.log.ui.actions.RefreshLogAction" id="Vcs.Log.Refresh" use-shortcut-of="Refresh"/>
<action class="com.intellij.vcs.log.ui.actions.ShowGraphHistoryAction" id="Vcs.Show.Graph.History"
text="Show History as Graph" description="Show History as Graph"/>
text="Show History as Graph" description="Show History as Graph" internal="true"/>
<action class="com.intellij.vcs.log.ui.actions.PrintIndexInfoAction" id="Vcs.Log.Print.Index.Info"
text="Print Index Info" description="Print Index Info for a Commit into Log File" internal="true"/>
<group id="Vcs.Log.Settings">
<reference id="Vcs.Log.ShowRootsColumnAction"/>
@@ -74,10 +76,12 @@
<group id="Vcs.Log.ContextMenu">
<reference id="Vcs.CopyRevisionNumberAction"/>
<reference id="Vcs.Log.CreatePatch"/>
<reference id="Vcs.Log.Print.Index.Info"/>
</group>
<group id="Log.KeymapGroup" text="Log">
<reference ref="Vcs.Log.CreatePatch"/>
<reference ref="Vcs.Log.Print.Index.Info"/>
<separator/>
<reference ref="Vcs.Log.GoToRef"/>
<reference ref="Vcs.Log.FocusTextFilter"/>
@@ -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<T> implements Disposable {
return new File(subdir, safeLogId + "." + version);
}
@Nullable
protected Collection<Integer> getKeysForCommit(int commit) throws IOException {
return myMapReduceIndex.getInputsIndex().get(commit);
}
private class MyMapReduceIndex extends MapReduceIndex<Integer, T, VcsFullCommitDetails> {
public MyMapReduceIndex(@NotNull DataIndexer<Integer, T, VcsFullCommitDetails> indexer,
@@ -160,6 +165,11 @@ public class VcsLogFullDetailsIndex<T> implements Disposable {
externalizer, 5000));
}
@NotNull
public PersistentHashMap<Integer, Collection<Integer>> getInputsIndex() {
return myInputsIndex;
}
public boolean isIndexed(int commitId) throws IOException {
return myInputsIndex.containsMapping(commitId);
}
@@ -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<Void> {
@@ -97,6 +98,26 @@ public class VcsLogMessagesTrigramIndex extends VcsLogFullDetailsIndex<Void> {
myNoTrigramsCommits.markCorrupted();
}
@NotNull
public String getTrigramInfo(int commit) throws IOException {
if (myNoTrigramsCommits.containsMapping(commit)) {
return "No trigrams";
}
Collection<Integer> 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<Integer, Void, VcsFullCommitDetails> {
@NotNull
@Override
@@ -168,6 +168,20 @@ public class VcsLogPathsIndex extends VcsLogFullDetailsIndex<Integer> {
myEmptyCommits.markCorrupted();
}
@NotNull
public String getPathInfo(int commit) throws IOException {
if (myEmptyCommits.containsMapping(commit)) {
return "No paths";
}
Collection<Integer> 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<Integer, Integer, VcsFullCommitDetails> {
@NotNull private final PersistentEnumeratorBase<String> myPathsEnumerator;
@NotNull private final Set<String> myRoots;
@@ -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<VirtualFile, TIntHashSet> 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;
@@ -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<Void> {
return getCommitsWithAnyKey(ids);
}
@NotNull
public String getUserInfo(int commit) throws IOException {
Collection<Integer> 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<Integer, Void, VcsFullCommitDetails> {
@NotNull private final VcsUserRegistryImpl myRegistry;
@NotNull private Consumer<Exception> myFatalErrorConsumer = LOG::error;
@@ -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<CommitId> 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);
}
}