diff hgext/shelve.py @ 38618:c829749e7639

shelve: directly handle the initial parent alignment Shelve is currently sub-contracting some of its work to the rebase extension. In order to make shelve more independent and flexible we would like shelve to handle the parent alignment directly. After this change, we no longer need to use rebase in shelve. Differential Revision: https://phab.mercurial-scm.org/D3693
author Boris Feld <boris.feld@octobus.net>
date Tue, 29 May 2018 00:30:50 +0200
parents 39db5a01cd53
children 9b077e5fa8ba
line wrap: on
line diff
--- a/hgext/shelve.py	Thu May 24 17:39:07 2018 +0200
+++ b/hgext/shelve.py	Tue May 29 00:30:50 2018 +0200
@@ -686,6 +686,10 @@
         shelvectx = repo[state.parents[1]]
         pendingctx = state.pendingctx
 
+        with repo.dirstate.parentchange():
+            repo.setparents(state.pendingctx.node(), nodemod.nullid)
+            repo.dirstate.write(repo.currenttransaction())
+
         overrides = {('phases', 'new-commit'): phases.secret}
         with repo.ui.configoverride(overrides, 'unshelve'):
             with repo.dirstate.parentchange():
@@ -761,33 +765,46 @@
     if tmpwctx.node() == shelvectx.parents()[0].node():
         return shelvectx
 
-    ui.status(_('rebasing shelved changes\n'))
-    try:
-        rebase.rebase(ui, repo, **{
-            r'rev': [shelvectx.rev()],
-            r'dest': "%d" % tmpwctx.rev(),
-            r'keep': True,
-            r'tool': opts.get('tool', ''),
-        })
-    except error.InterventionRequired:
-        tr.close()
+    overrides = {
+        ('ui', 'forcemerge'): opts.get('tool', ''),
+        ('phases', 'new-commit'): phases.secret,
+    }
+    with repo.ui.configoverride(overrides, 'unshelve'):
+        ui.status(_('rebasing shelved changes\n'))
+        stats = merge.graft(repo, shelvectx, shelvectx.p1(),
+                           labels=['dest', 'source'],
+                           keepconflictparent=True)
+        if stats.unresolvedcount:
+            tr.close()
+
+            nodestoremove = [repo.changelog.node(rev)
+                             for rev in xrange(oldtiprev, len(repo))]
+            shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoremove,
+                              branchtorestore, opts.get('keep'), activebookmark)
+            raise error.InterventionRequired(
+                _("unresolved conflicts (see 'hg resolve', then "
+                  "'hg unshelve --continue')"))
 
-        nodestoremove = [repo.changelog.node(rev)
-                         for rev in xrange(oldtiprev, len(repo))]
-        shelvedstate.save(repo, basename, pctx, tmpwctx, nodestoremove,
-                          branchtorestore, opts.get('keep'), activebookmark)
+        with repo.dirstate.parentchange():
+            repo.setparents(tmpwctx.node(), nodemod.nullid)
+            newnode = repo.commit(text=shelvectx.description(),
+                                  extra=shelvectx.extra(),
+                                  user=shelvectx.user(),
+                                  date=shelvectx.date())
 
-        repo.vfs.rename('rebasestate', 'unshelverebasestate')
-        raise error.InterventionRequired(
-            _("unresolved conflicts (see 'hg resolve', then "
-              "'hg unshelve --continue')"))
+        if newnode is None:
+            # If it ended up being a no-op commit, then the normal
+            # merge state clean-up path doesn't happen, so do it
+            # here. Fix issue5494
+            merge.mergestate.clean(repo)
+            shelvectx = tmpwctx
+            msg = _('note: unshelved changes already existed '
+                    'in the working copy\n')
+            ui.status(msg)
+        else:
+            shelvectx = repo[newnode]
+            hg.updaterepo(repo, tmpwctx.node(), False)
 
-    # refresh ctx after rebase completes
-    shelvectx = repo['tip']
-
-    if tmpwctx not in shelvectx.parents():
-        # rebase was a no-op, so it produced no child commit
-        shelvectx = tmpwctx
     return shelvectx
 
 def _forgetunknownfiles(repo, shelvectx, addedbefore):