[PATCH 06 of 11] ?copies: update _checkcopies to work in a rotated DAG (issue4028)
Gábor STEFANIK
Gabor.STEFANIK at nng.com
Wed Oct 5 08:04:13 EDT 2016
>
--------------------------------------------------------------------------
This message, including its attachments, is confidential. For more information please read NNG's email policy here:
http://www.nng.com/emailpolicy/
By responding to this email you accept the email policy.
-----Original Message-----
> From: Mercurial-devel [mailto:mercurial-devel-bounces at mercurial-scm.org]
> On Behalf Of Gábor Stefanik
> Sent: Wednesday, October 5, 2016 2:02 PM
> To: mercurial-devel at mercurial-scm.org
> Subject: [PATCH 06 of 11] ?copies: update _checkcopies to work in a rotated
> DAG (issue4028)
>
> # HG changeset patch
> # User G?bor Stefanik <gabor.stefanik at nng.com> # Date 1475588213 -7200
> # Tue Oct 04 15:36:53 2016 +0200
> # Node ID fc6190cdbebfab4a3cff72f213018fcc30b8f25c
> # Parent bc8729a69d10d61498712d5dab773918f1edcde0
> ?copies: update _checkcopies to work in a rotated DAG (issue4028)
Ouch! Even worse encoding errors.
>
> This introduces a distinction between "merge common ancestor" and
> "topological common ancestor". During a regular merge, these two are
> identical. Graft, however, performs a merge in a rotated DAG, where the
> merge common ancestor will not be a common ancestor at all in the original
> DAG.
>
> To correctly find copies in case of a graft, we need to take both the merge CA
> and the topological CA into account, and track any renames between them in
> reverse.
>
> Special care must be taken about the case where the merge CA lies not
> between the topological CA and the source, but outside it (typically between
> the topological CA and the destination).
> This is handled using the remoteca parameter; it would be possible to have
> _checkcopies itself detect this, but it's quite expensive and also guaranteed
> not to change between multiple _checkcopies invocations in the same
> mergecopies call, so it's better to check it there, and pass to _checkcopies as
> a parameter.
>
> diff -r bc8729a69d10 -r fc6190cdbebf mercurial/copies.py
> --- a/mercurial/copies.pyMon Oct 03 13:29:59 2016 +0200
> +++ b/mercurial/copies.pyTue Oct 04 15:36:53 2016 +0200
> @@ -345,10 +345,12 @@
> bothnew = sorted(addedinm1 & addedinm2)
>
> for f in u1u:
> - _checkcopies(c1, f, m1, m2, ca, limit, diverge, copy1, fullcopy1)
> + _checkcopies(c1, f, m1, m2, ca, ca, False, limit, diverge, copy1,
> + fullcopy1)
>
> for f in u2u:
> - _checkcopies(c2, f, m2, m1, ca, limit, diverge, copy2, fullcopy2)
> + _checkcopies(c2, f, m2, m1, ca, ca, False, limit, diverge, copy2,
> + fullcopy2)
>
> copy = dict(copy1.items() + copy2.items())
> movewithdir = dict(movewithdir1.items() + movewithdir2.items()) @@ -
> 373,8 +375,10 @@
> % "\n ".join(bothnew))
> bothdiverge, _copy, _fullcopy = {}, {}, {}
> for f in bothnew:
> - _checkcopies(c1, f, m1, m2, ca, limit, bothdiverge, _copy, _fullcopy)
> - _checkcopies(c2, f, m2, m1, ca, limit, bothdiverge, _copy, _fullcopy)
> + _checkcopies(c1, f, m1, m2, ca, ca, False, limit, bothdiverge, _copy,
> + _fullcopy)
> + _checkcopies(c2, f, m2, m1, ca, ca, False, limit, bothdiverge, _copy,
> + _fullcopy)
> for of, fl in bothdiverge.items():
> if len(fl) == 2 and fl[0] == fl[1]:
> copy[fl[0]] = of # not actually divergent, just matching renames @@ -
> 454,7 +458,8 @@
>
> return copy, movewithdir, diverge, renamedelete
>
> -def _checkcopies(ctx, f, m1, m2, ca, limit, diverge, copy, fullcopy):
> +def _checkcopies(ctx, f, m1, m2, ca, tca, remoteca, limit, diverge, copy,
> + fullcopy):
> """
> check possible copies of f from m1 to m2
>
> @@ -462,7 +467,9 @@
> f = the filename to check
> m1 = the source manifest
> m2 = the destination manifest
> - ca = the changectx of the common ancestor
> + ca = the changectx of the common ancestor, overridden on graft
> + tca = topological common ancestor for graft-like scenarios
> + remoteca = True if ca is outside tca::ctx, False otherwise
> limit = the rev number to not search beyond
> diverge = record all diverges in this dict
> copy = record all non-divergent copies in this dict @@ -475,6 +482,8 @@
> """
>
> ma = ca.manifest()
> + mta = tca.manifest()
> + backwards = ca != tca and not remoteca and f in ma
> getfctx = _makegetfctx(ctx)
>
> def _related(f1, f2, limit):
> @@ -520,15 +529,26 @@
> continue
> seen.add(of)
>
> - fullcopy[f] = of # remember for dir rename detection
> + # remember for dir rename detection
> + if backwards:
> + fullcopy[of] = f # grafting backwards through renames
> + else:
> + fullcopy[f] = of
> if of not in m2:
> continue # no match, keep looking
> if m2[of] == ma.get(of):
> return # no merge needed, quit early
> c2 = getfctx(of, m2[of])
> - cr = _related(oc, c2, ca.rev())
> + cr = _related(oc, c2, tca.rev())
> if cr and (of == f or of == c2.path()): # non-divergent
> - copy[f] = of
> + if backwards:
> + copy[of] = f
> + elif of in ma:
> + copy[f] = of
> + elif remoteca: # special case: a <- b <- a -> b "ping-pong" rename
> + copy[of] = f
> + del fullcopy[f]
> + fullcopy[of] = f
> return
>
> if of in ma:
> diff -r bc8729a69d10 -r fc6190cdbebf tests/test-graft.t
> --- a/tests/test-graft.tMon Oct 03 13:29:59 2016 +0200
> +++ b/tests/test-graft.tTue Oct 04 15:36:53 2016 +0200
> @@ -427,8 +427,8 @@
> $ hg graft 3 --log -u foo
> grafting 3:4c60f11aa304 "3"
> warning: can't find ancestor for 'c' copied from 'b'!
> - $ hg log --template '{rev} {parents} {desc}\n' -r tip
> - 14 1:5d205f8b35b6 3
> + $ hg log --template '{rev}:{node|short} {parents} {desc}\n' -r tip
> + 14:0c921c65ef1e 1:5d205f8b35b6 3
> (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
>
> Resolve conflicted graft
> @@ -620,7 +620,7 @@
> date: Thu Jan 01 00:00:00 1970 +0000
> summary: 2
>
> - changeset: 14:f64defefacee
> + changeset: 14:0c921c65ef1e
> parent: 1:5d205f8b35b6
> user: foo
> date: Thu Jan 01 00:00:00 1970 +0000
More information about the Mercurial-devel
mailing list