mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[vcs] get rid of Continuation in PatchApplier, shelve and GitUpdateProcess
Substitute it with a more clear control flow. * PatchApplier: make ApplyPatchTask synchronous: it is executed from the EDT, so update the ChangeListManager in SYNCHRONOUS mode (modal task). * ShelveChangesManager: make unshelveChangeList synchronous as well, surround the part which needs to be called from the EDT by invokeAndWait. * GitUpdateProcess: substitute GitComplexProcess (which is continuation-based) with GitFreezingProcess (which does the same about blocking and freezing, but without the continuation logic). * GitStashChangesSaver#load doesn't actually throw a VcsException => remove
This commit is contained in:
+13
-39
@@ -26,7 +26,6 @@ import com.intellij.openapi.diff.impl.patch.apply.ApplyTextFilePatch;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypes;
|
||||
import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
|
||||
import com.intellij.openapi.progress.AsynchronousExecution;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -43,11 +42,10 @@ import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
import com.intellij.util.continuation.*;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -127,23 +125,12 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
return new FilesMover(clm, targetChangeList);
|
||||
}
|
||||
|
||||
@AsynchronousExecution
|
||||
@CalledInAwt
|
||||
public void execute() {
|
||||
execute(true);
|
||||
execute(true, false);
|
||||
}
|
||||
|
||||
@AsynchronousExecution
|
||||
public void execute(boolean showSuccessNotification) {
|
||||
final Continuation continuation = ApplicationManager.getApplication().isDispatchThread() ?
|
||||
Continuation.createFragmented(myProject, true) :
|
||||
Continuation.createForCurrentProgress(myProject, true);
|
||||
final GatheringContinuationContext initContext =
|
||||
new GatheringContinuationContext();
|
||||
scheduleSelf(showSuccessNotification, initContext, false);
|
||||
continuation.run(initContext.getList());
|
||||
}
|
||||
|
||||
public class ApplyPatchTask extends TaskDescriptor {
|
||||
public class ApplyPatchTask {
|
||||
private ApplyPatchStatus myStatus;
|
||||
private final boolean myShowNotification;
|
||||
private final boolean mySystemOperation;
|
||||
@@ -151,14 +138,12 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
private VcsShowConfirmationOption.Value myDeleteconfirmationvalue;
|
||||
|
||||
public ApplyPatchTask(final boolean showNotification, boolean systemOperation) {
|
||||
super("", Where.AWT);
|
||||
myShowNotification = showNotification;
|
||||
mySystemOperation = systemOperation;
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@Override
|
||||
public void run(ContinuationContext context) {
|
||||
public void run() {
|
||||
myRemainingPatches.addAll(myPatches);
|
||||
|
||||
final ApplyPatchStatus patchStatus = nonWriteActionPreCheck();
|
||||
@@ -179,7 +164,7 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
if(myShowNotification || !ApplyPatchStatus.SUCCESS.equals(myStatus)) {
|
||||
showApplyStatus(myProject, myStatus);
|
||||
}
|
||||
refreshFiles(trigger.getAffected(), context);
|
||||
refreshFiles(trigger.getAffected());
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@@ -240,9 +225,9 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
return new ApplyPatchTask(showSuccessNotification, silentAddDelete);
|
||||
}
|
||||
|
||||
@AsynchronousExecution
|
||||
public void scheduleSelf(boolean showSuccessNotification, @NotNull final ContinuationContext context, boolean silentAddDelete) {
|
||||
context.next(createApplyPart(showSuccessNotification, silentAddDelete));
|
||||
@CalledInAwt
|
||||
public void execute(boolean showSuccessNotification, boolean silentAddDelete) {
|
||||
createApplyPart(showSuccessNotification, silentAddDelete).run();
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@@ -289,7 +274,7 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
}
|
||||
directlyAffected.addAll(trigger.getAffected());
|
||||
final Consumer<Collection<FilePath>> mover = localChangeList == null ? null : createMover(project, localChangeList);
|
||||
refreshPassedFilesAndMoveToChangelist(project, null, directlyAffected, indirectlyAffected, mover);
|
||||
refreshPassedFilesAndMoveToChangelist(project, directlyAffected, indirectlyAffected, mover);
|
||||
showApplyStatus(project, result);
|
||||
return result;
|
||||
}
|
||||
@@ -347,12 +332,12 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
protected void refreshFiles(final Collection<FilePath> additionalDirectly, @Nullable final ContinuationContext context) {
|
||||
protected void refreshFiles(final Collection<FilePath> additionalDirectly) {
|
||||
final List<FilePath> directlyAffected = myVerifier.getDirectlyAffected();
|
||||
final List<VirtualFile> indirectlyAffected = myVerifier.getAllAffected();
|
||||
directlyAffected.addAll(additionalDirectly);
|
||||
|
||||
refreshPassedFilesAndMoveToChangelist(myProject, context, directlyAffected, indirectlyAffected, myToTargetListsMover);
|
||||
refreshPassedFilesAndMoveToChangelist(myProject, directlyAffected, indirectlyAffected, myToTargetListsMover);
|
||||
}
|
||||
|
||||
public List<FilePath> getDirectlyAffected() {
|
||||
@@ -365,14 +350,9 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
|
||||
@CalledInAwt
|
||||
public static void refreshPassedFilesAndMoveToChangelist(@NotNull final Project project,
|
||||
final ContinuationContext context,
|
||||
final Collection<FilePath> directlyAffected,
|
||||
final Collection<VirtualFile> indirectlyAffected,
|
||||
final Consumer<Collection<FilePath>> targetChangelistMover) {
|
||||
if (context != null) {
|
||||
context.suspend();
|
||||
}
|
||||
|
||||
final LocalFileSystem lfs = LocalFileSystem.getInstance();
|
||||
for (FilePath filePath : directlyAffected) {
|
||||
lfs.refreshAndFindFileByIoFile(filePath.getIOFile());
|
||||
@@ -386,11 +366,8 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
@Override
|
||||
public void run() {
|
||||
targetChangelistMover.consume(directlyAffected);
|
||||
if (context != null) {
|
||||
context.ping();
|
||||
}
|
||||
}
|
||||
}, InvokeAfterUpdateMode.BACKGROUND_CANCELLABLE,
|
||||
}, InvokeAfterUpdateMode.SYNCHRONOUS_CANCELLABLE,
|
||||
VcsBundle.message("change.lists.manager.move.changes.to.list"),
|
||||
new Consumer<VcsDirtyScopeManager>() {
|
||||
@Override
|
||||
@@ -400,9 +377,6 @@ public class PatchApplier<BinaryType extends FilePatch> {
|
||||
}, null);
|
||||
} else {
|
||||
markDirty(VcsDirtyScopeManager.getInstance(project), directlyAffected, indirectlyAffected);
|
||||
if (context != null) {
|
||||
context.ping();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -33,6 +33,7 @@ import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
@@ -52,6 +53,7 @@ public class ApplyPatchDefaultExecutor implements ApplyPatchExecutor<AbstractFil
|
||||
return null;
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@Override
|
||||
public void apply(MultiMap<VirtualFile, AbstractFilePatchInProgress> patchGroups,
|
||||
LocalChangeList localList,
|
||||
|
||||
+2
@@ -55,6 +55,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -287,6 +288,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper {
|
||||
return actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private void runExecutor(ApplyPatchExecutor executor) {
|
||||
final Collection<AbstractFilePatchInProgress> included = getIncluded();
|
||||
if (included.isEmpty()) return;
|
||||
|
||||
+52
-63
@@ -25,6 +25,7 @@ package com.intellij.openapi.vcs.changes.shelf;
|
||||
import com.intellij.ide.impl.ProjectUtil;
|
||||
import com.intellij.lifecycle.PeriodicalTasksCloser;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.impl.LaterInvocator;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
@@ -33,7 +34,6 @@ import com.intellij.openapi.diff.impl.patch.*;
|
||||
import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
|
||||
import com.intellij.openapi.diff.impl.patch.formove.CustomBinaryPatchApplier;
|
||||
import com.intellij.openapi.diff.impl.patch.formove.PatchApplier;
|
||||
import com.intellij.openapi.progress.AsynchronousExecution;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -52,13 +52,13 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.continuation.*;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.intellij.util.messages.Topic;
|
||||
import com.intellij.util.text.CharArrayCharSequence;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcsUtil.FilesProgress;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.CalledInAny;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -355,60 +355,55 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD
|
||||
}
|
||||
}
|
||||
|
||||
@AsynchronousExecution
|
||||
@CalledInAny
|
||||
public void unshelveChangeList(final ShelvedChangeList changeList,
|
||||
@Nullable final List<ShelvedChange> changes,
|
||||
@Nullable final List<ShelvedBinaryFile> binaryFiles,
|
||||
@Nullable final LocalChangeList targetChangeList,
|
||||
boolean showSuccessNotification) {
|
||||
final Continuation continuation = Continuation.createForCurrentProgress(myProject, true);
|
||||
final GatheringContinuationContext initContext = new GatheringContinuationContext();
|
||||
scheduleUnshelveChangeList(changeList, changes, binaryFiles, targetChangeList, showSuccessNotification, initContext, false,
|
||||
false, null, null);
|
||||
continuation.run(initContext.getList());
|
||||
unshelveChangeList(changeList, changes, binaryFiles, targetChangeList, showSuccessNotification, false, false, null, null);
|
||||
}
|
||||
|
||||
@AsynchronousExecution
|
||||
public void scheduleUnshelveChangeList(final ShelvedChangeList changeList,
|
||||
@Nullable final List<ShelvedChange> changes,
|
||||
@Nullable final List<ShelvedBinaryFile> binaryFiles,
|
||||
@Nullable final LocalChangeList targetChangeList,
|
||||
final boolean showSuccessNotification,
|
||||
final ContinuationContext context,
|
||||
final boolean systemOperation,
|
||||
final boolean reverse,
|
||||
final String leftConflictTitle,
|
||||
final String rightConflictTitle) {
|
||||
context.next(new TaskDescriptor("", Where.AWT) {
|
||||
@CalledInAny
|
||||
public void unshelveChangeList(final ShelvedChangeList changeList,
|
||||
@Nullable final List<ShelvedChange> changes,
|
||||
@Nullable final List<ShelvedBinaryFile> binaryFiles,
|
||||
@Nullable final LocalChangeList targetChangeList,
|
||||
final boolean showSuccessNotification,
|
||||
final boolean systemOperation,
|
||||
final boolean reverse,
|
||||
final String leftConflictTitle,
|
||||
final String rightConflictTitle) {
|
||||
final List<FilePatch> remainingPatches = new ArrayList<FilePatch>();
|
||||
|
||||
final CommitContext commitContext = new CommitContext();
|
||||
final List<TextFilePatch> textFilePatches;
|
||||
try {
|
||||
textFilePatches = loadTextPatches(myProject, changeList, changes, remainingPatches, commitContext);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
PatchApplier.showError(myProject, "Cannot load patch(es): " + e.getMessage(), true);
|
||||
return;
|
||||
}
|
||||
catch (PatchSyntaxException e) {
|
||||
PatchApplier.showError(myProject, "Cannot load patch(es): " + e.getMessage(), true);
|
||||
LOG.info(e);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<FilePatch> patches = new ArrayList<FilePatch>(textFilePatches);
|
||||
|
||||
final List<ShelvedBinaryFile> remainingBinaries = new ArrayList<ShelvedBinaryFile>();
|
||||
final List<ShelvedBinaryFile> binaryFilesToUnshelve = getBinaryFilesToUnshelve(changeList, binaryFiles, remainingBinaries);
|
||||
|
||||
for (final ShelvedBinaryFile shelvedBinaryFile : binaryFilesToUnshelve) {
|
||||
patches.add(new ShelvedBinaryFilePatch(shelvedBinaryFile));
|
||||
}
|
||||
|
||||
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run(ContinuationContext contextInner) {
|
||||
final List<FilePatch> remainingPatches = new ArrayList<FilePatch>();
|
||||
|
||||
final CommitContext commitContext = new CommitContext();
|
||||
final List<TextFilePatch> textFilePatches;
|
||||
try {
|
||||
textFilePatches = loadTextPatches(myProject, changeList, changes, remainingPatches, commitContext);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
PatchApplier.showError(myProject, "Cannot load patch(es): " + e.getMessage(), true);
|
||||
return;
|
||||
}
|
||||
catch (PatchSyntaxException e) {
|
||||
PatchApplier.showError(myProject, "Cannot load patch(es): " + e.getMessage(), true);
|
||||
LOG.info(e);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<FilePatch> patches = new ArrayList<FilePatch>(textFilePatches);
|
||||
|
||||
final List<ShelvedBinaryFile> remainingBinaries = new ArrayList<ShelvedBinaryFile>();
|
||||
final List<ShelvedBinaryFile> binaryFilesToUnshelve = getBinaryFilesToUnshelve(changeList, binaryFiles, remainingBinaries);
|
||||
|
||||
for (final ShelvedBinaryFile shelvedBinaryFile : binaryFilesToUnshelve) {
|
||||
patches.add(new ShelvedBinaryFilePatch(shelvedBinaryFile));
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final BinaryPatchApplier binaryPatchApplier = new BinaryPatchApplier();
|
||||
final PatchApplier<ShelvedBinaryFilePatch> patchApplier =
|
||||
new PatchApplier<ShelvedBinaryFilePatch>(myProject, myProject.getBaseDir(),
|
||||
@@ -416,24 +411,18 @@ public class ShelveChangesManager extends AbstractProjectComponent implements JD
|
||||
rightConflictTitle);
|
||||
patchApplier.setIsSystemOperation(systemOperation);
|
||||
|
||||
// after patch applier part
|
||||
contextInner.next(new TaskDescriptor("", Where.AWT) {
|
||||
@Override
|
||||
public void run(ContinuationContext context) {
|
||||
remainingPatches.addAll(patchApplier.getRemainingPatches());
|
||||
remainingPatches.addAll(patchApplier.getRemainingPatches());
|
||||
|
||||
if (remainingPatches.isEmpty() && remainingBinaries.isEmpty()) {
|
||||
recycleChangeList(changeList);
|
||||
}
|
||||
else {
|
||||
saveRemainingPatches(changeList, remainingPatches, remainingBinaries, commitContext);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (remainingPatches.isEmpty() && remainingBinaries.isEmpty()) {
|
||||
recycleChangeList(changeList);
|
||||
}
|
||||
else {
|
||||
saveRemainingPatches(changeList, remainingPatches, remainingBinaries, commitContext);
|
||||
}
|
||||
|
||||
patchApplier.scheduleSelf(showSuccessNotification, contextInner, systemOperation);
|
||||
patchApplier.execute(showSuccessNotification, systemOperation);
|
||||
}
|
||||
});
|
||||
}, ModalityState.defaultModalityState());
|
||||
}
|
||||
|
||||
private static List<TextFilePatch> loadTextPatches(final Project project,
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManagerEx;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.continuation.ContinuationContext;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.config.GitVcsSettings;
|
||||
@@ -108,8 +107,8 @@ public abstract class GitChangesSaver {
|
||||
* Loads local changes from stash or shelf, and sorts the changes back to the change lists they were before update.
|
||||
* @param context
|
||||
*/
|
||||
public void restoreLocalChanges(ContinuationContext context) {
|
||||
load(context);
|
||||
public void restoreLocalChanges() {
|
||||
load();
|
||||
}
|
||||
|
||||
public void notifyLocalChangesAreNotRestored() {
|
||||
@@ -138,9 +137,8 @@ public abstract class GitChangesSaver {
|
||||
|
||||
/**
|
||||
* Loads the changes - specific for chosen save strategy.
|
||||
* @param exceptionConsumer
|
||||
*/
|
||||
protected abstract void load(ContinuationContext exceptionConsumer);
|
||||
public abstract void load();
|
||||
|
||||
/**
|
||||
* @return true if there were local changes to save.
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList;
|
||||
import com.intellij.openapi.vcs.changes.shelf.ShelvedChangesViewManager;
|
||||
import com.intellij.openapi.vcs.impl.LocalChangesUnderRoots;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.continuation.ContinuationContext;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.i18n.GitBundle;
|
||||
@@ -85,13 +84,14 @@ public class GitShelveChangesSaver extends GitChangesSaver {
|
||||
myProgressIndicator.setText(oldProgressTitle);
|
||||
}
|
||||
|
||||
protected void load(ContinuationContext context) {
|
||||
@Override
|
||||
public void load() {
|
||||
if (myShelvedLists != null) {
|
||||
LOG.info("load ");
|
||||
String oldProgressTitle = myProgressIndicator.getText();
|
||||
myProgressIndicator.setText(GitBundle.getString("update.unshelving.changes"));
|
||||
for (ShelvedChangeList list : myShelvedLists.values()) {
|
||||
GitShelveUtils.doSystemUnshelve(myProject, list, myShelveManager, context,
|
||||
GitShelveUtils.doSystemUnshelve(myProject, list, myShelveManager,
|
||||
getConflictLeftPanelTitle(), getConflictRightPanelTitle());
|
||||
}
|
||||
myProgressIndicator.setText(oldProgressTitle);
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.command.undo.DocumentReference;
|
||||
import com.intellij.openapi.command.undo.DocumentReferenceManager;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.AsynchronousExecution;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
@@ -33,9 +32,6 @@ import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.continuation.ContinuationContext;
|
||||
import com.intellij.util.continuation.TaskDescriptor;
|
||||
import com.intellij.util.continuation.Where;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -47,53 +43,29 @@ import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitShelveUtils {
|
||||
private static final Logger LOG = Logger.getInstance(GitShelveUtils.class.getName());
|
||||
|
||||
/**
|
||||
* Perform system level unshelve operation
|
||||
*
|
||||
* @param project the project
|
||||
* @param shelvedChangeList the shelved change list
|
||||
* @param shelveManager the shelve manager
|
||||
*/
|
||||
@AsynchronousExecution
|
||||
public static void doSystemUnshelve(final Project project, final ShelvedChangeList shelvedChangeList,
|
||||
public static void doSystemUnshelve(final Project project,
|
||||
final ShelvedChangeList shelvedChangeList,
|
||||
final ShelveChangesManager shelveManager,
|
||||
final @NotNull ContinuationContext context,
|
||||
@Nullable final String leftConflictTitle, @Nullable final String rightConflictTitle) {
|
||||
@Nullable final String leftConflictTitle,
|
||||
@Nullable final String rightConflictTitle) {
|
||||
VirtualFile baseDir = project.getBaseDir();
|
||||
assert baseDir != null;
|
||||
final String projectPath = baseDir.getPath() + "/";
|
||||
final List<ShelvedChange> changes = shelvedChangeList.getChanges(project);
|
||||
context.next(new TaskDescriptor("Refreshing files before unshelve", Where.POOLED) {
|
||||
@Override
|
||||
public void run(ContinuationContext context) {
|
||||
LOG.info("doSystemUnshelve ");
|
||||
// The changes are temporary copied to the first local change list, the next operation will restore them back
|
||||
// Refresh files that might be affected by unshelve
|
||||
refreshFilesBeforeUnshelve(project, shelvedChangeList, projectPath);
|
||||
|
||||
LOG.info("doSystemUnshelve files refreshed. unshelving in AWT thread.");
|
||||
}
|
||||
}, new TaskDescriptor("", Where.AWT) {
|
||||
@Override
|
||||
public void run(ContinuationContext context) {
|
||||
LOG.info("Unshelving in UI thread. shelvedChangeList: " + shelvedChangeList);
|
||||
// we pass null as target change list for Patch Applier to do NOTHING with change lists
|
||||
shelveManager.scheduleUnshelveChangeList(shelvedChangeList, changes,
|
||||
shelvedChangeList.getBinaryFiles(), null, false, context, true,
|
||||
true, leftConflictTitle, rightConflictTitle);
|
||||
}
|
||||
}, new TaskDescriptor("", Where.AWT) {
|
||||
@Override
|
||||
public void run(ContinuationContext context) {
|
||||
markUnshelvedFilesNonUndoable(project, changes);
|
||||
}
|
||||
});
|
||||
LOG.info("refreshing files ");
|
||||
// The changes are temporary copied to the first local change list, the next operation will restore them back
|
||||
// Refresh files that might be affected by unshelve
|
||||
refreshFilesBeforeUnshelve(project, shelvedChangeList, projectPath);
|
||||
|
||||
LOG.info("Unshelving shelvedChangeList: " + shelvedChangeList);
|
||||
// we pass null as target change list for Patch Applier to do NOTHING with change lists
|
||||
List<ShelvedChange> changes = shelvedChangeList.getChanges(project);
|
||||
shelveManager.unshelveChangeList(shelvedChangeList, changes, shelvedChangeList.getBinaryFiles(), null, false, true,
|
||||
true, leftConflictTitle, rightConflictTitle);
|
||||
markUnshelvedFilesNonUndoable(project, changes);
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@@ -116,7 +88,7 @@ public class GitShelveUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void refreshFilesBeforeUnshelve(final Project project, ShelvedChangeList shelvedChangeList, String projectPath) {
|
||||
private static void refreshFilesBeforeUnshelve(final Project project, ShelvedChangeList shelvedChangeList, String projectPath) {
|
||||
HashSet<File> filesToRefresh = new HashSet<File>();
|
||||
for (ShelvedChange c : shelvedChangeList.getChanges(project)) {
|
||||
if (c.getBeforePath() != null) {
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.openapi.vcs.impl.LocalChangesUnderRoots;
|
||||
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.continuation.ContinuationContext;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
@@ -69,16 +68,7 @@ public class GitStashChangesSaver extends GitChangesSaver {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void load(@NotNull ContinuationContext context) {
|
||||
try {
|
||||
load();
|
||||
}
|
||||
catch (VcsException e) {
|
||||
context.handleException(e, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void load() throws VcsException {
|
||||
public void load() {
|
||||
for (VirtualFile root : myStashedRoots) {
|
||||
loadRoot(root);
|
||||
}
|
||||
@@ -129,7 +119,7 @@ public class GitStashChangesSaver extends GitChangesSaver {
|
||||
* Returns true if the root was loaded with conflict.
|
||||
* False is returned in all other cases: in the case of success and in case of some other error.
|
||||
*/
|
||||
private boolean loadRoot(final VirtualFile root) throws VcsException {
|
||||
private boolean loadRoot(final VirtualFile root) {
|
||||
LOG.info("loadRoot " + root);
|
||||
myProgressIndicator.setText(GitHandlerUtil.formatOperationName("Unstashing changes to", root));
|
||||
|
||||
|
||||
@@ -30,14 +30,9 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.impl.LocalChangesUnderRoots;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.continuation.ContinuationContext;
|
||||
import com.intellij.util.continuation.ContinuationFinalTasksInserter;
|
||||
import com.intellij.util.continuation.TaskDescriptor;
|
||||
import com.intellij.util.continuation.Where;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitPlatformFacade;
|
||||
@@ -54,12 +49,12 @@ import git4idea.rebase.GitRebaser;
|
||||
import git4idea.repo.GitBranchTrackInfo;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.stash.GitChangesSaver;
|
||||
import git4idea.util.GitFreezingProcess;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import static git4idea.util.GitUIUtil.*;
|
||||
@@ -74,6 +69,7 @@ public class GitUpdateProcess {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final Git myGit;
|
||||
@NotNull private final GitPlatformFacade myPlatformFacade;
|
||||
@NotNull private final Collection<GitRepository> myRepositories;
|
||||
private final boolean myCheckRebaseOverMergeProblem;
|
||||
private final UpdatedFiles myUpdatedFiles;
|
||||
@@ -83,7 +79,6 @@ public class GitUpdateProcess {
|
||||
|
||||
private final Map<VirtualFile, GitBranchPair> myTrackedBranches = new HashMap<VirtualFile, GitBranchPair>();
|
||||
private GitUpdateResult myResult;
|
||||
private final Collection<VirtualFile> myRootsToSave;
|
||||
|
||||
public GitUpdateProcess(@NotNull Project project,
|
||||
@NotNull GitPlatformFacade platformFacade,
|
||||
@@ -92,6 +87,7 @@ public class GitUpdateProcess {
|
||||
@NotNull UpdatedFiles updatedFiles,
|
||||
boolean checkRebaseOverMergeProblem) {
|
||||
myProject = project;
|
||||
myPlatformFacade = platformFacade;
|
||||
myRepositories = repositories;
|
||||
myCheckRebaseOverMergeProblem = checkRebaseOverMergeProblem;
|
||||
myGit = ServiceManager.getService(Git.class);
|
||||
@@ -136,26 +132,23 @@ public class GitUpdateProcess {
|
||||
if (!fetchAndNotify()) {
|
||||
return GitUpdateResult.NOT_READY;
|
||||
}
|
||||
|
||||
GitComplexProcess.Operation updateOperation = new GitComplexProcess.Operation() {
|
||||
@Override public void run(ContinuationContext continuationContext) {
|
||||
new GitFreezingProcess(myProject, myPlatformFacade, "update", new Runnable() {
|
||||
public void run() {
|
||||
AccessToken token = DvcsUtil.workingTreeChangeStarted(myProject);
|
||||
try {
|
||||
myResult = updateImpl(updateMethod, continuationContext);
|
||||
myResult = updateImpl(updateMethod);
|
||||
}
|
||||
finally {
|
||||
DvcsUtil.workingTreeChangeFinished(myProject, token);
|
||||
}
|
||||
}
|
||||
};
|
||||
GitComplexProcess.execute(myProject, "update", updateOperation);
|
||||
|
||||
}).execute();
|
||||
myProgressIndicator.setText(oldText);
|
||||
return myResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GitUpdateResult updateImpl(@NotNull UpdateMethod updateMethod, ContinuationContext context) {
|
||||
private GitUpdateResult updateImpl(@NotNull UpdateMethod updateMethod) {
|
||||
Map<VirtualFile, GitUpdater> updaters;
|
||||
try {
|
||||
updaters = defineUpdaters(updateMethod);
|
||||
@@ -193,6 +186,7 @@ public class GitUpdateProcess {
|
||||
}
|
||||
|
||||
// save local changes if needed (update via merge may perform without saving).
|
||||
Collection<VirtualFile> myRootsToSave = ContainerUtil.newArrayList();
|
||||
LOG.info("updateImpl: identifying if save is needed...");
|
||||
for (Map.Entry<VirtualFile, GitUpdater> entry : updaters.entrySet()) {
|
||||
VirtualFile root = entry.getKey();
|
||||
@@ -244,7 +238,7 @@ public class GitUpdateProcess {
|
||||
}
|
||||
else {
|
||||
LOG.info("updateImpl: restoring local changes...");
|
||||
restoreLocalChanges(context);
|
||||
restoreLocalChanges();
|
||||
}
|
||||
}
|
||||
return compoundResult;
|
||||
@@ -312,28 +306,9 @@ public class GitUpdateProcess {
|
||||
return compoundResult.join(result);
|
||||
}
|
||||
|
||||
private void restoreLocalChanges(ContinuationContext context) {
|
||||
context.addExceptionHandler(VcsException.class, new Consumer<VcsException>() {
|
||||
@Override
|
||||
public void consume(VcsException e) {
|
||||
LOG.info("Couldn't restore local changes after update", e);
|
||||
notifyImportantError(myProject, "Couldn't restore local changes after update",
|
||||
"Restoring changes saved before update failed with an error.<br/>" + e.getLocalizedMessage());
|
||||
}
|
||||
});
|
||||
// try restore changes under all circumstances
|
||||
final ContinuationFinalTasksInserter finalTasksInserter = new ContinuationFinalTasksInserter(context);
|
||||
finalTasksInserter.allNextAreFinal();
|
||||
// !!!! this task is put NEXT, i.e. if unshelve/unstash will be done synchronously or scheduled on context,
|
||||
// it is unimportant -> files will be refreshed after
|
||||
context.next(new TaskDescriptor("Refresh local files", Where.POOLED) {
|
||||
@Override
|
||||
public void run(ContinuationContext context) {
|
||||
mySaver.refresh();
|
||||
}
|
||||
});
|
||||
mySaver.restoreLocalChanges(context);
|
||||
finalTasksInserter.removeFinalPropertyAdder();
|
||||
private void restoreLocalChanges() {
|
||||
mySaver.restoreLocalChanges();
|
||||
mySaver.refresh();
|
||||
}
|
||||
|
||||
// fetch all roots. If an error happens, return false and notify about errors.
|
||||
|
||||
@@ -167,15 +167,7 @@ public class GitPreservingProcess {
|
||||
|
||||
public void load() {
|
||||
if (myLoaded.compareAndSet(false, true)) {
|
||||
try {
|
||||
mySaver.load();
|
||||
}
|
||||
catch (VcsException e) {
|
||||
LOG.info("Couldn't load local changes", e);
|
||||
VcsNotifier.getInstance(myProject).notifyError("Couldn't restore uncommitted changes",
|
||||
String.format("Tried to unstash uncommitted changes, but failed with error.<br/>%s",
|
||||
join(e.getMessages())));
|
||||
}
|
||||
mySaver.load();
|
||||
}
|
||||
else {
|
||||
LOG.warn("The changes were already loaded", new Throwable());
|
||||
|
||||
+1
-1
@@ -256,7 +256,7 @@ public class MergeFromTheirsResolver {
|
||||
|
||||
final PatchApplier<BinaryFilePatch> patchApplier =
|
||||
new PatchApplier<BinaryFilePatch>(myVcs.getProject(), myBaseDir, patches, localList, null, null);
|
||||
patchApplier.scheduleSelf(false, myInner, true); // 3
|
||||
patchApplier.execute(false, true); // 3
|
||||
boolean thereAreCreations = false;
|
||||
for (FilePatch patch : patches) {
|
||||
if (patch.isNewFile() || ! Comparing.equal(patch.getAfterName(), patch.getBeforeName())) {
|
||||
|
||||
Reference in New Issue
Block a user