diff --git a/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java
index b191394a758c..70928b08624a 100644
--- a/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java
+++ b/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java
@@ -25,19 +25,14 @@ import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
-import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import git4idea.GitUtil;
-import git4idea.commands.Git;
-import git4idea.commands.GitCommandResult;
-import git4idea.commands.GitHandlerUtil;
-import git4idea.commands.GitSimpleEventDetector;
+import git4idea.commands.*;
import git4idea.merge.GitConflictResolver;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import git4idea.ui.GitUnstashDialog;
-import git4idea.util.GitUIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -101,12 +96,11 @@ public class GitStashChangesSaver extends GitChangesSaver {
@Override
public void load() {
- for (VirtualFile root : myStashedRoots) {
- loadRoot(root);
- }
-
- boolean conflictsResolved = new UnstashConflictResolver(myProject, myGit, myStashedRoots, myParams).merge();
- LOG.info("load: conflicts resolved status is " + conflictsResolved + " in roots " + myStashedRoots);
+ GitStashUtils.unstash(myProject, myStashedRoots, (root) -> {
+ GitLineHandler handler = new GitLineHandler(myProject, root, GitCommand.STASH);
+ handler.addParameters("pop");
+ return handler;
+ }, new UnstashConflictResolver(myProject, myGit, myStashedRoots, myParams));
}
@Override
@@ -130,36 +124,6 @@ public class GitStashChangesSaver extends GitChangesSaver {
GitUnstashDialog.showUnstashDialog(myProject, new ArrayList<>(myStashedRoots), myStashedRoots.iterator().next());
}
- /**
- * 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) {
- LOG.info("loadRoot " + root);
- myProgressIndicator.setText(GitHandlerUtil.formatOperationName("Unstashing changes to", root));
-
- GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
- if (repository == null) {
- LOG.error("Repository is null for root " + root);
- return false;
- }
-
- GitSimpleEventDetector conflictDetector = new GitSimpleEventDetector(GitSimpleEventDetector.Event.MERGE_CONFLICT_ON_UNSTASH);
- GitCommandResult result = myGit.stashPop(repository, conflictDetector);
- VfsUtil.markDirtyAndRefresh(false, true, false, root);
- if (result.success()) {
- return false;
- }
- else if (conflictDetector.hasHappened()) {
- return true;
- }
- else {
- LOG.info("unstash failed " + result.getErrorOutputAsJoinedString());
- GitUIUtil.notifyImportantError(myProject, "Couldn't unstash", "
" + result.getErrorOutputAsHtmlString());
- return false;
- }
- }
-
@Override
public String toString() {
return "StashChangesSaver. Roots: " + myStashedRoots;
diff --git a/plugins/git4idea/src/git4idea/stash/GitStashUtils.kt b/plugins/git4idea/src/git4idea/stash/GitStashUtils.kt
index 7f907a5c201d..5047a192edf5 100644
--- a/plugins/git4idea/src/git4idea/stash/GitStashUtils.kt
+++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.kt
@@ -17,18 +17,79 @@
package git4idea.stash
+import com.intellij.dvcs.DvcsUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.vcs.VcsException
+import com.intellij.openapi.vcs.VcsNotifier
+import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.Consumer
-import git4idea.commands.GitCommand
-import git4idea.commands.GitSimpleHandler
+import git4idea.commands.*
import git4idea.config.GitConfigUtil
+import git4idea.merge.GitConflictResolver
import git4idea.ui.StashInfo
import git4idea.util.GitUIUtil
+import git4idea.util.GitUntrackedFilesHelper
+import git4idea.util.LocalChangesWouldBeOverwrittenHelper
import git4idea.util.StringScanner
import java.nio.charset.Charset
+/**
+ * Unstash the given root, handling common error scenarios.
+ */
+fun unstash(project: Project, root: VirtualFile, handler: GitLineHandler, conflictResolver: GitConflictResolver) {
+ unstash(project, listOf(root), { handler }, conflictResolver)
+}
+
+/**
+ * Unstash the given roots one by one, handling common error scenarios.
+ *
+ * If there's an error in one of the roots, stop and show the error.
+ * If there's a conflict, show the merge dialog, and if the conflicts get resolved, continue with other roots.
+ */
+fun unstash(project: Project,
+ roots: Collection,
+ handlerProvider: (VirtualFile) -> GitLineHandler,
+ conflictResolver: GitConflictResolver) {
+ val token = DvcsUtil.workingTreeChangeStarted(project)
+ try {
+ for (root in roots) {
+ val handler = handlerProvider(root)
+
+ val conflictDetector = GitSimpleEventDetector(GitSimpleEventDetector.Event.MERGE_CONFLICT_ON_UNSTASH)
+ val untrackedFilesDetector = GitUntrackedFilesOverwrittenByOperationDetector(root)
+ val localChangesDetector = GitLocalChangesWouldBeOverwrittenDetector(root, GitLocalChangesWouldBeOverwrittenDetector.Operation.MERGE)
+ handler.addLineListener(conflictDetector)
+ handler.addLineListener(untrackedFilesDetector)
+ handler.addLineListener(localChangesDetector)
+
+ val result = Git.getInstance().runCommand { handler }
+
+ VfsUtil.markDirtyAndRefresh(false, true, false, root)
+
+ if (conflictDetector.hasHappened()) {
+ val conflictsResolved = conflictResolver.merge()
+ if (!conflictsResolved) return
+ }
+ else if (untrackedFilesDetector.wasMessageDetected()) {
+ GitUntrackedFilesHelper.notifyUntrackedFilesOverwrittenBy(project, root, untrackedFilesDetector.relativeFilePaths, "unstash", null)
+ return
+ }
+ else if (localChangesDetector.wasMessageDetected()) {
+ LocalChangesWouldBeOverwrittenHelper.showErrorDialog(project, root, "unstash", localChangesDetector.relativeFilePaths)
+ return
+ }
+ else if (!result.success()) {
+ VcsNotifier.getInstance(project).notifyError("Unstash Failed", result.errorOutputAsHtmlString)
+ return
+ }
+ }
+ }
+ finally {
+ token.finish()
+ }
+}
+
fun loadStashStack(project: Project, root: VirtualFile, consumer: Consumer) {
loadStashStack(project, root, Charset.forName(GitConfigUtil.getLogEncoding(project, root)), consumer)
}
diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
index 64c98d285659..923a66c65fec 100644
--- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
@@ -16,10 +16,8 @@
package git4idea.ui;
import com.intellij.CommonBundle;
-import com.intellij.dvcs.DvcsUtil;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
-import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
@@ -29,14 +27,10 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
-import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
import git4idea.GitRevisionNumber;
@@ -48,8 +42,6 @@ import git4idea.merge.GitConflictResolver;
import git4idea.repo.GitRepository;
import git4idea.stash.GitStashUtils;
import git4idea.util.GitUIUtil;
-import git4idea.util.GitUntrackedFilesHelper;
-import git4idea.util.LocalChangesWouldBeOverwrittenHelper;
import git4idea.validators.GitBranchNameValidator;
import org.jetbrains.annotations.NotNull;
@@ -64,9 +56,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.MERGE;
/**
* The unstash dialog
@@ -312,51 +301,15 @@ public class GitUnstashDialog extends DialogWrapper {
@Override
protected void doOKAction() {
VirtualFile root = getGitRoot();
- final GitLineHandler h = handler();
- final AtomicBoolean conflict = new AtomicBoolean();
+ GitLineHandler h = handler();
- h.addLineListener(new GitLineHandlerAdapter() {
- public void onLineAvailable(String line, Key outputType) {
- if (line.contains("Merge conflict")) {
- conflict.set(true);
- }
- }
- });
- GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root);
- GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, MERGE);
- h.addLineListener(untrackedFilesDetector);
- h.addLineListener(localChangesDetector);
+ boolean completed = ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
+ GitStashUtils.unstash(myProject, root, h, new UnstashConflictResolver(myProject, root, getSelectedStash()));
+ }, GitBundle.getString("unstash.unstashing"), true, myProject);
- AccessToken token = DvcsUtil.workingTreeChangeStarted(myProject);
- try {
- final Ref result = Ref.create();
- final ProgressManager progressManager = ProgressManager.getInstance();
- boolean completed = progressManager.runProcessWithProgressSynchronously(() -> {
- h.addLineListener(new GitHandlerUtil.GitLineHandlerListenerProgress(progressManager.getProgressIndicator(), h, "stash", false));
- Git git = Git.getInstance();
- result.set(git.runCommand(new Computable.PredefinedValueComputable<>(h)));
- }, GitBundle.getString("unstash.unstashing"), true, myProject);
-
- if (!completed) return;
-
- VfsUtil.markDirtyAndRefresh(false, true, false, root);
- GitCommandResult res = result.get();
- if (conflict.get()) {
- boolean conflictsResolved = new UnstashConflictResolver(myProject, root, getSelectedStash()).merge();
- LOG.info("loadRoot " + root + ", conflictsResolved: " + conflictsResolved);
- } else if (untrackedFilesDetector.wasMessageDetected()) {
- GitUntrackedFilesHelper.notifyUntrackedFilesOverwrittenBy(myProject, root, untrackedFilesDetector.getRelativeFilePaths(),
- "unstash", null);
- } else if (localChangesDetector.wasMessageDetected()) {
- LocalChangesWouldBeOverwrittenHelper.showErrorDialog(myProject, root, "unstash", localChangesDetector.getRelativeFilePaths());
- } else if (!res.success()) {
- GitUIUtil.showOperationErrors(myProject, h.errors(), h.printableCommandLine());
- }
+ if (completed) {
+ super.doOKAction();
}
- finally {
- token.finish();
- }
- super.doOKAction();
}
public static void showUnstashDialog(Project project, List gitRoots, VirtualFile defaultRoot) {