mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] Cherry pick: use the common commit dialog.
Instead of using a custom commit executor & custom commit session, use the common commit dialog. The problem is that the commit dialog "onOK"-procedure is asynchronous. To fix this provide a CommitResultHandler that is called on successful or failed commit, and wait (in the GitCherryPicker) until it reports that commit has completed. Don't show notification or report error during commit if the CommitResultHandler is set. This fixes IDEA-84825, IDEA-88236 and is necessary for IDEA-87476.
This commit is contained in:
@@ -20,7 +20,7 @@ import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.CommitExecutor;
|
||||
import com.intellij.openapi.vcs.changes.CommitResultHandler;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsHistoryProvider;
|
||||
@@ -185,8 +185,8 @@ public class MockVcsHelper extends AbstractVcsHelper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitChanges(@NotNull List<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitExecutor executor) {
|
||||
public boolean commitChanges(@NotNull Collection<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitResultHandler customResultHandler) {
|
||||
if (myCommitHandler != null) {
|
||||
return myCommitHandler.commit(commitMessage);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.CommitExecutor;
|
||||
import com.intellij.openapi.vcs.changes.CommitResultHandler;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsHistoryProvider;
|
||||
@@ -167,11 +167,11 @@ public abstract class AbstractVcsHelper {
|
||||
|
||||
|
||||
/**
|
||||
* Shows commit dialog, fills it with the given changes and given commit message, initially selects the given changelist.
|
||||
* @return true if user commits the changes, and commit succeeds; false if user presses Cancel or commit fails with errors.
|
||||
* <p>Shows commit dialog, fills it with the given changes and given commit message, initially selects the given changelist.</p>
|
||||
* <p>Note that the method is asynchronous: it returns right after user presses "Commit" or "Cancel" and after all pre-commit handlers
|
||||
* have been called. It doesn't wait for commit itself to succeed or fail - for this use the {@code customResultHandler}.</p>
|
||||
* @return true if user decides to commit the changes, false if user presses Cancel.
|
||||
*/
|
||||
public abstract boolean commitChanges(@NotNull List<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitExecutor executor);
|
||||
|
||||
|
||||
public abstract boolean commitChanges(@NotNull Collection<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitResultHandler customResultHandler);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.vcs.changes;
|
||||
|
||||
import com.intellij.openapi.vcs.AbstractVcsHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* CommitResultHandler may be passed to {@link AbstractVcsHelper#commitChanges(Collection, LocalChangeList, String, CommitResultHandler)}.
|
||||
* It is called after commit is performed: successful or failed.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public interface CommitResultHandler {
|
||||
|
||||
void onSuccess(@NotNull String commitMessage);
|
||||
|
||||
void onFailure();
|
||||
|
||||
}
|
||||
@@ -1158,7 +1158,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
|
||||
|
||||
private boolean doCommit(final LocalChangeList changeList, final List<Change> changes, final boolean synchronously) {
|
||||
return new CommitHelper(myProject, changeList, changes, changeList.getName(),
|
||||
changeList.getComment(), new ArrayList<CheckinHandler>(), false, synchronously, NullableFunction.NULL).doCommit();
|
||||
changeList.getComment(), new ArrayList<CheckinHandler>(), false, synchronously, NullableFunction.NULL, null).doCommit();
|
||||
}
|
||||
|
||||
public void commitChangesSynchronously(LocalChangeList changeList, List<Change> changes) {
|
||||
|
||||
+21
-11
@@ -111,6 +111,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
private final ZipperUpdater myZipperUpdater;
|
||||
private final Runnable myRefreshDetails;
|
||||
private CommitAction myCommitAction;
|
||||
@Nullable private CommitResultHandler myResultHandler;
|
||||
|
||||
private static class MyUpdateButtonsRunnable implements Runnable {
|
||||
private CommitChangeListDialog myDialog;
|
||||
@@ -139,7 +140,8 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
private final MyUpdateButtonsRunnable myUpdateButtonsRunnable = new MyUpdateButtonsRunnable(this);
|
||||
|
||||
private static boolean commit(final Project project, final List<Change> changes, final LocalChangeList initialSelection,
|
||||
final List<CommitExecutor> executors, final boolean showVcsCommit, final String comment) {
|
||||
final List<CommitExecutor> executors, final boolean showVcsCommit, final String comment,
|
||||
@Nullable CommitResultHandler customResultHandler) {
|
||||
final AbstractVcs[] allActiveVcss = ProjectLevelVcsManager.getInstance(project).getAllActiveVcss();
|
||||
final List<VcsCheckinHandlerFactory> factoryList =
|
||||
CheckinHandlersManager.getInstance().getMatchingVcsFactories(Arrays.<AbstractVcs>asList(allActiveVcss));
|
||||
@@ -155,7 +157,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
final ArrayList<LocalChangeList> changeLists = new ArrayList<LocalChangeList>(manager.getChangeListsCopy());
|
||||
CommitChangeListDialog dialog =
|
||||
new CommitChangeListDialog(project, changes, initialSelection, executors, showVcsCommit, defaultList, changeLists, null, false,
|
||||
comment);
|
||||
comment, customResultHandler);
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
dialog.show();
|
||||
}
|
||||
@@ -179,10 +181,10 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
public static boolean commitChanges(final Project project, final Collection<Change> changes, final LocalChangeList initialSelection,
|
||||
@Nullable final CommitExecutor executor, final String comment) {
|
||||
if (executor == null) {
|
||||
return commitChanges(project, changes, initialSelection, collectExecutors(project, changes), true, comment);
|
||||
return commitChanges(project, changes, initialSelection, collectExecutors(project, changes), true, comment, null);
|
||||
}
|
||||
else {
|
||||
return commitChanges(project, changes, initialSelection, Collections.singletonList(executor), false, comment);
|
||||
return commitChanges(project, changes, initialSelection, Collections.singletonList(executor), false, comment, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,22 +199,29 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the commit dialog, and performs the selected action: commit, commit & push, create patch, etc.
|
||||
* @param customResultHandler If this is not null, after commit is completed, custom result handler is called instead of
|
||||
* showing the default notification in case of commit or failure.
|
||||
* @return true if user agreed to commit, false if he pressed "Cancel".
|
||||
*/
|
||||
public static boolean commitChanges(final Project project, final Collection<Change> changes, final LocalChangeList initialSelection,
|
||||
final List<CommitExecutor> executors, final boolean showVcsCommit, final String comment) {
|
||||
final List<CommitExecutor> executors, final boolean showVcsCommit, final String comment,
|
||||
@Nullable CommitResultHandler customResultHandler) {
|
||||
if (changes.isEmpty() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
Messages.showInfoMessage(project, VcsBundle.message("commit.dialog.no.changes.detected.text") ,
|
||||
VcsBundle.message("commit.dialog.no.changes.detected.title"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return commit(project, new ArrayList<Change>(changes), initialSelection, executors, showVcsCommit, comment);
|
||||
return commit(project, new ArrayList<Change>(changes), initialSelection, executors, showVcsCommit, comment, customResultHandler);
|
||||
}
|
||||
|
||||
public static void commitAlienChanges(final Project project, final List<Change> changes, final AbstractVcs vcs,
|
||||
final String changelistName, final String comment) {
|
||||
final LocalChangeList lcl = new AlienLocalChangeList(changes, changelistName);
|
||||
new CommitChangeListDialog(project, changes, null, null, true, AlienLocalChangeList.DEFAULT_ALIEN, Collections.singletonList(lcl), vcs,
|
||||
true, comment).show();
|
||||
true, comment, null).show();
|
||||
}
|
||||
|
||||
private CommitChangeListDialog(final Project project,
|
||||
@@ -221,13 +230,14 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
final List<CommitExecutor> executors,
|
||||
final boolean showVcsCommit, final LocalChangeList defaultChangeList,
|
||||
final List<LocalChangeList> changeLists, final AbstractVcs singleVcs, final boolean isAlien,
|
||||
final String comment) {
|
||||
final String comment, @Nullable CommitResultHandler customResultHandler) {
|
||||
super(project, true);
|
||||
myCommitContext = new CommitContext();
|
||||
myProject = project;
|
||||
myExecutors = executors;
|
||||
myShowVcsCommit = showVcsCommit;
|
||||
myVcs = singleVcs;
|
||||
myResultHandler = customResultHandler;
|
||||
myListComments = new HashMap<String, String>();
|
||||
myAdditionalData = new PseudoMap<Object, Object>();
|
||||
myDiffDetails = new ShortDiffDetails(myProject, new Getter<Change[]>() {
|
||||
@@ -570,7 +580,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
runBeforeCommitHandlers(new Runnable() {
|
||||
public void run() {
|
||||
CommitChangeListDialog.super.doOKAction();
|
||||
doCommit();
|
||||
doCommit(myResultHandler);
|
||||
}
|
||||
}, null);
|
||||
|
||||
@@ -925,7 +935,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
super.doCancelAction();
|
||||
}
|
||||
|
||||
private void doCommit() {
|
||||
private void doCommit(@Nullable CommitResultHandler customResultHandler) {
|
||||
final CommitHelper helper = new CommitHelper(
|
||||
myProject,
|
||||
myBrowser.getSelectedChangeList(),
|
||||
@@ -933,7 +943,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
|
||||
myActionName,
|
||||
getCommitMessage(),
|
||||
myHandlers,
|
||||
myAllOfDefaultChangeListChangesIncluded, false, myAdditionalData);
|
||||
myAllOfDefaultChangeListChangesIncluded, false, myAdditionalData, customResultHandler);
|
||||
|
||||
if (myIsAlien) {
|
||||
helper.doAlienCommit(myVcs);
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
import com.intellij.util.ui.ConfirmationDialog;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -66,6 +67,7 @@ public class CommitHelper {
|
||||
private final boolean myAllOfDefaultChangeListChangesIncluded;
|
||||
private final boolean myForceSyncCommit;
|
||||
private final NullableFunction<Object, Object> myAdditionalData;
|
||||
@Nullable private final CommitResultHandler myCustomResultHandler;
|
||||
private final List<Document> myCommittingDocuments = new ArrayList<Document>();
|
||||
private final VcsConfiguration myConfiguration;
|
||||
private final VcsDirtyScopeManager myDirtyScopeManager;
|
||||
@@ -78,7 +80,8 @@ public class CommitHelper {
|
||||
final String commitMessage,
|
||||
final List<CheckinHandler> handlers,
|
||||
final boolean allOfDefaultChangeListChangesIncluded,
|
||||
final boolean synchronously, final NullableFunction<Object, Object> additionalDataHolder) {
|
||||
final boolean synchronously, final NullableFunction<Object, Object> additionalDataHolder,
|
||||
@Nullable CommitResultHandler customResultHandler) {
|
||||
myProject = project;
|
||||
myChangeList = changeList;
|
||||
myIncludedChanges = includedChanges;
|
||||
@@ -88,6 +91,7 @@ public class CommitHelper {
|
||||
myAllOfDefaultChangeListChangesIncluded = allOfDefaultChangeListChangesIncluded;
|
||||
myForceSyncCommit = synchronously;
|
||||
myAdditionalData = additionalDataHolder;
|
||||
myCustomResultHandler = customResultHandler;
|
||||
myConfiguration = VcsConfiguration.getInstance(myProject);
|
||||
myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||
myFeedback = new HashSet<String>();
|
||||
@@ -133,8 +137,11 @@ public class CommitHelper {
|
||||
|
||||
@Override
|
||||
public NotificationInfo notifyFinished() {
|
||||
String text = reportSuccess(processor);
|
||||
return new NotificationInfo("VCS Commit", "VCS Commit Finished", text, true);
|
||||
if (myCustomResultHandler == null) {
|
||||
String text = reportSuccess(processor);
|
||||
return new NotificationInfo("VCS Commit", "VCS Commit Finished", text, true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
ProgressManager.getInstance().run(task);
|
||||
@@ -511,6 +518,9 @@ public class CommitHelper {
|
||||
}
|
||||
|
||||
processor.afterSuccessfulCheckIn();
|
||||
if (myCustomResultHandler != null) {
|
||||
myCustomResultHandler.onSuccess(myCommitMessage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (CheckinHandler handler : myHandlers) {
|
||||
@@ -523,28 +533,38 @@ public class CommitHelper {
|
||||
if (indicator != null) {
|
||||
indicator.setText(VcsBundle.message("commit.dialog.completed.successfully"));
|
||||
}
|
||||
} else {
|
||||
WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
|
||||
public void run() {
|
||||
final String message;
|
||||
if (errorsSize > 0 && warningsSize > 0) {
|
||||
message = VcsBundle.message("message.text.commit.failed.with.errors.and.warnings");
|
||||
}
|
||||
else if (errorsSize > 0) {
|
||||
message = VcsBundle.message("message.text.commit.failed.with.errors");
|
||||
}
|
||||
else {
|
||||
message = VcsBundle.message("message.text.commit.finished.with.warnings");
|
||||
}
|
||||
//new VcsBalloonProblemNotifier(myProject, message, MessageType.ERROR).run();
|
||||
Messages.showErrorDialog(message, VcsBundle.message("message.title.commit"));
|
||||
|
||||
if (errorsSize > 0) {
|
||||
processor.afterFailedCheckIn();
|
||||
}
|
||||
}
|
||||
}, null, myProject);
|
||||
}
|
||||
else {
|
||||
if (myCustomResultHandler == null) {
|
||||
showErrorDialogAndMoveToAnotherList(processor, errorsSize, warningsSize);
|
||||
}
|
||||
else {
|
||||
myCustomResultHandler.onFailure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showErrorDialogAndMoveToAnotherList(final GeneralCommitProcessor processor, final int errorsSize, final int warningsSize) {
|
||||
WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
|
||||
public void run() {
|
||||
final String message;
|
||||
if (errorsSize > 0 && warningsSize > 0) {
|
||||
message = VcsBundle.message("message.text.commit.failed.with.errors.and.warnings");
|
||||
}
|
||||
else if (errorsSize > 0) {
|
||||
message = VcsBundle.message("message.text.commit.failed.with.errors");
|
||||
}
|
||||
else {
|
||||
message = VcsBundle.message("message.text.commit.finished.with.warnings");
|
||||
}
|
||||
//new VcsBalloonProblemNotifier(myProject, message, MessageType.ERROR).run();
|
||||
Messages.showErrorDialog(message, VcsBundle.message("message.title.commit"));
|
||||
|
||||
if (errorsSize > 0) {
|
||||
processor.afterFailedCheckIn();
|
||||
}
|
||||
}
|
||||
}, null, myProject);
|
||||
}
|
||||
|
||||
public static void moveToFailedList(final ChangeList changeList,
|
||||
|
||||
@@ -47,10 +47,7 @@ import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.actions.AnnotateToggleAction;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.changes.BackgroundFromStartOption;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.CommitExecutor;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.openapi.vcs.changes.committed.*;
|
||||
import com.intellij.openapi.vcs.changes.ui.*;
|
||||
import com.intellij.openapi.vcs.history.*;
|
||||
@@ -225,9 +222,11 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitChanges(@NotNull List<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitExecutor executor) {
|
||||
return CommitChangeListDialog.commitChanges(myProject, changes, initialChangeList, executor, commitMessage);
|
||||
public boolean commitChanges(@NotNull Collection<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitResultHandler customResultHandler) {
|
||||
return CommitChangeListDialog.commitChanges(myProject, changes, initialChangeList,
|
||||
CommitChangeListDialog.collectExecutors(myProject, changes), true, commitMessage,
|
||||
customResultHandler);
|
||||
}
|
||||
|
||||
private static void addDirectMessages(VcsErrorViewPanel vcsErrorViewPanel, List<VcsException> abstractVcsExceptions) {
|
||||
|
||||
@@ -18,24 +18,17 @@ package git4idea.history.browser;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.openapi.vcs.changes.ui.CommitHelper;
|
||||
import com.intellij.openapi.vcs.checkin.CheckinEnvironment;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.WaitForProgressToShow;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.checkin.GitCheckinEnvironment;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitSimpleEventDetector;
|
||||
@@ -43,15 +36,13 @@ import git4idea.commands.GitUntrackedFilesOverwrittenByOperationDetector;
|
||||
import git4idea.merge.GitConflictResolver;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.util.UntrackedFilesNotifier;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -246,26 +237,44 @@ public class GitCherryPicker {
|
||||
private boolean showCommitDialog(@NotNull final GitRepository repository, @NotNull final GitCommitWrapper commit,
|
||||
@NotNull final LocalChangeList changeList, @NotNull final String commitMessage) {
|
||||
final AtomicBoolean commitSucceeded = new AtomicBoolean();
|
||||
final Semaphore sem = new Semaphore(0);
|
||||
myPlatformFacade.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cancelCherryPick(repository);
|
||||
List<Change> changes = commit.getCommit().getChanges();
|
||||
CherryPickCommitExecutor executor = new CherryPickCommitExecutor(myProject, myPlatformFacade, changes, commitMessage);
|
||||
boolean commitNotCancelled = myPlatformFacade.getVcsHelper(myProject).commitChanges(changes, changeList, commitMessage, executor);
|
||||
boolean success = commitNotCancelled && !executor.hasCommitFailed();
|
||||
if (success) {
|
||||
commit.setActualSubject(getSubjectFromCommitMessage(executor.getActualCommitMessage()));
|
||||
boolean commitNotCancelled = myPlatformFacade.getVcsHelper(myProject).commitChanges(changes, changeList, commitMessage,
|
||||
new CommitResultHandler() {
|
||||
@Override
|
||||
public void onSuccess(@NotNull String commitMessage) {
|
||||
commit.setActualSubject(commitMessage);
|
||||
commitSucceeded.set(true);
|
||||
sem.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
commitSucceeded.set(false);
|
||||
sem.release();
|
||||
}
|
||||
});
|
||||
|
||||
if (!commitNotCancelled) {
|
||||
sem.release();
|
||||
commitSucceeded.set(false);
|
||||
}
|
||||
commitSucceeded.set(success);
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
return commitSucceeded.get();
|
||||
}
|
||||
|
||||
private static String getSubjectFromCommitMessage(String commitMessage) {
|
||||
int newLine = commitMessage.indexOf("\n");
|
||||
return newLine < 0 ? commitMessage : commitMessage.substring(0, newLine);
|
||||
// need additional waiting, because commitChanges is asynchronous
|
||||
try {
|
||||
sem.acquire();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
return false;
|
||||
}
|
||||
return commitSucceeded.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,142 +460,6 @@ public class GitCherryPicker {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Commit procedure is overridden by the executor with its own CommitSession.
|
||||
The reason of that is the asynchronous nature of the CommitHelper: it returns, we continue cherry-picking and occasionally pick
|
||||
the next commit in the queue, and only then Git is called for commit. Thus it commits two cherry-picks at once, which is wrong.
|
||||
|
||||
Here we call GitCheckinEnvironment manually
|
||||
*/
|
||||
private static class CherryPickCommitExecutor implements CommitExecutor {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final GitPlatformFacade myPlatformFacade;
|
||||
@NotNull private final List<Change> myChanges;
|
||||
@NotNull private final String myOriginalCommitMessage;
|
||||
private boolean myCommitFailed;
|
||||
|
||||
@Nullable private CherryPickCommitExecutor.CherryPickCommitSession myCommitSession;
|
||||
|
||||
CherryPickCommitExecutor(@NotNull Project project, @NotNull GitPlatformFacade platformFacade,
|
||||
@NotNull List<Change> changes, @NotNull String originalCommitMessage) {
|
||||
myProject = project;
|
||||
myPlatformFacade = platformFacade;
|
||||
myChanges = changes;
|
||||
myOriginalCommitMessage = originalCommitMessage;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@Override
|
||||
public String getActionText() {
|
||||
return "Commit";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CommitSession createCommitSession() {
|
||||
myCommitSession = new CherryPickCommitSession();
|
||||
return myCommitSession;
|
||||
}
|
||||
|
||||
public boolean hasCommitFailed() {
|
||||
return myCommitFailed;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getActualCommitMessage() {
|
||||
return myCommitSession == null ? myOriginalCommitMessage : myCommitSession.getActualCommitMessage();
|
||||
}
|
||||
|
||||
private class CherryPickCommitSession implements CommitSession {
|
||||
private String myActualCommitMessage;
|
||||
|
||||
@Override
|
||||
public JComponent getAdditionalConfigurationUI() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getAdditionalConfigurationUI(Collection<Change> changes, String commitMessage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Collection<Change> changes, String commitMessage) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Collection<Change> changes, String commitMessage) {
|
||||
final Collection<Document> committingDocs = markCommittingDocs();
|
||||
try {
|
||||
GitCheckinEnvironment ce = ServiceManager.getService(myProject, GitCheckinEnvironment.class);
|
||||
try {
|
||||
ce.reset();
|
||||
List<VcsException> exceptions = ce.commit(myChanges, commitMessage);
|
||||
VcsDirtyScopeManager.getInstance(myProject).filePathsDirty(ChangesUtil.getPaths(myChanges), null);
|
||||
if (exceptions != null && !exceptions.isEmpty()) {
|
||||
VcsException exception = exceptions.get(0);
|
||||
handleError(exception);
|
||||
}
|
||||
myActualCommitMessage = commitMessage;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
handleError(e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
unmarkCommittingDocs(committingDocs);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleError(Throwable exception) {
|
||||
myCommitFailed = true;
|
||||
final String errorMessage = exception.getMessage();
|
||||
WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
|
||||
public void run() {
|
||||
Messages.showErrorDialog(myProject, errorMessage, "Commit Failed");
|
||||
}
|
||||
}, null, myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executionCanceled() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void unmarkCommittingDocs(final Collection<Document> committingDocs) {
|
||||
myPlatformFacade.runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CommitHelper.unmarkCommittingDocuments(committingDocs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<Document> markCommittingDocs() {
|
||||
final Collection<Document> committingDocs = new ArrayList<Document>();
|
||||
myPlatformFacade.runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
committingDocs.addAll(CommitHelper.markCommittingDocuments(myProject, myChanges));
|
||||
}
|
||||
});
|
||||
return committingDocs;
|
||||
}
|
||||
|
||||
public String getActualCommitMessage() {
|
||||
return myActualCommitMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is needed to hold both the original GitCommit, and the commit message which could be changed by the user.
|
||||
* Only the subject of the commit message is needed.
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.CommitExecutor;
|
||||
import com.intellij.openapi.vcs.changes.CommitResultHandler;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsHistoryProvider;
|
||||
@@ -171,8 +171,8 @@ public class HgMockVcsHelper extends AbstractVcsHelper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitChanges(@NotNull List<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitExecutor executor) {
|
||||
public boolean commitChanges(@NotNull Collection<Change> changes, @NotNull LocalChangeList initialChangeList,
|
||||
@NotNull String commitMessage, @Nullable CommitResultHandler customResultHandler) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user