shelve: adds restoring newly created branch (issue5048) (BC)
authorliscju <piotr.listkiewicz@gmail.com>
Wed, 10 Feb 2016 02:23:27 +0100
changeset 28573 6a42564081cb
parent 28572 43c204ddf333
child 28574 7a4e1749cb07
shelve: adds restoring newly created branch (issue5048) (BC) Before this patch shelve never preserved branch information, so after applying unshelve branch was the same as it was on working copy no matter in which branch shelve took place. This patch makes bare shelving(with no files specified, without interactive,include and exclude option) remembers information if the working directory was on newly created branch ,in other words working directory was on different branch than its first parent. In this situation unshelving restores branch information to the working directory.
hgext/shelve.py
tests/test-shelve.t
--- a/hgext/shelve.py	Mon Mar 07 22:58:11 2016 +0100
+++ b/hgext/shelve.py	Wed Feb 10 02:23:27 2016 +0100
@@ -167,6 +167,7 @@
             pendingctx = 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()
         finally:
             fp.close()
 
@@ -176,11 +177,13 @@
         obj.pendingctx = repo[nodemod.bin(pendingctx)]
         obj.parents = parents
         obj.stripnodes = stripnodes
+        obj.branchtorestore = branchtorestore
 
         return obj
 
     @classmethod
-    def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
+    def save(cls, repo, name, originalwctx, pendingctx, stripnodes,
+             branchtorestore):
         fp = repo.vfs(cls._filename, 'wb')
         fp.write('%i\n' % cls._version)
         fp.write('%s\n' % name)
@@ -190,6 +193,7 @@
                  ' '.join([nodemod.hex(p) for p in repo.dirstate.parents()]))
         fp.write('%s\n' %
                  ' '.join([nodemod.hex(n) for n in stripnodes]))
+        fp.write('%s\n' % branchtorestore)
         fp.close()
 
     @classmethod
@@ -555,6 +559,12 @@
     finally:
         ui.quiet = oldquiet
 
+def restorebranch(ui, repo, branchtorestore):
+    if branchtorestore and branchtorestore != repo.dirstate.branch():
+        repo.dirstate.setbranch(branchtorestore)
+        ui.status(_('marked working directory as branch %s\n')
+                  % branchtorestore)
+
 def unshelvecleanup(ui, repo, name, opts):
     """remove related files after an unshelve"""
     if not opts.get('keep'):
@@ -594,6 +604,7 @@
             state.stripnodes.append(shelvectx.node())
 
         mergefiles(ui, repo, state.wctx, shelvectx)
+        restorebranch(ui, repo, state.branchtorestore)
 
         repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
         shelvedstate.clear(repo)
@@ -632,6 +643,10 @@
     that causes a conflict. This reverts the unshelved changes, and
     leaves the bundle in place.)
 
+    If bare shelved change(when no files are specified, without interactive,
+    include and exclude option) was done on newly created branch it would
+    restore branch information to the working directory.
+
     After a successful unshelve, the shelved changes are stored in a
     backup directory. Only the N most recent backups are kept. N
     defaults to 10 but can be overridden using the ``shelve.maxbackups``
@@ -740,6 +755,10 @@
 
         shelvectx = repo['tip']
 
+        branchtorestore = ''
+        if shelvectx.branch() != shelvectx.p1().branch():
+            branchtorestore = shelvectx.branch()
+
         # If the shelve is not immediately on top of the commit
         # we'll be merging with, rebase it to be on top.
         if tmpwctx.node() != shelvectx.parents()[0].node():
@@ -756,7 +775,8 @@
 
                 stripnodes = [repo.changelog.node(rev)
                               for rev in xrange(oldtiprev, len(repo))]
-                shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
+                shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes,
+                                  branchtorestore)
 
                 util.rename(repo.join('rebasestate'),
                             repo.join('unshelverebasestate'))
@@ -772,6 +792,7 @@
                 shelvectx = tmpwctx
 
         mergefiles(ui, repo, pctx, shelvectx)
+        restorebranch(ui, repo, branchtorestore)
 
         # Forget any files that were unknown before the shelve, unknown before
         # unshelve started, but are now added.
@@ -841,6 +862,12 @@
     files. If specific files or directories are named, only changes to
     those files are shelved.
 
+    In bare shelve(when no files are specified, without interactive,
+    include and exclude option), shelving remembers information if the
+    working directory was on newly created branch, in other words working
+    directory was on different branch than its first parent. In this
+    situation unshelving restores branch information to the working directory.
+
     Each shelved change has a name that makes it easier to find later.
     The name of a shelved change defaults to being based on the active
     bookmark, or if there is no active bookmark, the current named
--- a/tests/test-shelve.t	Mon Mar 07 22:58:11 2016 +0100
+++ b/tests/test-shelve.t	Wed Feb 10 02:23:27 2016 +0100
@@ -36,6 +36,12 @@
       specific files or directories are named, only changes to those files are
       shelved.
   
+      In bare shelve(when no files are specified, without interactive, include
+      and exclude option), shelving remembers information if the working
+      directory was on newly created branch, in other words working directory
+      was on different branch than its first parent. In this situation
+      unshelving restores branch information to the working directory.
+  
       Each shelved change has a name that makes it easier to find later. The
       name of a shelved change defaults to being based on the active bookmark,
       or if there is no active bookmark, the current named branch.  To specify a
@@ -1377,3 +1383,202 @@
   $ hg branch
   default
 
+When i shelve commit on newly created branch i expect
+that after unshelve newly created branch will be preserved.
+
+  $ hg init shelve_on_new_branch_simple
+  $ cd shelve_on_new_branch_simple
+  $ echo "aaa" >> a
+  $ hg commit -A -m "a"
+  adding a
+  $ hg branch
+  default
+  $ hg branch test
+  marked working directory as branch test
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo "bbb" >> a
+  $ hg status
+  M a
+  $ hg shelve
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg branch
+  default
+  $ echo "bbb" >> b
+  $ hg status
+  ? b
+  $ hg unshelve
+  unshelving change 'default'
+  marked working directory as branch test
+  $ hg status
+  M a
+  ? b
+  $ hg branch
+  test
+
+When i shelve commit on newly created branch, make
+some changes, unshelve it and running into merge
+conflicts i expect that after fixing them and
+running unshelve --continue newly created branch
+will be preserved.
+
+  $ hg init shelve_on_new_branch_conflict
+  $ cd shelve_on_new_branch_conflict
+  $ echo "aaa" >> a
+  $ hg commit -A -m "a"
+  adding a
+  $ hg branch
+  default
+  $ hg branch test
+  marked working directory as branch test
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo "bbb" >> a
+  $ hg status
+  M a
+  $ hg shelve
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg branch
+  default
+  $ echo "ccc" >> a
+  $ hg status
+  M a
+  $ hg unshelve
+  unshelving change 'default'
+  temporarily committing pending changes (restore with 'hg unshelve --abort')
+  rebasing shelved changes
+  rebasing 2:425c97ef07f3 "changes to: a" (tip)
+  merging a
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+  $ echo "aaabbbccc" > a
+  $ rm a.orig
+  $ hg resolve --mark a
+  (no more unresolved files)
+  continue: hg unshelve --continue
+  $ hg unshelve --continue
+  rebasing 2:425c97ef07f3 "changes to: a" (tip)
+  marked working directory as branch test
+  unshelve of 'default' complete
+  $ cat a
+  aaabbbccc
+  $ hg status
+  M a
+  $ hg branch
+  test
+  $ hg commit -m "test-commit"
+
+When i shelve on test branch, update to default branch
+and unshelve i expect that it will not preserve previous
+test branch.
+
+  $ echo "xxx" > b
+  $ hg add b
+  $ hg shelve
+  shelved as test
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg update -r default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg unshelve
+  unshelving change 'test'
+  rebasing shelved changes
+  rebasing 2:357525f34729 "changes to: test-commit" (tip)
+  $ hg status
+  A b
+  $ hg branch
+  default
+
+When i unshelve resulting in merge conflicts and makes saved
+file shelvedstate looks like in previous versions in
+mercurial(without restore branch information in 7th line) i
+expect that after resolving conflicts and succesfully
+running 'shelve --continue' the branch information won't be
+restored and branch will be unchanged.
+
+  $ hg init shelve_on_new_branch_conflict_with_previous_shelvedstate
+  $ cd shelve_on_new_branch_conflict_with_previous_shelvedstate
+  $ echo "aaa" >> a
+  $ hg commit -A -m "a"
+  adding a
+  $ hg branch
+  default
+  $ hg branch test
+  marked working directory as branch test
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo "bbb" >> a
+  $ hg status
+  M a
+  $ hg shelve
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg branch
+  default
+  $ echo "ccc" >> a
+  $ hg status
+  M a
+  $ hg unshelve
+  unshelving change 'default'
+  temporarily committing pending changes (restore with 'hg unshelve --abort')
+  rebasing shelved changes
+  rebasing 2:425c97ef07f3 "changes to: a" (tip)
+  merging a
+  warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+
+Removing restore branch information from shelvedstate file(making it looks like
+in previous versions) and running unshelve --continue
+
+  $ head -n 6 < .hg/shelvedstate > .hg/shelvedstate_oldformat
+  $ rm .hg/shelvedstate
+  $ mv .hg/shelvedstate_oldformat .hg/shelvedstate
+
+  $ echo "aaabbbccc" > a
+  $ rm a.orig
+  $ hg resolve --mark a
+  (no more unresolved files)
+  continue: hg unshelve --continue
+  $ hg unshelve --continue
+  rebasing 2:425c97ef07f3 "changes to: a" (tip)
+  unshelve of 'default' complete
+  $ cat a
+  aaabbbccc
+  $ hg status
+  M a
+  $ hg branch
+  default
+
+On non bare shelve the branch information shouldn't be restored
+
+  $ hg init bare_shelve_on_new_branch
+  $ cd bare_shelve_on_new_branch
+  $ echo "aaa" >> a
+  $ hg commit -A -m "a"
+  adding a
+  $ hg branch
+  default
+  $ hg branch test
+  marked working directory as branch test
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo "bbb" >> a
+  $ hg status
+  M a
+  $ hg shelve a
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg branch
+  test
+  $ hg branch default
+  marked working directory as branch default
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo "bbb" >> b
+  $ hg status
+  ? b
+  $ hg unshelve
+  unshelving change 'default'
+  $ hg status
+  M a
+  ? b
+  $ hg branch
+  default