[PATCH] shelve: fix dirstate corruption during unshelve (issue4055)

Durham Goode durham at fb.com
Fri Oct 11 19:42:59 CDT 2013


# HG changeset patch
# User Durham Goode <durham at fb.com>
# Date 1381537180 25200
#      Fri Oct 11 17:19:40 2013 -0700
# Node ID 79c75e64aac7cdc624544b11a6f2bb37b6b02516
# Parent  e828975722c8ff632f08cbeb84ec184da2952823
shelve: fix dirstate corruption during unshelve (issue4055)

If you shelved on top of commit A, then rebased A to @ and unshelved, any file
changed in A would appear as modified in hg status despite the contents not having
changed.

The fix is to use dirstate.setparents() instead of doing it manually. This will
be a little slower since it has to iterate through everything in the dirstate
instead of only what's in the mergestate, but this will be more correct since
the mergestate did not include files which were merged but had no conflict.

The tests also had several bad dirstate's hardcoded in them. This change updates
the tests appropriately and adds a new test to cover this specific rebase case.

diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -380,11 +380,7 @@
 def finishmerge(ui, repo, ms, stripnodes, name, opts):
     # Reset the working dir so it's no longer in a merge state.
     dirstate = repo.dirstate
-    for f in ms:
-        if dirstate[f] == 'm':
-            dirstate.normallookup(f)
-    dirstate._pl = (dirstate._pl[0], nullid)
-    dirstate._dirty = dirstate._dirtypl = True
+    dirstate.setparents(dirstate._pl[0])
     shelvedstate.clear(repo)
 
 def unshelvecontinue(ui, repo, state, opts):
diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -328,7 +328,6 @@
   3:2e69b451d1ea
 
   $ hg status -C
-  M a/a
   M b.rename/b
     b/b
   M c.copy
@@ -341,8 +340,6 @@
 
   $ hg shelve -l
 
-  $ hg commit -m whee a/a
-
 #if execbit
 
 ensure that metadata-only changes are shelved
@@ -390,10 +387,9 @@
   merging a/a
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   $ hg parents -q
-  5:01ba9745dc5a
+  4:33f7f61e6c5e
   $ hg shelve -l
   $ hg status
-  M a/a
   A foo/foo
   $ cat a/a
   a
@@ -423,12 +419,12 @@
 
   $ hg bookmark test
   $ hg bookmark
-   * test                      5:01ba9745dc5a
+   * test                      4:33f7f61e6c5e
   $ hg shelve
   shelved as test
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg bookmark
-   * test                      5:01ba9745dc5a
+   * test                      4:33f7f61e6c5e
   $ hg unshelve
   unshelving change 'test'
   adding changesets
@@ -437,7 +433,7 @@
   added 1 changesets with 1 changes to 7 files
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg bookmark
-   * test                      5:01ba9745dc5a
+   * test                      4:33f7f61e6c5e
 
 shelve should still work even if mq is disabled
 
@@ -453,3 +449,36 @@
   adding file changes
   added 1 changesets with 1 changes to 7 files
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+shelve should leave dirstate clean (issue 4055)
+
+  $ cd ..
+  $ hg init shelverebase
+  $ cd shelverebase
+  $ printf 'x\ny\n' > x
+  $ echo z > z
+  $ hg commit -Aqm xy
+  $ echo z >> x
+  $ hg commit -Aqm z
+  $ hg up 0
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ printf 'a\nx\ny\nz\n' > x
+  $ hg commit -Aqm xyz
+  $ echo c >> z
+  $ hg shelve
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg rebase -d 1 --config extensions.rebase=
+  merging x
+  saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-backup.hg (glob)
+  $ hg unshelve
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files (+1 heads)
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg status
+  M z
+
+  $ cd ..


More information about the Mercurial-devel mailing list