[PATCH V2] shelve: restore parents after unshelve (issue5123)

Pierre-Yves David pierre-yves.david at ens-lyon.org
Fri Apr 1 09:30:15 UTC 2016



On 03/31/2016 03:15 PM, liscju wrote:
> # HG changeset patch
> # User liscju <piotr.listkiewicz at gmail.com>
> # Date 1459461357 -7200
> #      Thu Mar 31 23:55:57 2016 +0200
> # Node ID 427ff5e02d5d4a4cb0a51b816ac2bbca84377cfd
> # Parent  ff0d3b6b287f89594bd8d0308fe2810d2a18ea01
> shelve: restore parents after unshelve (issue5123)
>
> unshelve operates on the first parent of the working directory,
> commiting pending changes and applying the saved commit
> in shelve on the first parent.
>
> Before this commit it forgot about second parent, so second
> parent was not restored and lost in the process. This commit makes
> unshelve remember original parents of the working directory and
> recreates it when working context had more than one parent.
>
> Recreating merge parent is done in restoremergeparent function.
> It sets the working copy second parent to the second parent of
> pendingctx. pendingctx is changeset with saved changes to working
> copy, it is best represented by the following diagram:
>
> .. -> originalwctx -> pendingctx -> shelvectx
>
> Restoring second parent of pendingctx is done only when originalwctx
> is different than pendingctx. When pendingctx is the same as orignalwctx
> it means that working copy wasn't changed so working copy after unshelve
> should have only one parent - originalwctx.

I know that there is usually dirstate content issue after the use of set 
parent. Did you pay attention to them? I'm not sure how to generate a 
bad case here, but If you have not though about it yet, please wider 
your testing.

The thing are looking for here are files reported with the wrong status 
(mostly modified file reported as clean)

> diff -r ff0d3b6b287f -r 427ff5e02d5d hgext/shelve.py
> --- a/hgext/shelve.py	Tue Mar 29 12:29:00 2016 -0500
> +++ b/hgext/shelve.py	Thu Mar 31 23:55:57 2016 +0200
> @@ -532,6 +532,7 @@ def unshelveabort(ui, repo, state, opts)
>               mergefiles(ui, repo, state.wctx, state.pendingctx)
>               repair.strip(ui, repo, state.stripnodes, backup=False,
>                            topic='shelve')
> +            restoremergeparent(repo, state.wctx, state.pendingctx)
>           finally:
>               shelvedstate.clear(repo)
>               ui.warn(_("unshelve of '%s' aborted\n") % state.name)
> @@ -565,6 +566,14 @@ def restorebranch(ui, repo, branchtorest
>           ui.status(_('marked working directory as branch %s\n')
>                     % branchtorestore)
>
> +def restoremergeparent(repo, originalwctx, pendingctx):
> +    if originalwctx != pendingctx and len(pendingctx.parents()) > 1:
> +        # We want to keep first parent as it is now,
> +        # only second parent should change
> +        p1 = repo['.'].node()
> +        p2 = pendingctx.p2().node()
> +        repo.setparents(p1, p2)
> +
>   def unshelvecleanup(ui, repo, name, opts):
>       """remove related files after an unshelve"""
>       if not opts.get('keep'):
> @@ -605,6 +614,7 @@ def unshelvecontinue(ui, repo, state, op
>
>           mergefiles(ui, repo, state.wctx, shelvectx)
>           restorebranch(ui, repo, state.branchtorestore)
> +        restoremergeparent(repo, state.wctx, state.pendingctx)
>
>           repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
>           shelvedstate.clear(repo)
> @@ -793,6 +803,7 @@ def _dounshelve(ui, repo, *shelved, **op
>
>           mergefiles(ui, repo, pctx, shelvectx)
>           restorebranch(ui, repo, branchtorestore)
> +        restoremergeparent(repo, pctx, tmpwctx)
>
>           # Forget any files that were unknown before the shelve, unknown before
>           # unshelve started, but are now added.
> diff -r ff0d3b6b287f -r 427ff5e02d5d tests/test-shelve.t
> --- a/tests/test-shelve.t	Tue Mar 29 12:29:00 2016 -0500
> +++ b/tests/test-shelve.t	Thu Mar 31 23:55:57 2016 +0200
> @@ -1583,3 +1583,459 @@ On non bare shelve the branch informatio
>     ? b
>     $ hg branch
>     default
> +
> +  $ cd ..
> +
> +When unshelving is done on working context that has more than
> +one parents, working context after unshelving should still has
> +the same parents as before.
> +
> +  $ hg init unshelving_restores_merge_parents
> +  $ cd unshelving_restores_merge_parents

Same feedback on the use of "_" and name length than for your bundle 
patch. Can you think about another name?

> +  $ touch a
> +  $ hg add a
> +  $ hg commit -m "a"
> +  $ touch b
> +  $ hg add b
> +  $ hg commit -m "b"
> +  $ hg update -r 0
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ touch c
> +  $ hg add c
> +  $ hg commit -m "c"
> +  created new head
> +  $ hg update -r 1
> +  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg log -G
> +  o  changeset:   2:d5e255ef74f8
> +  |  tag:         tip
> +  |  parent:      0:3903775176ed
> +  |  user:        test
> +  |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  |  summary:     c
> +  |
> +  | @  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a
> +
> +  $ touch d
> +  $ hg add d
> +  $ hg shelve
> +  shelved as default
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg merge -r 2
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  (branch merge, don't forget to commit)

Adding a status call here would be a good first step

> +  $ hg log -G
> +  @  changeset:   2:d5e255ef74f8
> +  |  tag:         tip
> +  |  parent:      0:3903775176ed
> +  |  user:        test
> +  |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  |  summary:     c
> +  |
> +  | @  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a
> +
> +  $ hg unshelve
> +  unshelving change 'default'
> +  temporarily committing pending changes (restore with 'hg unshelve --abort')
> +  rebasing shelved changes
> +  rebasing 4:013284d9655e "changes to: b" (tip)
> +  $ hg parents
> +  changeset:   1:0e067c57feba
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     b
> +
> +  changeset:   2:d5e255ef74f8
> +  tag:         tip
> +  parent:      0:3903775176ed
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     c
> +
> +  $ hg status
> +  A d

Then check that the status after unshelve is sane


> +  $ hg commit -m "d"
> +  $ hg log -G
> +  @    changeset:   3:cf9d915cbda8
> +  |\   tag:         tip
> +  | |  parent:      1:0e067c57feba
> +  | |  parent:      2:d5e255ef74f8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     d
> +  | |
> +  | o  changeset:   2:d5e255ef74f8
> +  | |  parent:      0:3903775176ed
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     c
> +  | |
> +  o |  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a
> +
> +
> +Unshelve should preserve merge parents also when used with --continue
> +
> +  $ touch e
> +  $ hg add e
> +  $ hg commit -m "e"
> +  $ hg update -r 3
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ touch f
> +  $ hg add f
> +  $ hg commit -m "f"
> +  created new head
> +  $ echo "xxx" >> g
> +  $ hg add g
> +  $ hg shelve
> +  shelved as default
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg log -G
> +  @  changeset:   5:eed8e5d60bdb
> +  |  tag:         tip
> +  |  parent:      3:cf9d915cbda8
> +  |  user:        test
> +  |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  |  summary:     f
> +  |
> +  | o  changeset:   4:2bb82181804e
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     e
> +  |
> +  o    changeset:   3:cf9d915cbda8
> +  |\   parent:      1:0e067c57feba
> +  | |  parent:      2:d5e255ef74f8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     d
> +  | |
> +  | o  changeset:   2:d5e255ef74f8
> +  | |  parent:      0:3903775176ed
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     c
> +  | |
> +  o |  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a

Consider retricting your log size, we don't need the full repository 
content every time

> +
> +  $ hg merge -r 4
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  (branch merge, don't forget to commit)
> +  $ hg parents
> +  changeset:   5:eed8e5d60bdb
> +  tag:         tip
> +  parent:      3:cf9d915cbda8
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     f
> +
> +  changeset:   4:2bb82181804e
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     e
> +
> +  $ echo "ggg" >> g
> +  $ hg add g
> +  $ hg unshelve
> +  unshelving change 'default'
> +  temporarily committing pending changes (restore with 'hg unshelve --abort')
> +  rebasing shelved changes
> +  rebasing 7:f3112b16f74c "changes to: f" (tip)
> +  merging g
> +  warning: conflicts while merging g! (edit, then use 'hg resolve --mark')
> +  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
> +  [1]
> +  $ hg resolve --mark g
> +  (no more unresolved files)
> +  continue: hg unshelve --continue
> +  $ hg unshelve --continue
> +  rebasing 7:f3112b16f74c "changes to: f" (tip)
> +  unshelve of 'default' complete
> +  $ hg parents
> +  changeset:   5:eed8e5d60bdb
> +  tag:         tip
> +  parent:      3:cf9d915cbda8
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     f
> +
> +  changeset:   4:2bb82181804e
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     e
> +
> +  $ hg commit -m "g"
> +  $ hg log -G
> +  @    changeset:   6:* (glob)
> +  |\   tag:         tip
> +  | |  parent:      5:eed8e5d60bdb
> +  | |  parent:      4:2bb82181804e
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     g
> +  | |
> +  | o  changeset:   5:eed8e5d60bdb
> +  | |  parent:      3:cf9d915cbda8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     f
> +  | |
> +  o |  changeset:   4:2bb82181804e
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     e
> +  |
> +  o    changeset:   3:cf9d915cbda8
> +  |\   parent:      1:0e067c57feba
> +  | |  parent:      2:d5e255ef74f8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     d
> +  | |
> +  | o  changeset:   2:d5e255ef74f8
> +  | |  parent:      0:3903775176ed
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     c
> +  | |
> +  o |  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a
> +
> +

More mumble about merge size

> +Unshelve should preserve merge parents after --abort
> +
> +  $ touch h
> +  $ hg add h
> +  $ hg commit -m "h"
> +  $ hg update -r 6
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ touch i
> +  $ hg add i
> +  $ hg commit -m "i"
> +  created new head
> +  $ hg log -G
> +  @  changeset:   8:* (glob)
> +  |  tag:         tip
> +  |  parent:      6:* (glob)
> +  |  user:        test
> +  |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  |  summary:     i
> +  |
> +  | o  changeset:   7:* (glob)
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     h
> +  |
> +  o    changeset:   6:* (glob)
> +  |\   parent:      5:eed8e5d60bdb
> +  | |  parent:      4:2bb82181804e
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     g
> +  | |
> +  | o  changeset:   5:eed8e5d60bdb
> +  | |  parent:      3:cf9d915cbda8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     f
> +  | |
> +  o |  changeset:   4:2bb82181804e
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     e
> +  |
> +  o    changeset:   3:cf9d915cbda8
> +  |\   parent:      1:0e067c57feba
> +  | |  parent:      2:d5e255ef74f8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     d
> +  | |
> +  | o  changeset:   2:d5e255ef74f8
> +  | |  parent:      0:3903775176ed
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     c
> +  | |
> +  o |  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a
> +
> +  $ echo "xxx" >> j
> +  $ hg add j
> +  $ hg shelve
> +  shelved as default
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg merge -r 7
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  (branch merge, don't forget to commit)
> +  $ hg parents
> +  changeset:   8:* (glob)
> +  tag:         tip
> +  parent:      6:* (glob)
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     i
> +
> +  changeset:   7:* (glob)
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     h
> +
> +  $ echo "jjj" >> j
> +  $ hg add j
> +  $ hg unshelve
> +  unshelving change 'default'
> +  temporarily committing pending changes (restore with 'hg unshelve --abort')
> +  rebasing shelved changes
> +  rebasing 10:* "changes to: i" (tip) (glob)
> +  merging j
> +  warning: conflicts while merging j! (edit, then use 'hg resolve --mark')
> +  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
> +  [1]
> +  $ hg unshelve --abort
> +  rebase aborted
> +  unshelve of 'default' aborted
> +  $ hg status
> +  A j
> +  ? g.orig
> +  ? j.orig
> +  $ hg parents
> +  changeset:   8:* (glob)
> +  tag:         tip
> +  parent:      6:* (glob)
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     i
> +
> +  changeset:   7:* (glob)
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     h
> +
> +  $ hg log -G
> +  @  changeset:   8:* (glob)
> +  |  tag:         tip
> +  |  parent:      6:* (glob)
> +  |  user:        test
> +  |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  |  summary:     i
> +  |
> +  | @  changeset:   7:* (glob)
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     h
> +  |
> +  o    changeset:   6:* (glob)
> +  |\   parent:      5:eed8e5d60bdb
> +  | |  parent:      4:2bb82181804e
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     g
> +  | |
> +  | o  changeset:   5:eed8e5d60bdb
> +  | |  parent:      3:cf9d915cbda8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     f
> +  | |
> +  o |  changeset:   4:2bb82181804e
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     e
> +  |
> +  o    changeset:   3:cf9d915cbda8
> +  |\   parent:      1:0e067c57feba
> +  | |  parent:      2:d5e255ef74f8
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     d
> +  | |
> +  | o  changeset:   2:d5e255ef74f8
> +  | |  parent:      0:3903775176ed
> +  | |  user:        test
> +  | |  date:        Thu Jan 01 00:00:00 1970 +0000
> +  | |  summary:     c
> +  | |
> +  o |  changeset:   1:0e067c57feba
> +  |/   user:        test
> +  |    date:        Thu Jan 01 00:00:00 1970 +0000
> +  |    summary:     b
> +  |
> +  o  changeset:   0:3903775176ed
> +     user:        test
> +     date:        Thu Jan 01 00:00:00 1970 +0000
> +     summary:     a
> +
> +Unshelve on merge parent should have only one parent
> +
> +  $ hg commit -m "Merge 7 and 8"
> +  $ touch k
> +  $ hg add k
> +  $ hg parents
> +  changeset:   9:* (glob)
> +  tag:         tip
> +  parent:      8:* (glob)
> +  parent:      7:* (glob)
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     Merge 7 and 8
> +
> +  $ hg shelve
> +  shelved as default-01
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg unshelve
> +  unshelving change 'default-01'
> +  $ hg parents
> +  changeset:   9:* (glob)
> +  tag:         tip
> +  parent:      8:* (glob)
> +  parent:      7:* (glob)
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     Merge 7 and 8
> +

Beside the wish for more testing, the naming "issue" and the feedback 
about log size. The thing looks good. I'll probably have a deeper look 
at it tomorrow.

Cheers,

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list