shelve: make unshelve be able to abort in any case
authorKostia Balytskyi <ikostia@fb.com>
Wed, 13 Jul 2016 16:16:18 +0100
changeset 29536 b17a6e3cd2ac
parent 29535 da1848f07c6a
child 29537 5f8b36d5a6ec
shelve: make unshelve be able to abort in any case
hgext/shelve.py
mercurial/error.py
tests/test-shelve.t
--- a/hgext/shelve.py	Wed Jul 13 10:39:33 2016 -0400
+++ b/hgext/shelve.py	Wed Jul 13 16:16:18 2016 +0100
@@ -165,21 +165,26 @@
                 raise error.Abort(_('this version of shelve is incompatible '
                                    'with the version used in this repo'))
             name = fp.readline().strip()
-            wctx = fp.readline().strip()
-            pendingctx = fp.readline().strip()
+            wctx = nodemod.bin(fp.readline().strip())
+            pendingctx = nodemod.bin(fp.readline().strip())
             parents = [nodemod.bin(h) for h in fp.readline().split()]
             stripnodes = [nodemod.bin(h) for h in fp.readline().split()]
             branchtorestore = fp.readline().strip()
+        except (ValueError, TypeError) as err:
+            raise error.CorruptedState(str(err))
         finally:
             fp.close()
 
-        obj = cls()
-        obj.name = name
-        obj.wctx = repo[nodemod.bin(wctx)]
-        obj.pendingctx = repo[nodemod.bin(pendingctx)]
-        obj.parents = parents
-        obj.stripnodes = stripnodes
-        obj.branchtorestore = branchtorestore
+        try:
+            obj = cls()
+            obj.name = name
+            obj.wctx = repo[wctx]
+            obj.pendingctx = repo[pendingctx]
+            obj.parents = parents
+            obj.stripnodes = stripnodes
+            obj.branchtorestore = branchtorestore
+        except error.RepoLookupError as err:
+            raise error.CorruptedState(str(err))
 
         return obj
 
@@ -666,6 +671,20 @@
             if err.errno != errno.ENOENT:
                 raise
             cmdutil.wrongtooltocontinue(repo, _('unshelve'))
+        except error.CorruptedState as err:
+            ui.debug(str(err) + '\n')
+            if continuef:
+                msg = _('corrupted shelved state file')
+                hint = _('please run hg unshelve --abort to abort unshelve '
+                         'operation')
+                raise error.Abort(msg, hint=hint)
+            elif abortf:
+                msg = _('could not read shelved state file, your working copy '
+                        'may be in an unexpected state\nplease update to some '
+                        'commit\n')
+                ui.warn(msg)
+                shelvedstate.clear(repo)
+            return
 
         if abortf:
             return unshelveabort(ui, repo, state, opts)
--- a/mercurial/error.py	Wed Jul 13 10:39:33 2016 -0400
+++ b/mercurial/error.py	Wed Jul 13 16:16:18 2016 +0100
@@ -240,3 +240,6 @@
 
 class UnsupportedBundleSpecification(Exception):
     """error raised when a bundle specification is not supported."""
+
+class CorruptedState(Exception):
+    """error raised when a command is not able to read its state from file"""
--- a/tests/test-shelve.t	Wed Jul 13 10:39:33 2016 -0400
+++ b/tests/test-shelve.t	Wed Jul 13 16:16:18 2016 +0100
@@ -1585,3 +1585,40 @@
   ? b
   $ hg branch
   default
+  $ cd ..
+
+Prepare unshleve with a corrupted shelvedstate
+  $ hg init r1 && cd r1
+  $ echo text1 > file && hg add file
+  $ hg shelve
+  shelved as default
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo text2 > file && hg ci -Am text1
+  adding file
+  $ hg unshelve
+  unshelving change 'default'
+  rebasing shelved changes
+  rebasing 1:396ea74229f9 "(changes in empty repository)" (tip)
+  merging file
+  warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+  $ echo somethingsomething > .hg/shelvedstate
+
+Unshelve --continue fails with appropriate message if shelvedstate is corrupted
+  $ hg unshelve --continue
+  abort: corrupted shelved state file
+  (please run hg unshelve --abort to abort unshelve operation)
+  [255]
+
+Unshelve --abort works with a corrupted shelvedstate
+  $ hg unshelve --abort
+  could not read shelved state file, your working copy may be in an unexpected state
+  please update to some commit
+
+Unshelve --abort fails with appropriate message if there's no unshelve in
+progress
+  $ hg unshelve --abort
+  abort: no unshelve in progress
+  [255]
+  $ cd ..