From 00e2508e86765c8f7f4e8cdf7a292f4800ec0ab5 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Thu, 16 Jan 2014 15:38:13 +0400 Subject: [PATCH] IDEA-119238 Git and Hg Amend Commit: amend message updated for multi-root selection changes *last messaged for all committed repositories stored to map; *amended message reconstructed using current selected repositories --- .../dvcs/DvcsCommitAdditionalComponent.java | 77 ++++++++++++------- .../checkin/GitCheckinEnvironment.java | 24 +++--- .../provider/commit/HgCheckinEnvironment.java | 4 +- .../src/org/zmlx/hg4idea/util/HgUtil.java | 17 ++++ 4 files changed, 80 insertions(+), 42 deletions(-) diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java b/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java index 56900785e57b..b891d3ba3814 100644 --- a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java +++ b/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java @@ -24,10 +24,13 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.CheckinProjectPanel; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.NonFocusableCheckBox; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,8 +39,9 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.Collection; -import java.util.LinkedHashSet; +import java.io.File; +import java.util.*; +import java.util.List; /** * @author Nadya Zabrodina @@ -51,6 +55,7 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp @Nullable private String myPreviousMessage; @Nullable private String myAmendedMessage; @NotNull protected final CheckinProjectPanel myCheckinPanel; + @Nullable private Map myMessagesForRoots; public DvcsCommitAdditionalComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) { myCheckinPanel = panel; @@ -76,14 +81,16 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp @Override public void actionPerformed(ActionEvent e) { if (myAmend.isSelected()) { - if (myPreviousMessage.equals(myCheckinPanel.getCommitMessage())) { // if user has already typed something, don't revert it - if (myAmendedMessage == null) { - loadMessageInModalTask(project); + if (myPreviousMessage.equals(myCheckinPanel.getCommitMessage())) { // if user has already typed something, don't revert it + if (myMessagesForRoots == null) { + loadMessagesInModalTask(project); //load all commit messages for all repositories + } + String message = constructAmendedMessage(); + if (!StringUtil.isEmptyOrSpaces(message)) { + myAmendedMessage = message; + substituteCommitMessage(myAmendedMessage); + } } - else { // checkbox is selected not the first time - substituteCommitMessage(myAmendedMessage); - } - } } else { // there was the amended message, but user has changed it => not reverting @@ -96,6 +103,20 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp myPanel.add(myAmend, c); } + private String constructAmendedMessage() { + Set selectedRoots = getVcsRoots(getSelectedFilePaths()); // get only selected files + LinkedHashSet messages = ContainerUtil.newLinkedHashSet(); + if (myMessagesForRoots != null) { + for (VirtualFile root : selectedRoots) { + String message = myMessagesForRoots.get(root); + if (message != null) { + messages.add(message); + } + } + } + return DvcsUtil.joinMessagesOrNull(messages); + } + public JComponent getComponent() { return myPanel; } @@ -104,19 +125,15 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp myAmend.setSelected(false); } - private void loadMessageInModalTask(@NotNull Project project) { + private void loadMessagesInModalTask(@NotNull Project project) { try { - String messageFromVcs = - ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable() { + myMessagesForRoots = + ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable, VcsException>() { @Override - public String compute() throws VcsException { - return getLastCommitMessage(); + public Map compute() throws VcsException { + return getLastCommitMessages(); } }, "Reading commit message...", false, project); - if (!StringUtil.isEmptyOrSpaces(messageFromVcs)) { - substituteCommitMessage(messageFromVcs); - myAmendedMessage = messageFromVcs; - } } catch (VcsException e) { Messages.showErrorDialog(getComponent(), "Couldn't load commit message of the commit to amend.\n" + e.getMessage(), @@ -133,24 +150,32 @@ public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComp } @Nullable - private String getLastCommitMessage() throws VcsException { - Collection roots = getRoots(); + private Map getLastCommitMessages() throws VcsException { + Map messagesForRoots = new HashMap(); + Collection roots = myCheckinPanel.getRoots(); //all committed vcs roots, not only selected final Ref exception = Ref.create(); - LinkedHashSet messages = ContainerUtil.newLinkedHashSet(); for (VirtualFile root : roots) { String message = getLastCommitMessage(root); - if (message != null) { - messages.add(message); - } + messagesForRoots.put(root, message); } if (!exception.isNull()) { throw exception.get(); } - return DvcsUtil.joinMessagesOrNull(messages); + return messagesForRoots; } @NotNull - protected abstract Collection getRoots(); + private List getSelectedFilePaths() { + return ContainerUtil.map(myCheckinPanel.getFiles(), new Function() { + @Override + public FilePath fun(File file) { + return new FilePathImpl(file, file.isDirectory()); + } + }); + } + + @NotNull + protected abstract Set getVcsRoots(Collection files); @Nullable protected abstract String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException; diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java index d5c4b3fa8505..cf26be1cef2a 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java @@ -25,7 +25,10 @@ import com.intellij.openapi.ui.ComboBox; 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.*; +import com.intellij.openapi.vcs.CheckinProjectPanel; +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; @@ -33,7 +36,10 @@ import com.intellij.openapi.vcs.checkin.CheckinEnvironment; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.GuiUtils; -import com.intellij.util.*; +import com.intellij.util.ArrayUtil; +import com.intellij.util.FunctionUtil; +import com.intellij.util.NullableFunction; +import com.intellij.util.PairConsumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.ui.UIUtil; @@ -643,8 +649,8 @@ public class GitCheckinEnvironment implements CheckinEnvironment { @Override @NotNull - protected Set getRoots() { - return GitUtil.gitRoots(getSelectedFilePaths()); + protected Set getVcsRoots(Collection filePaths) { + return GitUtil.gitRoots(filePaths); } @Nullable @@ -665,16 +671,6 @@ public class GitCheckinEnvironment implements CheckinEnvironment { return h.run(); } - @NotNull - private List getSelectedFilePaths() { - return ContainerUtil.map(myCheckinPanel.getFiles(), new Function() { - @Override - public FilePath fun(File file) { - return new FilePathImpl(file, file.isDirectory()); - } - }); - } - private List getUsersList(final Project project) { return NewGitUsersComponent.getInstance(project).get(); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java index aaf9e9dd1c8b..ab721b8a70dc 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java @@ -284,8 +284,8 @@ public class HgCheckinEnvironment implements CheckinEnvironment { @NotNull @Override - protected Collection getRoots() { - return HgUtil.getHgRepositories(myProject); + protected Set getVcsRoots(Collection filePaths) { + return HgUtil.hgRoots(myProject, filePaths); } @Nullable diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index fd0fc503df7d..c57f61f0e30b 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -240,6 +240,23 @@ public abstract class HgUtil { return getNearestHgRoot(VcsUtil.getVcsRootFor(project, filePath)); } + /** + * Get hg roots for paths + * + * @param filePaths the context paths + * @return a set of git roots + */ + public static Set hgRoots(@NotNull Project project, final Collection filePaths) { + HashSet rc = new HashSet(); + for (FilePath path : filePaths) { + final VirtualFile root = getHgRootOrNull(project, path); + if (root != null) { + rc.add(root); + } + } + return rc; + } + /** * Gets the Mercurial root for the given file path or null if non exists: * the root should not only be in directory mappings, but also the .hg repository folder should exist.