mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] IDEA-85684 Better support of commit when CHERRY_PICK_HEAD exists
* GitCheckinEnvironment already has support for the case when the MERGE_HEAD file exists. Add support for cherry-pick. * Make better dialog about partial commit: show the files via SelectFilePathsDialog.
This commit is contained in:
+2
-2
@@ -36,8 +36,8 @@ public class SelectFilePathsDialog extends AbstractSelectFilesDialog<FilePath> {
|
||||
|
||||
public SelectFilePathsDialog(final Project project, List<FilePath> originalFiles, final String prompt,
|
||||
final VcsShowConfirmationOption confirmationOption,
|
||||
@Nullable String okActionName, @Nullable String cancelActionName) {
|
||||
super(project, false, confirmationOption, prompt, true);
|
||||
@Nullable String okActionName, @Nullable String cancelActionName, boolean showDoNotAskOption) {
|
||||
super(project, false, confirmationOption, prompt, showDoNotAskOption);
|
||||
myFileList = new ChangesTreeList<FilePath>(project, originalFiles, true, true, null, null) {
|
||||
protected DefaultTreeModel buildTreeModel(final List<FilePath> changes, ChangeNodeDecorator changeNodeDecorator) {
|
||||
return new TreeModelBuilder(project, false).buildModelFromFilePaths(changes);
|
||||
|
||||
@@ -190,7 +190,7 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
|
||||
}
|
||||
|
||||
final SelectFilePathsDialog dlg =
|
||||
new SelectFilePathsDialog(myProject, files, prompt, confirmationOption, okActionName, cancelActionName);
|
||||
new SelectFilePathsDialog(myProject, files, prompt, confirmationOption, okActionName, cancelActionName, true);
|
||||
dlg.setTitle(title);
|
||||
if (! confirmationOption.isPersistent()) {
|
||||
dlg.setDoNotAskOption(null);
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
package git4idea.checkin;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.CheckinProjectPanel;
|
||||
@@ -26,6 +27,7 @@ import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.ObjectsConvertor;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.openapi.vcs.changes.ui.SelectFilePathsDialog;
|
||||
import com.intellij.openapi.vcs.checkin.CheckinChangeListSpecificComponent;
|
||||
import com.intellij.openapi.vcs.checkin.CheckinEnvironment;
|
||||
import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
|
||||
@@ -182,10 +184,11 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
commit(myProject, root, files, messageFile, myNextCommitAuthor, myNextCommitAmend, myNextCommitAuthorDate);
|
||||
}
|
||||
catch (VcsException ex) {
|
||||
if (!isMergeCommit(ex)) {
|
||||
PartialOperation partialOperation = isMergeCommit(ex);
|
||||
if (partialOperation == PartialOperation.NONE) {
|
||||
throw ex;
|
||||
}
|
||||
if (!mergeCommit(myProject, root, added, removed, messageFile, myNextCommitAuthor, exceptions)) {
|
||||
if (!mergeCommit(myProject, root, added, removed, messageFile, myNextCommitAuthor, exceptions, partialOperation)) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@@ -223,6 +226,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
/**
|
||||
* Preform a merge commit
|
||||
*
|
||||
*
|
||||
* @param project a project
|
||||
* @param root a vcs root
|
||||
* @param added added files
|
||||
@@ -230,6 +234,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
* @param messageFile a message file for commit
|
||||
* @param author an author
|
||||
* @param exceptions the list of exceptions to report
|
||||
* @param partialOperation
|
||||
* @return true if merge commit was successful
|
||||
*/
|
||||
private static boolean mergeCommit(final Project project,
|
||||
@@ -238,7 +243,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
final Set<FilePath> removed,
|
||||
final File messageFile,
|
||||
final String author,
|
||||
List<VcsException> exceptions) {
|
||||
List<VcsException> exceptions, @NotNull final PartialOperation partialOperation) {
|
||||
HashSet<FilePath> realAdded = new HashSet<FilePath>();
|
||||
HashSet<FilePath> realRemoved = new HashSet<FilePath>();
|
||||
// perform diff
|
||||
@@ -278,26 +283,20 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
realAdded.removeAll(added);
|
||||
realRemoved.removeAll(removed);
|
||||
if (realAdded.size() != 0 || realRemoved.size() != 0) {
|
||||
TreeSet<String> files = new TreeSet<String>();
|
||||
for (FilePath f : realAdded) {
|
||||
files.add(f.getPresentableUrl());
|
||||
}
|
||||
for (FilePath f : realRemoved) {
|
||||
files.add(f.getPresentableUrl());
|
||||
}
|
||||
final StringBuilder fileList = new StringBuilder();
|
||||
for (String f : files) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
fileList.append("<li>");
|
||||
fileList.append(StringUtil.escapeXml(f));
|
||||
fileList.append("</li>");
|
||||
}
|
||||
final int[] rc = new int[1];
|
||||
|
||||
final List<FilePath> files = new ArrayList<FilePath>();
|
||||
files.addAll(realAdded);
|
||||
files.addAll(realRemoved);
|
||||
final Ref<Boolean> mergeAll = new Ref<Boolean>();
|
||||
try {
|
||||
GuiUtils.runOrInvokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
rc[0] = Messages.showOkCancelDialog(project, GitBundle.message("commit.partial.merge.message", fileList.toString()),
|
||||
GitBundle.getString("commit.partial.merge.title"), null);
|
||||
String message = GitBundle.message("commit.partial.merge.message", partialOperation.getName());
|
||||
SelectFilePathsDialog dialog = new SelectFilePathsDialog(project, files, message,
|
||||
null, "Commit All Files", CommonBundle.getCancelButtonText(), false);
|
||||
dialog.setTitle(GitBundle.getString("commit.partial.merge.title"));
|
||||
dialog.show();
|
||||
mergeAll.set(dialog.isOK());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -307,7 +306,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
catch (Exception ex) {
|
||||
throw new RuntimeException("Unable to invoke a message box on AWT thread", ex);
|
||||
}
|
||||
if (rc[0] != 0) {
|
||||
if (!mergeAll.get()) {
|
||||
return false;
|
||||
}
|
||||
// update non-indexed files
|
||||
@@ -342,14 +341,21 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if commit has failed due to unfinished merge
|
||||
* Check if commit has failed due to unfinished merge or cherry-pick.
|
||||
*
|
||||
*
|
||||
* @param ex an exception to examine
|
||||
* @return true if exception means that there is a partial commit during merge
|
||||
*/
|
||||
private static boolean isMergeCommit(final VcsException ex) {
|
||||
//noinspection HardCodedStringLiteral
|
||||
return ex.getMessage().contains("fatal: cannot do a partial commit during a merge.");
|
||||
private static PartialOperation isMergeCommit(final VcsException ex) {
|
||||
String message = ex.getMessage();
|
||||
if (message.contains("fatal: cannot do a partial commit during a merge")) {
|
||||
return PartialOperation.MERGE;
|
||||
}
|
||||
if (message.contains("fatal: cannot do a partial commit during a cherry-pick")) {
|
||||
return PartialOperation.CHERRY_PICK;
|
||||
}
|
||||
return PartialOperation.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,6 +520,22 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
|
||||
return rc;
|
||||
}
|
||||
|
||||
private enum PartialOperation {
|
||||
NONE("none"),
|
||||
MERGE("merge"),
|
||||
CHERRY_PICK("cherry-pick");
|
||||
|
||||
private final String myName;
|
||||
|
||||
PartialOperation(String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return myName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort changes by roots
|
||||
*
|
||||
|
||||
@@ -62,7 +62,9 @@ commit.author.tooltip=<html>Specify a commit author here if it is different from
|
||||
commit.author=&Author:
|
||||
commit.amend.tooltip=<html>Merge this commit with the previous one</html>
|
||||
commit.amend=Amend commit
|
||||
commit.partial.merge.message=<html>The following files are not included in commit.<ul>{0}</ul>Perform commit with all files included?</html>
|
||||
commit.partial.merge.message=Partial commit during a {0} is not allowed.\n\
|
||||
The following files are not included in commit.\n\
|
||||
Perform commit with all files included?
|
||||
commit.partial.merge.title=Partial Merge Commit
|
||||
commit.push.changes.tooltip=When this option is enabled, changes are pushed to the server after commit.
|
||||
commit.push.changes=&Push Changes
|
||||
|
||||
Reference in New Issue
Block a user