Patchwork [1,of,8] rebase: on abort delete rebase state file no matter what

login
register
mail settings
Submitter Christian Delahousse
Date Oct. 16, 2015, 2:33 a.m.
Message ID <c3787f7156bdbb6d5f7c.1444962810@dev4253.prn1.facebook.com>
Download mbox | patch
Permalink /patch/11133/
State Accepted
Commit 21e50e36de02b46cf2abc704800d4c169c12fd4f
Headers show

Comments

Christian Delahousse - Oct. 16, 2015, 2:33 a.m.
# HG changeset patch
# User Christian Delahousse <cdelahousse@fb.com>
# Date 1444936426 25200
#      Thu Oct 15 12:13:46 2015 -0700
# Node ID c3787f7156bdbb6d5f7c6e2540248b911162c0b3
# Parent  e8f1b728591786143174515ea18089db0df4af90
rebase: on abort delete rebase state file no matter what

When a user's repository is in an unfinished rebase state and they choose to
abort, at a minimum, the repo should be out of that state. We've found
situations where the user could not leave the state unless manually deleting the
rebasestate file. This fix ensures that no matter what exception may be raised
during the abort, the rebase state file will be deleted, the user will be out of
the rebase state and they can get their repository into a workable condition.

Patch

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -926,43 +926,46 @@ 
     activebookmark: the name of the bookmark that should be active after the
         restore'''
 
-    # If the first commits in the rebased set get skipped during the rebase,
-    # their values within the state mapping will be the target rev id. The
-    # dstates list must must not contain the target rev (issue4896)
-    dstates = [s for s in state.values() if s >= 0 and s != target]
-    immutable = [d for d in dstates if not repo[d].mutable()]
-    cleanup = True
-    if immutable:
-        repo.ui.warn(_("warning: can't clean up public changesets %s\n")
-                     % ', '.join(str(repo[r]) for r in immutable),
-                     hint=_('see "hg help phases" for details'))
-        cleanup = False
+    try:
+        # If the first commits in the rebased set get skipped during the rebase,
+        # their values within the state mapping will be the target rev id. The
+        # dstates list must must not contain the target rev (issue4896)
+        dstates = [s for s in state.values() if s >= 0 and s != target]
+        immutable = [d for d in dstates if not repo[d].mutable()]
+        cleanup = True
+        if immutable:
+            repo.ui.warn(_("warning: can't clean up public changesets %s\n")
+                        % ', '.join(str(repo[r]) for r in immutable),
+                        hint=_('see "hg help phases" for details'))
+            cleanup = False
 
-    descendants = set()
-    if dstates:
-        descendants = set(repo.changelog.descendants(dstates))
-    if descendants - set(dstates):
-        repo.ui.warn(_("warning: new changesets detected on target branch, "
-                       "can't strip\n"))
-        cleanup = False
+        descendants = set()
+        if dstates:
+            descendants = set(repo.changelog.descendants(dstates))
+        if descendants - set(dstates):
+            repo.ui.warn(_("warning: new changesets detected on target branch, "
+                        "can't strip\n"))
+            cleanup = False
 
-    if cleanup:
-        # Update away from the rebase if necessary
-        if needupdate(repo, state):
-            merge.update(repo, originalwd, False, True, False)
+        if cleanup:
+            # Update away from the rebase if necessary
+            if needupdate(repo, state):
+                merge.update(repo, originalwd, False, True, False)
 
-        # Strip from the first rebased revision
-        rebased = filter(lambda x: x >= 0 and x != target, state.values())
-        if rebased:
-            strippoints = [c.node()  for c in repo.set('roots(%ld)', rebased)]
-            # no backup of rebased cset versions needed
-            repair.strip(repo.ui, repo, strippoints)
+            # Strip from the first rebased revision
+            rebased = filter(lambda x: x >= 0 and x != target, state.values())
+            if rebased:
+                strippoints = [
+                        c.node()  for c in repo.set('roots(%ld)', rebased)]
+                # no backup of rebased cset versions needed
+                repair.strip(repo.ui, repo, strippoints)
 
-    if activebookmark and activebookmark in repo._bookmarks:
-        bookmarks.activate(repo, activebookmark)
+        if activebookmark and activebookmark in repo._bookmarks:
+            bookmarks.activate(repo, activebookmark)
 
-    clearstatus(repo)
-    repo.ui.warn(_('rebase aborted\n'))
+    finally:
+        clearstatus(repo)
+        repo.ui.warn(_('rebase aborted\n'))
     return 0
 
 def buildstate(repo, dest, rebaseset, collapse, obsoletenotrebased):