Obtaining all revisions in a file history

Answered

Hello! I'm trying to develop a plugin that has an action which should take all of the commits from a file history window and perform some operations using the diffs between each revision. For example, the action would be invoked by clicking the circled button in the file history window for `Driver.java`.

I'm not sure if I'm going in the right direction but so far I have been looking through the implementation for the "Show History" action in: 

`src/com/intellij/history/integration/ui/actions/ShowHistoryAction.java`

to get an idea of how to develop my own action. After seeing this, I thought I should try to recreate the history dialog:

`src/com/intellij/history/integration/ui/views/HistoryDialog.java`

as I thought this might be the way to get access to the history dialog's list of revisions through its method `getRevisions()`. However, since the method is protected, I think there must be a better or simpler way? 

I tried playing around with the information obtained from `VcsDataKeys` such as:
 `VcsFileRevision[] revisions = e.getData(VcsDataKeys.VCS_FILE_REVISIONS);` but found that when I called my action, which I registered to the group `Vcs.FileHistory.Toolbar`, it only gives access to the revision that was selected when the action was called. My desired behaviour is to get all of the revisions in the file history when the action is called.

From reading some old forum posts, I saw `TabbedShowHistoryAction.java` might be what I need to look at. However, I was confused at the difference between mention of "old history" and "new history" .

Thank you for reading this and any direction anyone can provide!

EDIT (3/28/2022): I think I made some progress by taking a look at: `src/com/intellij/openapi/vcs/actions/TabbedShowHistoryForRevisionAction.java`. 

I currently have the following:

public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
FilePath filePath = e.getData(VcsDataKeys.FILE_PATH);

assert project != null;
AbstractVcs vcs = Objects.requireNonNull(getVcs(project, e.getData(VcsDataKeys.VCS)));
VcsHistoryProvider historyProvider = vcs.getVcsHistoryProvider();
try {
assert historyProvider != null;
VcsHistorySession historySession = historyProvider.createSessionFor(filePath);
assert historySession != null;
List<VcsFileRevision> revisionList = historySession.getRevisionList();
LOG.info((Throwable) revisionList); // obtained here
} catch (VcsException ex) {
ex.printStackTrace();
}
}
@Nullable
private static AbstractVcs getVcs(@NotNull Project project, @Nullable VcsKey vcsKey) {
return vcsKey == null ? null : ProjectLevelVcsManager.getInstance(project).findVcsByName(vcsKey.getName());
}

I'm currently running into the issue of getting all the `ContentRevision` for each revision though. I'm trying to do this through:

VirtualFile virtualFile = Objects.requireNonNull(e.getData(VcsDataKeys.VCS_VIRTUAL_FILE));
AbstractVcs vcs = Objects.requireNonNull(getVcs(project, vcsKey));
DiffProvider diffProvider = Objects.requireNonNull(vcs.getDiffProvider());
for (VcsFileRevision vcsFileRevision : revisionList) {
ContentRevision contentRevision = diffProvider.createFileContent(vcsFileRevision.getRevisionNumber(), virtualFile);
}

But am running into an issue where it seems the `createFileContent` method can't be called on an event dispatch thread: "access from event dispatch thread is not allowed".

2 comments
Comment actions Permalink

Hello! In case anyone else sees this post and would like to know, I managed to do this with the following:

AbstractVcs vcs = Objects.requireNonNull(getVcs(vcsKey));
VcsHistoryProvider historyProvider = Objects.requireNonNull(vcs.getVcsHistoryProvider());
try {
VcsHistorySession historySession = Objects.requireNonNull(historyProvider.createSessionFor(filePath));
return historySession.getRevisionList();
} catch (VcsException ex) {
ex.printStackTrace();
}
return null;
@Nullable
private AbstractVcs getVcs(@Nullable VcsKey vcsKey) {
return vcsKey == null ? null : ProjectLevelVcsManager.getInstance(this.project).findVcsByName(vcsKey.getName());
}
1
Comment actions Permalink

Hi, Alison Li,

Sorry for the late reply. Method `com.intellij.openapi.vcs.history.VcsHistoryProvider#createSessionFor` can't be called on the EDT, and also it does not return you commits in the file history window (it will call git to get a file history, or use a cached version, but this history will differ from what you see in the table). Currently, for retrieving data from the log ui we have `com.intellij.vcs.log.VcsLog` class, accessible from the data context by `com.intellij.vcs.log.VcsLogDataKeys#VCS_LOG`. But it only allows to get the data for the selected commits, not all commits. If you want to look at the arbitrary commits, you can try to use the following code:

FileHistoryUi logUi = e.getRequiredData(VcsLogInternalDataKeys.FILE_HISTORY_UI); // currently opened file history
VisibleGraph<Integer> visibleGraph = logUi.getDataPack().getVisibleGraph(); // file history graph
int rowsCount = visibleGraph.getVisibleCommitCount(); // total number of commits in the history
int row = 0; // as an example, let's look at the first row
Integer commitId = visibleGraph.getRowInfo(row).getCommit(); // id of the commit in this row
FilePath filePath = FileHistoryPaths.filePath(logUi.getDataPack(), commitId); // path to the file in this commit
Hash commitHash = logUi.getLogData().getMiniDetailsGetter().getCommitData(commitId).getId(); // commit hash
1

Please sign in to leave a comment.