evolve: handle merge commit with single obsolete parent (issue4389)
This handles evolving merge commits with a single obsolete parent. Merge
commits with two obsolete parents are still unsupported. Note this depends
on a change to merge.graft in core. Older versions of mercurial will not
have this functionality. Also, test-unstable.t will fail with older
versions.
--- a/README Tue Dec 22 14:11:09 2015 +0000
+++ b/README Thu Nov 26 20:38:31 2015 -0500
@@ -62,6 +62,7 @@
- tests: drop our copy of 'run-tests.py' use core one instead,
- bookmark: do all bookmark movement within a transaction.
- evolve: compatibility with Mercurial 3.7
+- evolve: support merge with a single obsolete parent.
5.2.2 --
--- a/hgext/evolve.py Tue Dec 22 14:11:09 2015 +0000
+++ b/hgext/evolve.py Thu Nov 26 20:38:31 2015 -0500
@@ -896,7 +896,7 @@
class MergeFailure(error.Abort):
pass
-def relocate(repo, orig, dest, keepbranch=False):
+def relocate(repo, orig, dest, pctx=None, keepbranch=False):
"""rewrite <rev> on dest"""
if orig.rev() == dest.rev():
raise error.Abort(_('tried to relocate a node on top of itself'),
@@ -905,11 +905,13 @@
"manually with nothing to rebase - working "
"directory parent is also destination"))
- if not orig.p2().rev() == node.nullrev:
- raise error.Abort(
- 'no support for evolving merge changesets yet',
- hint="Redo the merge and use `hg prune <old> --succ <new>` "
- "to obsolete the old one")
+ if pctx is None:
+ if len(orig.parents()) == 2:
+ raise error.Abort(_("tried to relocate a merge commit without "
+ "specifying which parent should be moved"),
+ hint=_("Specify the parent by passing in pctx"))
+ pctx = orig.p1()
+
destbookmarks = repo.nodebookmarks(dest.node())
nodesrc = orig.node()
destphase = repo[nodesrc].phase()
@@ -949,7 +951,19 @@
bmdeactivate(repo)
if keepbranch:
repo.dirstate.setbranch(orig.branch())
- r = merge.graft(repo, orig, orig.p1(), ['local', 'graft'])
+
+ try:
+ r = merge.graft(repo, orig, pctx, ['local', 'graft'], True)
+ except TypeError:
+ # not using recent enough mercurial
+ if len(orig.parents()) == 2:
+ raise error.Abort(
+ _("no support for evolving merge changesets yet"),
+ hint=_("Redo the merge and use `hg prune <old> --succ "
+ "<new>` to obsolete the old one"))
+
+ r = merge.graft(repo, orig, pctx, ['local', 'graft'])
+
if r[-1]: #some conflict
raise error.Abort(
'unresolved merge conflicts (see hg help resolve)')
@@ -1734,13 +1748,20 @@
def _solveunstable(ui, repo, orig, dryrun=False, confirm=False,
progresscb=None):
"""Stabilize an unstable changeset"""
- obs = orig.parents()[0]
- if not obs.obsolete() and len(orig.parents()) == 2:
- obs = orig.parents()[1] # second parent is obsolete ?
-
- if not obs.obsolete():
+ pctx = orig.p1()
+ if len(orig.parents()) == 2:
+ if not pctx.obsolete():
+ pctx = orig.p2() # second parent is obsolete ?
+ elif orig.p2().obsolete():
+ raise error.Abort(_("no support for evolving merge changesets "
+ "with two obsolete parents yet"),
+ hint=_("Redo the merge and use `hg prune <old> "
+ "--succ <new>` to obsolete the old one"))
+
+ if not pctx.obsolete():
ui.warn(_("cannot solve instability of %s, skipping\n") % orig)
return False
+ obs = pctx
newer = obsolete.successorssets(repo, obs.node())
# search of a parent which is not killed
while not newer or newer == [()]:
@@ -1786,7 +1807,7 @@
if progresscb: progresscb()
keepbranch = orig.p1().branch() != orig.branch()
try:
- relocate(repo, orig, target, keepbranch)
+ relocate(repo, orig, target, pctx, keepbranch)
except MergeFailure:
repo.opener.write('graftstate', orig.hex() + '\n')
repo.ui.write_err(_('evolve failed!\n'))
--- a/tests/test-unstable.t Tue Dec 22 14:11:09 2015 +0000
+++ b/tests/test-unstable.t Thu Nov 26 20:38:31 2015 -0500
@@ -103,17 +103,13 @@
$ hg evo --all --any --unstable
move:[3] merge
atop:[4] aprime
- abort: no support for evolving merge changesets yet
- (Redo the merge and use `hg prune <old> --succ <new>` to obsolete the old one)
- [255]
+ working directory is now at 0bf3f3a59c8c
$ hg log -G
- @ 4:47127ea62e5f@default(draft) aprime
- |
- | o 3:6b4280e33286@default(draft) merge
- | |\
- +---o 2:474da87dd33b@default(draft) add _c
+ @ 5:0bf3f3a59c8c@default(draft) merge
+ |\
+ | o 4:47127ea62e5f@default(draft) aprime
| |
- | x 1:b3264cec9506@default(draft) add _a
+ o | 2:474da87dd33b@default(draft) add _c
|/
o 0:b4952fcf48cf@default(draft) add base
@@ -158,9 +154,7 @@
$ hg evo --all --any --unstable
- move:[3] merge
- atop:[5] cprime
- abort: no support for evolving merge changesets yet
+ abort: no support for evolving merge changesets with two obsolete parents yet
(Redo the merge and use `hg prune <old> --succ <new>` to obsolete the old one)
[255]
$ hg log -G