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.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", "<br/>" + result.getErrorOutputAsHtmlString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StashChangesSaver. Roots: " + myStashedRoots;
|
||||
|
||||
@@ -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<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>) {
|
||||
loadStashStack(project, root, Charset.forName(GitConfigUtil.getLogEncoding(project, root)), consumer)
|
||||
}
|
||||
|
||||
@@ -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<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());
|
||||
}
|
||||
if (completed) {
|
||||
super.doOKAction();
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
public static void showUnstashDialog(Project project, List<VirtualFile> gitRoots, VirtualFile defaultRoot) {
|
||||
|
||||
Reference in New Issue
Block a user