Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/merge.py @ 23526:a5887f2da5e6
merge: don't treat 'diverge' and 'renamedelete' like actions
See earlier patch for motivation.
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Tue, 09 Dec 2014 16:49:55 -0800 |
parents | 5126d7718d7c |
children | 416c133145ee |
comparison
equal
deleted
inserted
replaced
23525:5126d7718d7c | 23526:a5887f2da5e6 |
---|---|
373 branchmerge and force are as passed in to update | 373 branchmerge and force are as passed in to update |
374 partial = function to filter file lists | 374 partial = function to filter file lists |
375 acceptremote = accept the incoming changes without prompting | 375 acceptremote = accept the incoming changes without prompting |
376 """ | 376 """ |
377 | 377 |
378 actions = dict((m, []) for m in 'a f g cd dc r dm dg m dr e rd k'.split()) | 378 actions = dict((m, []) for m in 'a f g cd dc r dm dg m e k'.split()) |
379 copy, movewithdir = {}, {} | 379 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {} |
380 | 380 |
381 # manifests fetched in order are going to be faster, so prime the caches | 381 # manifests fetched in order are going to be faster, so prime the caches |
382 [x.manifest() for x in | 382 [x.manifest() for x in |
383 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())] | 383 sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())] |
384 | 384 |
385 if followcopies: | 385 if followcopies: |
386 ret = copies.mergecopies(repo, wctx, p2, pa) | 386 ret = copies.mergecopies(repo, wctx, p2, pa) |
387 copy, movewithdir, diverge, renamedelete = ret | 387 copy, movewithdir, diverge, renamedelete = ret |
388 for of, fl in diverge.iteritems(): | |
389 actions['dr'].append((of, (fl,), "divergent renames")) | |
390 for of, fl in renamedelete.iteritems(): | |
391 actions['rd'].append((of, (fl,), "rename and delete")) | |
392 | 388 |
393 repo.ui.note(_("resolving manifests\n")) | 389 repo.ui.note(_("resolving manifests\n")) |
394 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n" | 390 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n" |
395 % (bool(branchmerge), bool(force), bool(partial))) | 391 % (bool(branchmerge), bool(force), bool(partial))) |
396 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2)) | 392 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2)) |
537 (force or not wctx.dirty(missing=True, branch=False))): | 533 (force or not wctx.dirty(missing=True, branch=False))): |
538 _checkcollision(repo, m2, None) | 534 _checkcollision(repo, m2, None) |
539 else: | 535 else: |
540 _checkcollision(repo, m1, actions) | 536 _checkcollision(repo, m1, actions) |
541 | 537 |
542 return actions | 538 return actions, diverge, renamedelete |
543 | 539 |
544 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial, | 540 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, partial, |
545 acceptremote, followcopies): | 541 acceptremote, followcopies): |
546 "Calculate the actions needed to merge mctx into wctx using ancestors" | 542 "Calculate the actions needed to merge mctx into wctx using ancestors" |
547 | 543 |
548 if len(ancestors) == 1: # default | 544 if len(ancestors) == 1: # default |
549 actions = manifestmerge(repo, wctx, mctx, ancestors[0], | 545 actions, diverge, renamedelete = manifestmerge( |
550 branchmerge, force, | 546 repo, wctx, mctx, ancestors[0], branchmerge, force, partial, |
551 partial, acceptremote, followcopies) | 547 acceptremote, followcopies) |
552 | 548 |
553 else: # only when merge.preferancestor=* - the default | 549 else: # only when merge.preferancestor=* - the default |
554 repo.ui.note( | 550 repo.ui.note( |
555 _("note: merging %s and %s using bids from ancestors %s\n") % | 551 _("note: merging %s and %s using bids from ancestors %s\n") % |
556 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors))) | 552 (wctx, mctx, _(' and ').join(str(anc) for anc in ancestors))) |
557 | 553 |
558 # Call for bids | 554 # Call for bids |
559 fbids = {} # mapping filename to bids (action method to list af actions) | 555 fbids = {} # mapping filename to bids (action method to list af actions) |
556 diverge, renamedelete = None, None | |
560 for ancestor in ancestors: | 557 for ancestor in ancestors: |
561 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor) | 558 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor) |
562 actions = manifestmerge(repo, wctx, mctx, ancestor, | 559 actions, diverge1, renamedelete1 = manifestmerge( |
563 branchmerge, force, | 560 repo, wctx, mctx, ancestor, branchmerge, force, partial, |
564 partial, acceptremote, followcopies) | 561 acceptremote, followcopies) |
562 if diverge is None: # and renamedelete is None. | |
563 # Arbitrarily pick warnings from first iteration | |
564 diverge = diverge1 | |
565 renamedelete = renamedelete1 | |
565 for m, l in sorted(actions.items()): | 566 for m, l in sorted(actions.items()): |
566 for a in l: | 567 for a in l: |
567 f, args, msg = a | 568 f, args, msg = a |
568 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m)) | 569 repo.ui.debug(' %s: %s -> %s\n' % (f, msg, m)) |
569 if f in fbids: | 570 if f in fbids: |
642 if wctx.rev() is None: | 643 if wctx.rev() is None: |
643 ractions, factions = _forgetremoved(wctx, mctx, branchmerge) | 644 ractions, factions = _forgetremoved(wctx, mctx, branchmerge) |
644 actions['r'].extend(ractions) | 645 actions['r'].extend(ractions) |
645 actions['f'].extend(factions) | 646 actions['f'].extend(factions) |
646 | 647 |
647 return actions | 648 return actions, diverge, renamedelete |
648 | 649 |
649 def batchremove(repo, actions): | 650 def batchremove(repo, actions): |
650 """apply removes to the working directory | 651 """apply removes to the working directory |
651 | 652 |
652 yields tuples for progress updates | 653 yields tuples for progress updates |
740 if os.path.lexists(repo.wjoin(f)): | 741 if os.path.lexists(repo.wjoin(f)): |
741 repo.ui.debug("removing %s\n" % f) | 742 repo.ui.debug("removing %s\n" % f) |
742 audit(f) | 743 audit(f) |
743 util.unlinkpath(repo.wjoin(f)) | 744 util.unlinkpath(repo.wjoin(f)) |
744 | 745 |
745 numupdates = sum(len(l) for m, l in actions.items() | 746 numupdates = sum(len(l) for m, l in actions.items() if m != 'k') |
746 if m not in ('k', 'dr', 'rd')) | |
747 | 747 |
748 if [a for a in actions['r'] if a[0] == '.hgsubstate']: | 748 if [a for a in actions['r'] if a[0] == '.hgsubstate']: |
749 subrepo.submerge(repo, wctx, mctx, wctx, overwrite) | 749 subrepo.submerge(repo, wctx, mctx, wctx, overwrite) |
750 | 750 |
751 # remove in parallel (must come first) | 751 # remove in parallel (must come first) |
1085 pass | 1085 pass |
1086 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True): | 1086 elif pas[0] and repo.ui.configbool('merge', 'followcopies', True): |
1087 followcopies = True | 1087 followcopies = True |
1088 | 1088 |
1089 ### calculate phase | 1089 ### calculate phase |
1090 actions = calculateupdates(repo, wc, p2, pas, branchmerge, force, | 1090 actions, diverge, renamedelete = calculateupdates( |
1091 partial, mergeancestor, followcopies) | 1091 repo, wc, p2, pas, branchmerge, force, partial, mergeancestor, |
1092 followcopies) | |
1092 | 1093 |
1093 ### apply phase | 1094 ### apply phase |
1094 if not branchmerge: # just jump to the new rev | 1095 if not branchmerge: # just jump to the new rev |
1095 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, '' | 1096 fp1, fp2, xp1, xp2 = fp2, nullid, xp2, '' |
1096 if not partial: | 1097 if not partial: |
1099 repo.vfs.write('updatestate', p2.hex()) | 1100 repo.vfs.write('updatestate', p2.hex()) |
1100 | 1101 |
1101 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels) | 1102 stats = applyupdates(repo, actions, wc, p2, overwrite, labels=labels) |
1102 | 1103 |
1103 # divergent renames | 1104 # divergent renames |
1104 for f, args, msg in actions['dr']: | 1105 for f, fl in sorted(diverge.iteritems()): |
1105 fl, = args | |
1106 repo.ui.warn(_("note: possible conflict - %s was renamed " | 1106 repo.ui.warn(_("note: possible conflict - %s was renamed " |
1107 "multiple times to:\n") % f) | 1107 "multiple times to:\n") % f) |
1108 for nf in fl: | 1108 for nf in fl: |
1109 repo.ui.warn(" %s\n" % nf) | 1109 repo.ui.warn(" %s\n" % nf) |
1110 | 1110 |
1111 # rename and delete | 1111 # rename and delete |
1112 for f, args, msg in actions['rd']: | 1112 for f, fl in sorted(renamedelete.iteritems()): |
1113 fl, = args | |
1114 repo.ui.warn(_("note: possible conflict - %s was deleted " | 1113 repo.ui.warn(_("note: possible conflict - %s was deleted " |
1115 "and renamed to:\n") % f) | 1114 "and renamed to:\n") % f) |
1116 for nf in fl: | 1115 for nf in fl: |
1117 repo.ui.warn(" %s\n" % nf) | 1116 repo.ui.warn(" %s\n" % nf) |
1118 | 1117 |