diff --git a/hgext/shelve.py b/hgext/shelve.py --- a/hgext/shelve.py +++ b/hgext/shelve.py @@ -165,21 +165,26 @@ class shelvedstate(object): 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 @@ def _dounshelve(ui, repo, *shelved, **op 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) diff --git a/mercurial/error.py b/mercurial/error.py --- a/mercurial/error.py +++ b/mercurial/error.py @@ -240,3 +240,6 @@ class InvalidBundleSpecification(Excepti 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""" diff --git a/tests/test-shelve.t b/tests/test-shelve.t --- a/tests/test-shelve.t +++ b/tests/test-shelve.t @@ -1585,3 +1585,40 @@ On non bare shelve the branch informatio ? 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 ..