[patch]: add an ability to call getBaseVersionContent from any Thread

* use Task.WithResult instead of VcsUtil.runVcsProcessWithProgress which
 is EDT required method;
* optimize try/catch blocks;
* add annotation;
This commit is contained in:
Nadya Zabrodina
2017-05-17 17:22:45 +03:00
parent 06a7e1d503
commit 5f0ed26635
2 changed files with 82 additions and 57 deletions
@@ -101,7 +101,7 @@ column.name.revisions.list.branch=Branch
column.name.revision.list.revision=Revision
lookup.title.vcs.file.revisions=File Revisions
border.selected.revision.commit.message=Commit message
loading.file.history.progress=Loading file history
loading.file.history.progress=Loading File History
message.title.could.not.load.file.history=Problems while loading file history
diff.content.title.repository.version={0} ( Repository Version )
action.name.file.history=File {0} History
@@ -173,7 +173,7 @@ column.name.revision.list.message=Message
column.name.revision.list.date=Date
checkbox.show.changed.revisions.only=Changes only
dialog.title.history.for.file=History for File {0}
progress.text2.loading.revision=Loading revision {0}
progress.text2.loading.revision=Loading Revision {0}
message.text.cannot.load.version.because.of.error=Cannot load version {0}:{1}
message.title.load.version=Load Version
progress.title.loading.contents=Loading Contents
@@ -18,16 +18,25 @@ package com.intellij.openapi.vcs.changes.patch;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.progress.ProcessCanceledException;
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.util.Ref;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.diff.DiffProvider;
import com.intellij.openapi.vcs.history.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.intellij.vcsUtil.VcsRunnable;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.CalledInAny;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Date;
@@ -35,6 +44,8 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.intellij.openapi.vcs.VcsBundle.message;
public class DefaultPatchBaseVersionProvider {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.patch.DefaultPatchBaseVersionProvider");
private final static Pattern ourTsPattern = Pattern.compile("\\(date ([0-9]+)\\)");
@@ -61,6 +72,7 @@ public class DefaultPatchBaseVersionProvider {
myRevisionPattern = null;
}
@CalledInAny
public void getBaseVersionContent(final FilePath filePath,
final Processor<CharSequence> processor,
final List<String> warnings) throws VcsException {
@@ -76,32 +88,31 @@ public class DefaultPatchBaseVersionProvider {
if (matcher.find()) {
revision = myVcs.parseRevisionNumber(matcher.group(1), filePath);
final VcsRevisionNumber finalRevision = revision;
final Boolean[] loadedExactRevision = new Boolean[1];
if (historyProvider instanceof VcsBaseRevisionAdviser) {
final boolean success = VcsUtil.runVcsProcessWithProgress(new VcsRunnable() {
public void run() throws VcsException {
loadedExactRevision[0] = ((VcsBaseRevisionAdviser)historyProvider).getBaseVersionContent(filePath, processor, finalRevision.asString(), warnings);
}
}, VcsBundle.message("progress.text2.loading.revision", revision.asString()), true, myProject);
// was cancelled
if (! success) return;
} else {
// use diff provider
final DiffProvider diffProvider = myVcs.getDiffProvider();
if (diffProvider != null && filePath.getVirtualFile() != null) {
final ContentRevision fileContent = diffProvider.createFileContent(finalRevision, filePath.getVirtualFile());
final boolean success = VcsUtil.runVcsProcessWithProgress(new VcsRunnable() {
public void run() throws VcsException {
loadedExactRevision[0] = ! processor.process(fileContent.getContent());
}
}, VcsBundle.message("progress.text2.loading.revision", revision.asString()), true, myProject);
// was cancelled
if (! success) return;
}
try {
final boolean loadedExactRevision = finalRevision != null &&
computeInBackgroundTask(myProject,
message("progress.text2.loading.revision", finalRevision.asString()),
true, () -> {
if (historyProvider instanceof VcsBaseRevisionAdviser) {
return ((VcsBaseRevisionAdviser)historyProvider)
.getBaseVersionContent(filePath, processor, finalRevision.asString(), warnings);
}
else {
// use diff provider
final DiffProvider diffProvider = myVcs.getDiffProvider();
if (diffProvider != null && filePath.getVirtualFile() != null) {
final ContentRevision fileContent =
diffProvider.createFileContent(finalRevision, filePath.getVirtualFile());
return fileContent != null && !processor.process(fileContent.getContent());
}
return false;
}
});
if (loadedExactRevision) return;
}
catch (ProcessCanceledException pce) {
return;
}
if (Boolean.TRUE.equals(loadedExactRevision[0])) return;
}
}
@@ -121,40 +132,42 @@ public class DefaultPatchBaseVersionProvider {
return;
}
}
try {
final Ref<VcsHistorySession> ref = new Ref<>();
boolean result = VcsUtil.runVcsProcessWithProgress(new VcsRunnable() {
public void run() throws VcsException {
ref.set(historyProvider.createSessionFor(filePath));
}
}, VcsBundle.message("loading.file.history.progress"), true, myProject);
//if not found or cancelled
if (ref.isNull() || !result) return;
final VcsHistorySession session = ref.get();
final List<VcsFileRevision> list = session.getRevisionList();
if (list == null) return;
for (VcsFileRevision fileRevision : list) {
boolean found;
if (revision != null) {
found = fileRevision.getRevisionNumber().compareTo(revision) <= 0;
}
else {
final Date date = fileRevision instanceof VcsFileRevisionEx ?
((VcsFileRevisionEx) fileRevision).getAuthorDate() : fileRevision.getRevisionDate();
found = (date != null) && (date.before(versionDate) || date.equals(versionDate));
}
if (found) {
final VcsHistorySession historySession;
try {
historySession = computeInBackgroundTask(myProject, message("loading.file.history.progress"), true,
() -> historyProvider.createSessionFor(filePath));
}
catch (ProcessCanceledException e) {
return;
}
//if not found or cancelled
if (historySession == null) return;
final List<VcsFileRevision> list = historySession.getRevisionList();
if (list == null) return;
for (VcsFileRevision fileRevision : list) {
boolean found;
if (revision != null) {
found = fileRevision.getRevisionNumber().compareTo(revision) <= 0;
}
else {
final Date date = fileRevision instanceof VcsFileRevisionEx ?
((VcsFileRevisionEx)fileRevision).getAuthorDate() : fileRevision.getRevisionDate();
found = (date != null) && (date.before(versionDate) || date.equals(versionDate));
}
if (found) {
try {
fileRevision.loadContent();
processor.process(LoadTextUtil.getTextByBinaryPresentation(fileRevision.getContent(), myFile, false, false));
// TODO: try to download more than one version
break;
}
catch (IOException e) {
LOG.error(e);
}
}
}
catch (IOException e) {
LOG.error(e);
}
}
public boolean canProvideContent() {
@@ -194,4 +207,16 @@ public class DefaultPatchBaseVersionProvider {
}
return null;
}
public static <T, E extends Exception> T computeInBackgroundTask(@Nullable Project project,
@Nls(capitalization = Nls.Capitalization.Title) @NotNull String title,
boolean canBeCancelled,
@NotNull ThrowableComputable<T, E> computable) throws E {
return ProgressManager.getInstance().run(new Task.WithResult<T, E>(project, title, canBeCancelled) {
@Override
protected T compute(@NotNull ProgressIndicator indicator) throws E {
return computable.compute();
}
});
}
}