mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Unify git unstash procedures
This fixes IDEA-174332
This commit is contained in:
@@ -25,19 +25,14 @@ import com.intellij.openapi.vcs.VcsException;
|
|||||||
import com.intellij.openapi.vcs.VcsNotifier;
|
import com.intellij.openapi.vcs.VcsNotifier;
|
||||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||||
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
||||||
import com.intellij.openapi.vfs.VfsUtil;
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import git4idea.GitUtil;
|
import git4idea.GitUtil;
|
||||||
import git4idea.commands.Git;
|
import git4idea.commands.*;
|
||||||
import git4idea.commands.GitCommandResult;
|
|
||||||
import git4idea.commands.GitHandlerUtil;
|
|
||||||
import git4idea.commands.GitSimpleEventDetector;
|
|
||||||
import git4idea.merge.GitConflictResolver;
|
import git4idea.merge.GitConflictResolver;
|
||||||
import git4idea.repo.GitRepository;
|
import git4idea.repo.GitRepository;
|
||||||
import git4idea.repo.GitRepositoryManager;
|
import git4idea.repo.GitRepositoryManager;
|
||||||
import git4idea.ui.GitUnstashDialog;
|
import git4idea.ui.GitUnstashDialog;
|
||||||
import git4idea.util.GitUIUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@@ -101,12 +96,11 @@ public class GitStashChangesSaver extends GitChangesSaver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
for (VirtualFile root : myStashedRoots) {
|
GitStashUtils.unstash(myProject, myStashedRoots, (root) -> {
|
||||||
loadRoot(root);
|
GitLineHandler handler = new GitLineHandler(myProject, root, GitCommand.STASH);
|
||||||
}
|
handler.addParameters("pop");
|
||||||
|
return handler;
|
||||||
boolean conflictsResolved = new UnstashConflictResolver(myProject, myGit, myStashedRoots, myParams).merge();
|
}, new UnstashConflictResolver(myProject, myGit, myStashedRoots, myParams));
|
||||||
LOG.info("load: conflicts resolved status is " + conflictsResolved + " in roots " + myStashedRoots);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,36 +124,6 @@ public class GitStashChangesSaver extends GitChangesSaver {
|
|||||||
GitUnstashDialog.showUnstashDialog(myProject, new ArrayList<>(myStashedRoots), myStashedRoots.iterator().next());
|
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", "<br/>" + result.getErrorOutputAsHtmlString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "StashChangesSaver. Roots: " + myStashedRoots;
|
return "StashChangesSaver. Roots: " + myStashedRoots;
|
||||||
|
|||||||
@@ -17,18 +17,79 @@
|
|||||||
|
|
||||||
package git4idea.stash
|
package git4idea.stash
|
||||||
|
|
||||||
|
import com.intellij.dvcs.DvcsUtil
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vcs.VcsException
|
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.openapi.vfs.VirtualFile
|
||||||
import com.intellij.util.Consumer
|
import com.intellij.util.Consumer
|
||||||
import git4idea.commands.GitCommand
|
import git4idea.commands.*
|
||||||
import git4idea.commands.GitSimpleHandler
|
|
||||||
import git4idea.config.GitConfigUtil
|
import git4idea.config.GitConfigUtil
|
||||||
|
import git4idea.merge.GitConflictResolver
|
||||||
import git4idea.ui.StashInfo
|
import git4idea.ui.StashInfo
|
||||||
import git4idea.util.GitUIUtil
|
import git4idea.util.GitUIUtil
|
||||||
|
import git4idea.util.GitUntrackedFilesHelper
|
||||||
|
import git4idea.util.LocalChangesWouldBeOverwrittenHelper
|
||||||
import git4idea.util.StringScanner
|
import git4idea.util.StringScanner
|
||||||
import java.nio.charset.Charset
|
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<VirtualFile>,
|
||||||
|
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<StashInfo>) {
|
fun loadStashStack(project: Project, root: VirtualFile, consumer: Consumer<StashInfo>) {
|
||||||
loadStashStack(project, root, Charset.forName(GitConfigUtil.getLogEncoding(project, root)), consumer)
|
loadStashStack(project, root, Charset.forName(GitConfigUtil.getLogEncoding(project, root)), consumer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,8 @@
|
|||||||
package git4idea.ui;
|
package git4idea.ui;
|
||||||
|
|
||||||
import com.intellij.CommonBundle;
|
import com.intellij.CommonBundle;
|
||||||
import com.intellij.dvcs.DvcsUtil;
|
|
||||||
import com.intellij.notification.Notification;
|
import com.intellij.notification.Notification;
|
||||||
import com.intellij.notification.NotificationListener;
|
import com.intellij.notification.NotificationListener;
|
||||||
import com.intellij.openapi.application.AccessToken;
|
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.application.ModalityState;
|
import com.intellij.openapi.application.ModalityState;
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
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.project.Project;
|
||||||
import com.intellij.openapi.ui.DialogWrapper;
|
import com.intellij.openapi.ui.DialogWrapper;
|
||||||
import com.intellij.openapi.ui.Messages;
|
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.VcsException;
|
||||||
import com.intellij.openapi.vcs.VcsNotifier;
|
import com.intellij.openapi.vcs.VcsNotifier;
|
||||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||||
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
||||||
import com.intellij.openapi.vfs.VfsUtil;
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.ui.DocumentAdapter;
|
import com.intellij.ui.DocumentAdapter;
|
||||||
import git4idea.GitRevisionNumber;
|
import git4idea.GitRevisionNumber;
|
||||||
@@ -48,8 +42,6 @@ import git4idea.merge.GitConflictResolver;
|
|||||||
import git4idea.repo.GitRepository;
|
import git4idea.repo.GitRepository;
|
||||||
import git4idea.stash.GitStashUtils;
|
import git4idea.stash.GitStashUtils;
|
||||||
import git4idea.util.GitUIUtil;
|
import git4idea.util.GitUIUtil;
|
||||||
import git4idea.util.GitUntrackedFilesHelper;
|
|
||||||
import git4idea.util.LocalChangesWouldBeOverwrittenHelper;
|
|
||||||
import git4idea.validators.GitBranchNameValidator;
|
import git4idea.validators.GitBranchNameValidator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@@ -64,9 +56,6 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.MERGE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The unstash dialog
|
* The unstash dialog
|
||||||
@@ -312,51 +301,15 @@ public class GitUnstashDialog extends DialogWrapper {
|
|||||||
@Override
|
@Override
|
||||||
protected void doOKAction() {
|
protected void doOKAction() {
|
||||||
VirtualFile root = getGitRoot();
|
VirtualFile root = getGitRoot();
|
||||||
final GitLineHandler h = handler();
|
GitLineHandler h = handler();
|
||||||
final AtomicBoolean conflict = new AtomicBoolean();
|
|
||||||
|
|
||||||
h.addLineListener(new GitLineHandlerAdapter() {
|
boolean completed = ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
|
||||||
public void onLineAvailable(String line, Key outputType) {
|
GitStashUtils.unstash(myProject, root, h, new UnstashConflictResolver(myProject, root, getSelectedStash()));
|
||||||
if (line.contains("Merge conflict")) {
|
}, GitBundle.getString("unstash.unstashing"), true, myProject);
|
||||||
conflict.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root);
|
|
||||||
GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, MERGE);
|
|
||||||
h.addLineListener(untrackedFilesDetector);
|
|
||||||
h.addLineListener(localChangesDetector);
|
|
||||||
|
|
||||||
AccessToken token = DvcsUtil.workingTreeChangeStarted(myProject);
|
if (completed) {
|
||||||
try {
|
super.doOKAction();
|
||||||
final Ref<GitCommandResult> 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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
token.finish();
|
|
||||||
}
|
|
||||||
super.doOKAction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showUnstashDialog(Project project, List<VirtualFile> gitRoots, VirtualFile defaultRoot) {
|
public static void showUnstashDialog(Project project, List<VirtualFile> gitRoots, VirtualFile defaultRoot) {
|
||||||
|
|||||||
Reference in New Issue
Block a user