[PATCH evolve-ext] evolve: handle merge commit with single obsolete parent (issue4389)

Pierre-Yves David pierre-yves.david at ens-lyon.org
Wed Dec 2 19:58:37 UTC 2015



On 11/26/2015 06:41 PM, Andrew Halberstadt wrote:
> # HG changeset patch
> # User Andrew Halberstadt <ahalberstadt at mozilla.com>
> # Date 1448588311 18000
> #      Thu Nov 26 20:38:31 2015 -0500
> # Node ID 21b5e4b3df092855c554331587fdd7b713b9551e
> # Parent  72f50a17780674de8f372803a333d43c77230df5
> evolve: handle merge commit with single obsolete parent (issue4389)

This is a nice change, but it is done in the wrong layer.

The relocate function is not expected to know anything about the higher 
level evolution process. We should not be adding evolution related logic 
as this patch do.

The code modified here is responsible for finding the proper merge base 
and bail out in case of merge because of the ambiguity. We should add 
some "parents/base" argument and compute what it should be in the higher 
function actually calling relocate.

> diff --git a/hgext/evolve.py b/hgext/evolve.py
> --- a/hgext/evolve.py
> +++ b/hgext/evolve.py
> @@ -899,20 +899,32 @@ def relocate(repo, orig, dest, keepbranc
>       """rewrite <rev> on dest"""
>       if orig.rev() == dest.rev():
>           raise util.Abort(_('tried to relocate a node on top of itself'),
>                            hint=_("This shouldn't happen. If you still "
>                                   "need to move changesets, please do so "
>                                   "manually with nothing to rebase - working "
>                                   "directory parent is also destination"))
>
> -    if not orig.p2().rev() == node.nullrev:
> -        raise util.Abort(
> -            'no support for evolving merge changesets yet',
> -            hint="Redo the merge and use `hg prune <old> --succ <new>` to obsolete the old one")
> +    parents = orig.parents()
> +    if len(parents) == 2:
> +        if all(p.obsolete() for p in parents):
> +            raise util.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")
> +
> +        for p in parents:
> +            if p.obsolete():
> +                pctx = p
> +            else:
> +                pother = p.node()
> +    else:
> +        pctx = orig.p1()
> +        pother = nullid
> +
>       destbookmarks = repo.nodebookmarks(dest.node())
>       nodesrc = orig.node()
>       destphase = repo[nodesrc].phase()
>       commitmsg = orig.description()
>
>       cache = {}
>       sha1s = re.findall(sha1re, commitmsg)
>       unfi = repo.unfiltered()
> @@ -942,17 +954,26 @@ def relocate(repo, orig, dest, keepbranc
>           try:
>               if repo['.'].rev() != dest.rev():
>                   merge.update(repo, dest, False, True, False)
>               if bmactive(repo):
>                   repo.ui.status(_("(leaving bookmark %s)\n") % bmactive(repo))
>               bmdeactivate(repo)
>               if keepbranch:
>                   repo.dirstate.setbranch(orig.branch())
> -            r = merge.graft(repo, orig, orig.p1(), ['local', 'graft'])
> +            r = merge.graft(repo, orig, pctx, ['local', 'graft'])
> +
> +            if pother != nullid:
> +                # Add back the original second parent which got nullified
> +                # by merge.graft().
> +                repo.dirstate.beginparentchange()
> +                repo.setparents(repo['.'].node(), pother)
> +                repo.dirstate.write(repo.currenttransaction())
> +                repo.dirstate.endparentchange()

Could we get hg graft able to grat merge instead (basically the same 
drill as what is needed of relocate)

Many thanks for working on this.

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list