Patchwork shelve: delete shelve statefile on any exception during abort

login
register
mail settings
Submitter Christian Delahousse
Date Oct. 15, 2015, 3:58 a.m.
Message ID <74c8003ff5ad2c32aea8.1444881483@dev4253.prn1.facebook.com>
Download mbox | patch
Permalink /patch/11095/
State Accepted
Headers show

Comments

Christian Delahousse - Oct. 15, 2015, 3:58 a.m.
# HG changeset patch
# User Christian Delahousse <cdelahousse@fb.com>
# Date 1444880106 25200
#      Wed Oct 14 20:35:06 2015 -0700
# Node ID 74c8003ff5ad2c32aea8e7810a81c0c6aaddc561
# Parent  07db7e95c464537aeb2dd7aba39de0813eaffd04
shelve: delete shelve statefile on any exception during abort

When a user's repository is in an unfinished unshelve 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
state file. This fix ensures that no matter what exception may be raised during
the abort, the shelved state file will be deleted, the user will be out of the
unshelve state and they can get their repository into a workable condition.
Augie Fackler - Oct. 15, 2015, 1:03 p.m.
On Wed, Oct 14, 2015 at 08:58:03PM -0700, Christian Delahousse wrote:
> # HG changeset patch
> # User Christian Delahousse <cdelahousse@fb.com>
> # Date 1444880106 25200
> #      Wed Oct 14 20:35:06 2015 -0700
> # Node ID 74c8003ff5ad2c32aea8e7810a81c0c6aaddc561
> # Parent  07db7e95c464537aeb2dd7aba39de0813eaffd04
> shelve: delete shelve statefile on any exception during abort

queued, thanks

>
> When a user's repository is in an unfinished unshelve 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
> state file. This fix ensures that no matter what exception may be raised during
> the abort, the shelved state file will be deleted, the user will be out of the
> unshelve state and they can get their repository into a workable condition.
>
> diff --git a/hgext/shelve.py b/hgext/shelve.py
> --- a/hgext/shelve.py
> +++ b/hgext/shelve.py
> @@ -482,9 +482,9 @@
>          mergefiles(ui, repo, state.wctx, state.pendingctx)
>
>          repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
> +    finally:
>          shelvedstate.clear(repo)
>          ui.warn(_("unshelve of '%s' aborted\n") % state.name)
> -    finally:
>          lockmod.release(lock, wlock)
>
>  def mergefiles(ui, repo, wctx, shelvectx):
> diff --git a/tests/test-shelve.t b/tests/test-shelve.t
> --- a/tests/test-shelve.t
> +++ b/tests/test-shelve.t
> @@ -1010,3 +1010,43 @@
>    changegroup -- "{'version': '02'}"
>        7e30d8ac6f23cfc84330fd7e698730374615d21a
>    $ cd ..
> +
> +test Abort unshelve always gets user out of the unshelved state
> +---------------------------------------------------------------
> +  $ hg init salvage
> +  $ cd salvage
> +  $ echo 'content' > root
> +  $ hg commit -A -m 'root' -q
> +  $ echo '' > root
> +  $ hg shelve -q
> +  $ echo 'contADDent' > root
> +  $ hg unshelve -q
> +  warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
> +  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
> +  [1]
> +Wreak havoc on the unshelve process
> +  $ rm .hg/unshelverebasestate
> +  $ hg unshelve --abort
> +  unshelve of 'default' aborted
> +  abort: No such file or directory
> +  [255]
> +Can the user leave the current state?
> +  $ hg up -C .
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +
> +Try again but with a corrupted shelve state file
> +  $ hg strip -r 2 -r 1 -q
> +  $ hg up -r 0 -q
> +  $ echo '' > root
> +  $ hg shelve -q
> +  $ echo 'contADDent' > root
> +  $ hg unshelve -q
> +  warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
> +  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
> +  [1]
> +  $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
> +  $ mv ../corrupt-shelvedstate .hg/histedit-state
> +  $ hg unshelve --abort |& grep 'rebase aborted'
> +  rebase aborted
> +  $ hg up -C .
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> https://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -482,9 +482,9 @@ 
         mergefiles(ui, repo, state.wctx, state.pendingctx)
 
         repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
+    finally:
         shelvedstate.clear(repo)
         ui.warn(_("unshelve of '%s' aborted\n") % state.name)
-    finally:
         lockmod.release(lock, wlock)
 
 def mergefiles(ui, repo, wctx, shelvectx):
diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -1010,3 +1010,43 @@ 
   changegroup -- "{'version': '02'}"
       7e30d8ac6f23cfc84330fd7e698730374615d21a
   $ cd ..
+
+test Abort unshelve always gets user out of the unshelved state
+---------------------------------------------------------------
+  $ hg init salvage
+  $ cd salvage
+  $ echo 'content' > root
+  $ hg commit -A -m 'root' -q
+  $ echo '' > root
+  $ hg shelve -q
+  $ echo 'contADDent' > root
+  $ hg unshelve -q
+  warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+Wreak havoc on the unshelve process
+  $ rm .hg/unshelverebasestate
+  $ hg unshelve --abort
+  unshelve of 'default' aborted
+  abort: No such file or directory
+  [255]
+Can the user leave the current state?
+  $ hg up -C .
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Try again but with a corrupted shelve state file
+  $ hg strip -r 2 -r 1 -q
+  $ hg up -r 0 -q
+  $ echo '' > root
+  $ hg shelve -q
+  $ echo 'contADDent' > root
+  $ hg unshelve -q
+  warning: conflicts while merging root! (edit, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+  $ sed 's/ae8c668541e8/123456789012/' .hg/shelvedstate > ../corrupt-shelvedstate
+  $ mv ../corrupt-shelvedstate .hg/histedit-state
+  $ hg unshelve --abort |& grep 'rebase aborted'
+  rebase aborted
+  $ hg up -C .
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved