From 06fd1b4c07f3ce6a2a410ab7536875188e84bda7 Mon Sep 17 00:00:00 2001 From: irengrig Date: Tue, 19 Jun 2012 13:33:02 +0400 Subject: [PATCH] git update/push: when shelving local changes, create technical changelist for every local changelist, for easier manual recovery in case of failure --- .../vcs/impl/LocalChangesUnderRoots.java | 31 +++++++--- .../git4idea/stash/GitShelveChangesSaver.java | 59 +++++++++++-------- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/LocalChangesUnderRoots.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/LocalChangesUnderRoots.java index 3412cdb4f57c..e20dbd7d3860 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/LocalChangesUnderRoots.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/LocalChangesUnderRoots.java @@ -19,20 +19,14 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsRoot; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vcs.changes.ChangesUtil; -import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; +import java.util.*; /** * Utility class to sort changes by roots. @@ -52,6 +46,19 @@ public class LocalChangesUnderRoots { myVcsManager = ProjectLevelVcsManager.getInstance(myProject); } + public Map>> getChangesByLists(@NotNull Collection rootsToSave) { + final Map>> result = new HashMap>>(); + myRoots = myVcsManager.getAllVcsRoots(); + + final List changeLists = myChangeManager.getChangeListsCopy(); + for (LocalChangeList list : changeLists) { + final HashMap> subMap = new HashMap>(); + addChangesToMap(rootsToSave, subMap, list.getChanges()); + result.put(list.getName(), subMap); + } + return result; + } + /** * Sort all changes registered in the {@link ChangeListManager} by VCS roots, * filtering out any roots except the specified ones. @@ -64,6 +71,13 @@ public class LocalChangesUnderRoots { final Collection allChanges = myChangeManager.getAllChanges(); myRoots = myVcsManager.getAllVcsRoots(); + addChangesToMap(rootsToSave, result, allChanges); + return result; + } + + private void addChangesToMap(Collection rootsToSave, + Map> result, + Collection allChanges) { for (Change change : allChanges) { if (change.getBeforeRevision() != null) { addChangeToMap(result, change, change.getBeforeRevision(), rootsToSave); @@ -72,7 +86,6 @@ public class LocalChangesUnderRoots { addChangeToMap(result, change, change.getAfterRevision(), rootsToSave); } } - return result; } private void addChangeToMap(@NotNull Map> result, @NotNull Change change, @NotNull ContentRevision revision, @NotNull Collection rootsToSave) { diff --git a/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java index 14cd4d97817d..6994f3777f90 100644 --- a/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java +++ b/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java @@ -40,7 +40,7 @@ public class GitShelveChangesSaver extends GitChangesSaver { private static final Logger LOG = Logger.getInstance(GitShelveChangesSaver.class); private final ShelveChangesManager myShelveManager; private final ShelvedChangesViewManager myShelveViewManager; - private ShelvedChangeList myShelvedChangeList; + private Map myShelvedLists; public GitShelveChangesSaver(Project project, Git git, ProgressIndicator indicator, String stashMessage) { super(project, git, indicator, stashMessage); @@ -51,35 +51,46 @@ public class GitShelveChangesSaver extends GitChangesSaver { @Override protected void save(@NotNull Collection rootsToSave) throws VcsException { LOG.info("save " + rootsToSave); - final Map> map = new LocalChangesUnderRoots(myProject).getChangesUnderRoots(rootsToSave); - final Set changes = new HashSet(); - for (Collection changeCollection : map.values()) { - changes.addAll(changeCollection); - } - if (! changes.isEmpty()) { - String oldProgressTitle = myProgressIndicator.getText(); - myProgressIndicator.setText(GitBundle.getString("update.shelving.changes")); - List exceptions = new ArrayList(1); - myShelvedChangeList = GitShelveUtils.shelveChanges(myProject, myShelveManager, changes, myStashMessage, exceptions, false); - myProgressIndicator.setText(oldProgressTitle); - if (! exceptions.isEmpty()) { - LOG.info("save " + exceptions, exceptions.get(0)); - throw exceptions.get(0); - } else { - for (VirtualFile root : rootsToSave) { - GitRollbackEnvironment.resetHardLocal(myProject, root); - } + final Map>> lists = new LocalChangesUnderRoots(myProject).getChangesByLists(rootsToSave); + + String oldProgressTitle = myProgressIndicator.getText(); + myProgressIndicator.setText(GitBundle.getString("update.shelving.changes")); + List exceptions = new ArrayList(1); + myShelvedLists = new HashMap(); + + for (Map.Entry>> entry : lists.entrySet()) { + final Map> map = entry.getValue(); + final Set changes = new HashSet(); + for (Collection changeCollection : map.values()) { + changes.addAll(changeCollection); + } + if (! changes.isEmpty()) { + final ShelvedChangeList list = GitShelveUtils.shelveChanges(myProject, myShelveManager, changes, + myStashMessage + " [" + entry.getKey() + "]", exceptions, false); + myShelvedLists.put(entry.getKey(), list); } } + if (! exceptions.isEmpty()) { + LOG.info("save " + exceptions, exceptions.get(0)); + myShelvedLists = null; // no restore here since during shelving changes are not rolled back... + throw exceptions.get(0); + } else { + for (VirtualFile root : rootsToSave) { + GitRollbackEnvironment.resetHardLocal(myProject, root); + } + } + myProgressIndicator.setText(oldProgressTitle); } protected void load(ContinuationContext context) { - if (myShelvedChangeList != null) { + if (myShelvedLists != null) { LOG.info("load "); String oldProgressTitle = myProgressIndicator.getText(); myProgressIndicator.setText(GitBundle.getString("update.unshelving.changes")); - if (myShelvedChangeList != null) { - GitShelveUtils.doSystemUnshelve(myProject, myShelvedChangeList, myShelveManager, context); + if (myShelvedLists != null) { + for (ShelvedChangeList list : myShelvedLists.values()) { + GitShelveUtils.doSystemUnshelve(myProject, list, myShelveManager, context); + } } myProgressIndicator.setText(oldProgressTitle); } @@ -87,7 +98,7 @@ public class GitShelveChangesSaver extends GitChangesSaver { @Override protected boolean wereChangesSaved() { - return myShelvedChangeList != null; + return myShelvedLists != null; } @Override @@ -97,7 +108,7 @@ public class GitShelveChangesSaver extends GitChangesSaver { @Override protected void showSavedChanges() { - myShelveViewManager.activateView(myShelvedChangeList); + myShelveViewManager.activateView(myShelvedLists.get(myShelvedLists.keySet().iterator().next())); } @Override