Patchwork [2,of,3,STABLE] rebase: catch RepoLookupError at restoring rebase state for abort/continue

login
register
mail settings
Submitter Katsunori FUJIWARA
Date Sept. 30, 2013, 4:49 p.m.
Message ID <d347f0221d8a513bdfdd.1380559742@feefifofum>
Download mbox | patch
Permalink /patch/2678/
State Accepted
Commit 577f4c562d52cd6f2e3030d616cff7924214bb1c
Delegated to: Augie Fackler
Headers show

Comments

Katsunori FUJIWARA - Sept. 30, 2013, 4:49 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1380555307 -32400
#      Tue Oct 01 00:35:07 2013 +0900
# Branch stable
# Node ID d347f0221d8a513bdfddb25519554de50e2260dc
# Parent  b7f9df0416e284e4400fb8d19ae98d441d9cdd28
rebase: catch RepoLookupError at restoring rebase state for abort/continue

Before this patch, "rebase --abort"/"--continue" may fail, when rebase
state is inconsistent: for example, the root of rebase destination
revisions recorded in rebase state file is already stripped manually.

Mercurial earlier than 2.7 allows users to do anything other than
starting new rebase, even though current rebase is not finished or
aborted yet. So, such inconsistent rebase states may be left and
forgotten in repositories.

This patch catches RepoLookupError at restoring rebase state for
abort/continue, and treat such state as "broken".

Patch

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -159,8 +159,19 @@ 
             if opts.get('tool', False):
                 ui.warn(_('tool option will be ignored\n'))
 
-            (originalwd, target, state, skipped, collapsef, keepf,
-                keepbranchesf, external, activebookmark) = restorestatus(repo)
+            try:
+                (originalwd, target, state, skipped, collapsef, keepf,
+                 keepbranchesf, external, activebookmark) = restorestatus(repo)
+            except error.RepoLookupError:
+                if abortf:
+                    clearstatus(repo)
+                    repo.ui.warn(_('rebase aborted (no revision is removed,'
+                                   ' only broken state is cleared)\n'))
+                    return 0
+                else:
+                    msg = _('cannot continue inconsistent rebase')
+                    hint = _('use "hg rebase --abort" to clear borken state')
+                    raise util.Abort(msg, hint=hint)
             if abortf:
                 return abort(repo, originalwd, target, state)
         else:
diff --git a/tests/test-rebase-abort.t b/tests/test-rebase-abort.t
--- a/tests/test-rebase-abort.t
+++ b/tests/test-rebase-abort.t
@@ -75,6 +75,29 @@ 
   |
   o  0:draft 'C1'
   
+Test safety for inconsistent rebase state, which may be created (and
+forgotten) by Mercurial earlier than 2.7. This emulates Mercurial
+earlier than 2.7 by renaming ".hg/rebasestate" temporarily.
+
+  $ hg rebase -s 3 -d 2
+  merging common
+  warning: conflicts during merge.
+  merging common incomplete! (edit conflicts, then use 'hg resolve --mark')
+  unresolved conflicts (see hg resolve, then hg rebase --continue)
+  [1]
+
+  $ mv .hg/rebasestate .hg/rebasestate.back
+  $ hg update --quiet --clean 2
+  $ hg --config extensions.mq= strip --quiet "destination()"
+  $ mv .hg/rebasestate.back .hg/rebasestate
+
+  $ hg rebase --continue
+  abort: cannot continue inconsistent rebase
+  (use "hg rebase --abort" to clear borken state)
+  [255]
+  $ hg rebase --abort
+  rebase aborted (no revision is removed, only broken state is cleared)
+
   $ cd ..