Mercurial > public > mercurial-scm > hg
comparison mercurial/copies.py @ 30203:b94b92f0c683
checkcopies: add logic to handle remotebase
As the two _checkcopies passes' ranges are separated by tca, not base,
only one of the two passes will actually encounter the base.
Pass "remotebase" to the other pass to let it know not to expect passing
over the base. This is required for handling a few unusual rename cases.
author | G?bor Stefanik <gabor.stefanik@nng.com> |
---|---|
date | Tue, 11 Oct 2016 04:25:59 +0200 |
parents | a005c33d0bd7 |
children | 1894c830ee74 |
comparison
equal
deleted
inserted
replaced
30202:a005c33d0bd7 | 30203:b94b92f0c683 |
---|---|
411 u1u, u2u = _computenonoverlap(repo, c1, c2, m1.filesnotin(mta), | 411 u1u, u2u = _computenonoverlap(repo, c1, c2, m1.filesnotin(mta), |
412 m2.filesnotin(mta), | 412 m2.filesnotin(mta), |
413 baselabel='topological common ancestor') | 413 baselabel='topological common ancestor') |
414 | 414 |
415 for f in u1u: | 415 for f in u1u: |
416 _checkcopies(c1, f, m1, m2, base, tca, limit, data1) | 416 _checkcopies(c1, f, m1, m2, base, tca, dirtyc1, limit, data1) |
417 | 417 |
418 for f in u2u: | 418 for f in u2u: |
419 _checkcopies(c2, f, m2, m1, base, tca, limit, data2) | 419 _checkcopies(c2, f, m2, m1, base, tca, dirtyc2, limit, data2) |
420 | 420 |
421 copy = dict(data1['copy'].items() + data2['copy'].items()) | 421 copy = dict(data1['copy'].items() + data2['copy'].items()) |
422 fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items()) | 422 fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items()) |
423 | 423 |
424 if dirtyc1: | 424 if dirtyc1: |
458 'incomplete': {}, | 458 'incomplete': {}, |
459 'diverge': bothdiverge, | 459 'diverge': bothdiverge, |
460 'incompletediverge': bothincompletediverge | 460 'incompletediverge': bothincompletediverge |
461 } | 461 } |
462 for f in bothnew: | 462 for f in bothnew: |
463 _checkcopies(c1, f, m1, m2, base, tca, limit, both1) | 463 _checkcopies(c1, f, m1, m2, base, tca, dirtyc1, limit, both1) |
464 _checkcopies(c2, f, m2, m1, base, tca, limit, both2) | 464 _checkcopies(c2, f, m2, m1, base, tca, dirtyc2, limit, both2) |
465 if dirtyc1: | 465 if dirtyc1: |
466 assert both2['incomplete'] == {} | 466 assert both2['incomplete'] == {} |
467 remainder = _combinecopies({}, both1['incomplete'], copy, bothdiverge, | 467 remainder = _combinecopies({}, both1['incomplete'], copy, bothdiverge, |
468 bothincompletediverge) | 468 bothincompletediverge) |
469 else: | 469 else: |
588 elif f1r == f2r or f1r < limit or f2r < limit: | 588 elif f1r == f2r or f1r < limit or f2r < limit: |
589 return False # copy no longer relevant | 589 return False # copy no longer relevant |
590 except StopIteration: | 590 except StopIteration: |
591 return False | 591 return False |
592 | 592 |
593 def _checkcopies(ctx, f, m1, m2, base, tca, limit, data): | 593 def _checkcopies(ctx, f, m1, m2, base, tca, remotebase, limit, data): |
594 """ | 594 """ |
595 check possible copies of f from m1 to m2 | 595 check possible copies of f from m1 to m2 |
596 | 596 |
597 ctx = starting context for f in m1 | 597 ctx = starting context for f in m1 |
598 f = the filename to check (as in m1) | 598 f = the filename to check (as in m1) |
599 m1 = the source manifest | 599 m1 = the source manifest |
600 m2 = the destination manifest | 600 m2 = the destination manifest |
601 base = the changectx used as a merge base | 601 base = the changectx used as a merge base |
602 tca = topological common ancestor for graft-like scenarios | 602 tca = topological common ancestor for graft-like scenarios |
603 remotebase = True if base is outside tca::ctx, False otherwise | |
603 limit = the rev number to not search beyond | 604 limit = the rev number to not search beyond |
604 data = dictionary of dictionary to store copy data. (see mergecopies) | 605 data = dictionary of dictionary to store copy data. (see mergecopies) |
605 | 606 |
606 note: limit is only an optimization, and there is no guarantee that | 607 note: limit is only an optimization, and there is no guarantee that |
607 irrelevant revisions will not be limited | 608 irrelevant revisions will not be limited |
617 # traversed backwards. | 618 # traversed backwards. |
618 # | 619 # |
619 # In the case there is both backward and forward renames (before and after | 620 # In the case there is both backward and forward renames (before and after |
620 # the base) this is more complicated as we must detect a divergence. | 621 # the base) this is more complicated as we must detect a divergence. |
621 # We use 'backwards = False' in that case. | 622 # We use 'backwards = False' in that case. |
622 backwards = base != tca and f in mb | 623 backwards = not remotebase and base != tca and f in mb |
623 getfctx = _makegetfctx(ctx) | 624 getfctx = _makegetfctx(ctx) |
624 | 625 |
625 of = None | 626 of = None |
626 seen = set([f]) | 627 seen = set([f]) |
627 for oc in getfctx(f, m1[f]).ancestors(): | 628 for oc in getfctx(f, m1[f]).ancestors(): |
650 if cr and (of == f or of == c2.path()): # non-divergent | 651 if cr and (of == f or of == c2.path()): # non-divergent |
651 if backwards: | 652 if backwards: |
652 data['copy'][of] = f | 653 data['copy'][of] = f |
653 elif of in mb: | 654 elif of in mb: |
654 data['copy'][f] = of | 655 data['copy'][f] = of |
656 elif remotebase: # special case: a <- b <- a -> b "ping-pong" rename | |
657 data['copy'][of] = f | |
658 del data['fullcopy'][f] | |
659 data['fullcopy'][of] = f | |
655 else: # divergence w.r.t. graft CA on one side of topological CA | 660 else: # divergence w.r.t. graft CA on one side of topological CA |
656 for sf in seen: | 661 for sf in seen: |
657 if sf in mb: | 662 if sf in mb: |
658 assert sf not in data['diverge'] | 663 assert sf not in data['diverge'] |
659 data['diverge'][sf] = [f, of] | 664 data['diverge'][sf] = [f, of] |