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