From 15b98239ea1044f7ed128c59d584fec9efa7831a Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Wed, 12 Apr 2017 19:23:41 +0300 Subject: [PATCH] [file-history] move code for loading diff in background to GitLogDiffHandler Reuse the code in all diff kinds. This way actions would not need to manage background execution themselves. --- .../intellij/vcs/log/VcsLogDiffHandler.java | 6 +- .../CompareRevisionsFromHistoryAction.java | 19 +-- .../src/git4idea/log/GitLogDiffHandler.java | 152 ++++++++++++------ 3 files changed, 104 insertions(+), 73 deletions(-) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java index 826fe76e0252..f334465a062f 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDiffHandler.java @@ -16,7 +16,6 @@ package com.intellij.vcs.log; import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,10 +23,9 @@ import org.jetbrains.annotations.Nullable; public interface VcsLogDiffHandler { void showDiff(@NotNull VirtualFile root, @Nullable FilePath leftPath, @NotNull Hash leftHash, - @Nullable FilePath rightPath, @NotNull Hash rightHash) throws VcsException; + @Nullable FilePath rightPath, @NotNull Hash rightHash); void showDiffWithLocal(@NotNull VirtualFile root, @Nullable FilePath revisionPath, - @NotNull Hash hash, @NotNull FilePath localPath) - throws VcsException; + @NotNull Hash hash, @NotNull FilePath localPath); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java index b98c57ebce43..dea68d90358e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/history/CompareRevisionsFromHistoryAction.java @@ -117,24 +117,7 @@ public class CompareRevisionsFromHistoryAction extends AnAction implements DumbA // so that it could return a single file path for each revision VcsFullCommitDetails newestDetail = details.get(0); VcsFullCommitDetails olderDetail = details.get(1); - ProgressIndicator indicator = ui.getLogData().getProgress().createProgressIndicator(true); - ProgressManager.getInstance() - .runProcessWithProgressAsynchronously(new Task.Backgroundable(project, "Comparing Revisions...", false) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - try { - notNull(handler).showDiff(root, ui.getPath(olderDetail), olderDetail.getId(), ui.getPath(newestDetail), newestDetail.getId()); - } - catch (VcsException e1) { - VcsBalloonProblemNotifier.showOverVersionControlView(project, "Could not compare revisions " + - olderDetail.getId().asString() + - " and " + - newestDetail.getId().asString() + - "\n" + - e1.getMessage(), MessageType.ERROR); - } - } - }, indicator); + notNull(handler).showDiff(root, ui.getPath(olderDetail), olderDetail.getId(), ui.getPath(newestDetail), newestDetail.getId()); } else if (details.size() == 1) { VcsFullCommitDetails detail = notNull(ContainerUtil.getFirstItem(details)); diff --git a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java index 06a3918bf092..42c1cb59ec89 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java +++ b/plugins/git4idea/src/git4idea/log/GitLogDiffHandler.java @@ -23,15 +23,21 @@ import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.requests.DiffRequest; import com.intellij.diff.requests.SimpleDiffRequest; import com.intellij.diff.util.DiffUserDataKeysEx; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.history.VcsDiffUtil; +import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.WaitForProgressToShow; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLogDiffHandler; @@ -39,11 +45,11 @@ import com.intellij.vcsUtil.VcsFileUtil; import git4idea.GitRevisionNumber; import git4idea.changes.GitChangeUtils; import git4idea.util.GitFileUtils; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Collection; import java.util.Collections; import java.util.Objects; @@ -65,87 +71,131 @@ public class GitLogDiffHandler implements VcsLogDiffHandler { @Nullable FilePath leftPath, @NotNull Hash leftHash, @Nullable FilePath rightPath, - @NotNull Hash rightHash) throws VcsException { + @NotNull Hash rightHash) { if (leftPath == null && rightPath == null) return; if (chooseNotNull(leftPath, rightPath).isDirectory()) { showDiffForDirectory(root, chooseNotNull(leftPath, rightPath), leftHash, rightHash); } else { - try { - DiffContent leftDiffContent = createDiffContent(root, leftPath, leftHash); - DiffContent rightDiffContent = createDiffContent(root, rightPath, rightHash); + loadDiffAndShow(new ThrowableComputable() { + @Override + public DiffRequest compute() throws VcsException { + DiffContent leftDiffContent = createDiffContent(root, leftPath, leftHash); + DiffContent rightDiffContent = createDiffContent(root, rightPath, rightHash); - DiffRequest request = new SimpleDiffRequest(getTitle(leftPath, rightPath), - leftDiffContent, rightDiffContent, - leftHash.asString(), rightHash.asString()); - - WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> DiffManager.getInstance().showDiff(myProject, request), null, myProject); - } - catch (IOException e) { - LOG.error(e); - } + return new SimpleDiffRequest(getTitle(leftPath, rightPath), + leftDiffContent, rightDiffContent, + leftHash.asString(), rightHash.asString()); + } + }, + request -> DiffManager.getInstance().showDiff(myProject, request), + "Calculating Diff for " + chooseNotNull(rightPath, leftPath).getName()); } } @Override public void showDiffWithLocal(@NotNull VirtualFile root, @Nullable FilePath revisionPath, @NotNull Hash revisionHash, - @NotNull FilePath localPath) - throws VcsException { + @NotNull FilePath localPath) { if (localPath.isDirectory()) { showDiffForDirectory(root, localPath, revisionHash, null); } else { - try { - DiffContent leftDiffContent = createDiffContent(root, revisionPath, revisionHash); + loadDiffAndShow(new ThrowableComputable() { + @Override + public DiffRequest compute() throws VcsException { + DiffContent leftDiffContent = createDiffContent(root, revisionPath, revisionHash); - VirtualFile file = localPath.getVirtualFile(); - LOG.assertTrue(file != null); - DiffContent rightDiffContent = myDiffContentFactory.create(myProject, file); + VirtualFile file = localPath.getVirtualFile(); + LOG.assertTrue(file != null); + DiffContent rightDiffContent = myDiffContentFactory.create(myProject, file); - DiffRequest request = new SimpleDiffRequest(getTitle(revisionPath, localPath), - leftDiffContent, rightDiffContent, - revisionHash.asString(), "(Local)"); - - WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> DiffManager.getInstance().showDiff(myProject, request), null, myProject); - } - catch (IOException e) { - LOG.error(e); - } + return new SimpleDiffRequest(getTitle(revisionPath, localPath), + leftDiffContent, rightDiffContent, + revisionHash.asString(), "(Local)"); + } + }, + request -> DiffManager.getInstance().showDiff(myProject, request), "Calculating Diff for " + localPath.getName()); } } private void showDiffForDirectory(@NotNull VirtualFile root, @NotNull FilePath directoryPath, - @NotNull Hash leftRevision, @Nullable Hash rightRevision) throws VcsException { - Collection diff = GitChangeUtils.getDiff(myProject, root, - leftRevision.asString(), rightRevision == null ? null : rightRevision.asString(), - Collections.singleton(directoryPath)); - WaitForProgressToShow.runOrInvokeLaterAboveProgress(() -> { - String dialogTitle = "Changes between " + - leftRevision.asString() + - " and " + - (rightRevision == null ? "current revision" : rightRevision.asString()) + - " in " + - getTitle(directoryPath, directoryPath); - VcsDiffUtil.showChangesDialog(myProject, dialogTitle, - ContainerUtil.newArrayList(diff)); - }, - null, - myProject); + @NotNull Hash leftRevision, @Nullable Hash rightRevision) { + loadDiffAndShow(() -> GitChangeUtils.getDiff(myProject, root, + leftRevision.asString(), rightRevision == null ? null : rightRevision.asString(), + Collections.singleton(directoryPath)), + (diff) -> { + String dialogTitle = "Changes between " + + leftRevision.asString() + + " and " + + (rightRevision == null ? "current revision" : rightRevision.asString()) + + " in " + + getTitle(directoryPath, directoryPath); + VcsDiffUtil.showChangesDialog(myProject, dialogTitle, ContainerUtil.newArrayList(diff)); + }, "Calculating Diff for " + directoryPath.getName()); + } + + private void loadDiffAndShow(@NotNull ThrowableComputable load, + @NotNull Consumer show, + @NotNull @Nls(capitalization = Nls.Capitalization.Title) String title) { + if (ApplicationManager.getApplication().isDispatchThread()) { + ProgressManager.getInstance().run(new Task.Backgroundable(myProject, title + "...", false) { + @Nullable private T myResult; + + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + myResult = load.compute(); + } + catch (VcsException e) { + throw new RuntimeException(e); + } + } + + @Override + public void onSuccess() { + if (myResult != null) { + show.consume(myResult); + } + } + + @Override + public void onThrowable(@NotNull Throwable error) { + VcsBalloonProblemNotifier.showOverVersionControlView(myProject, title + " failed\n" + + error.getMessage(), MessageType.ERROR); + } + }); + } + else { + try { + T result = load.compute(); + ApplicationManager.getApplication().invokeLater(() -> show.consume(result)); + } + catch (VcsException e) { + VcsBalloonProblemNotifier.showOverVersionControlView(myProject, title + " failed\n" + + e.getMessage(), MessageType.ERROR); + } + } } @NotNull private DiffContent createDiffContent(@NotNull VirtualFile root, @Nullable FilePath path, - @NotNull Hash hash) throws IOException, VcsException { + @NotNull Hash hash) throws VcsException { + DiffContent diffContent; if (path == null) { diffContent = new EmptyContent(); } else { - byte[] content = GitFileUtils.getFileContent(myProject, root, hash.asString(), VcsFileUtil.relativePath(root, path)); - diffContent = myDiffContentFactory.createFromBytes(myProject, content, path); + try { + byte[] content = GitFileUtils.getFileContent(myProject, root, hash.asString(), VcsFileUtil.relativePath(root, path)); + diffContent = myDiffContentFactory.createFromBytes(myProject, content, path); + } + catch (IOException e) { + throw new VcsException(e); + } } diffContent.putUserData(DiffUserDataKeysEx.REVISION_INFO, new Pair<>(path, new GitRevisionNumber(hash.asString())));