comparison mercurial/merge.py @ 27346:ba0da4b7397d

merge: rework manifestmerge to use a matcher This opens the door to working slightly more closely with the manifest type and letting it optimize out some of the diff comparisons for us, and also makes life significantly easier for narrowhg.
author Augie Fackler <augie@google.com>
date Mon, 14 Dec 2015 20:47:22 -0500
parents 98266b1d144d
children 2e31a17ad1bf
comparison
equal deleted inserted replaced
27345:98266b1d144d 27346:ba0da4b7397d
681 """run the conclude step of the merge driver, if any 681 """run the conclude step of the merge driver, if any
682 682
683 This is currently not implemented -- it's an extension point.""" 683 This is currently not implemented -- it's an extension point."""
684 return True 684 return True
685 685
686 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial, 686 def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher,
687 acceptremote, followcopies): 687 acceptremote, followcopies):
688 """ 688 """
689 Merge p1 and p2 with ancestor pa and generate merge action list 689 Merge p1 and p2 with ancestor pa and generate merge action list
690 690
691 branchmerge and force are as passed in to update 691 branchmerge and force are as passed in to update
692 partial = function to filter file lists 692 matcher = matcher to filter file lists
693 acceptremote = accept the incoming changes without prompting 693 acceptremote = accept the incoming changes without prompting
694 """ 694 """
695 if matcher is not None and matcher.always():
696 matcher = None
695 697
696 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {} 698 copy, movewithdir, diverge, renamedelete = {}, {}, {}, {}
697 699
698 # manifests fetched in order are going to be faster, so prime the caches 700 # manifests fetched in order are going to be faster, so prime the caches
699 [x.manifest() for x in 701 [x.manifest() for x in
703 ret = copies.mergecopies(repo, wctx, p2, pa) 705 ret = copies.mergecopies(repo, wctx, p2, pa)
704 copy, movewithdir, diverge, renamedelete = ret 706 copy, movewithdir, diverge, renamedelete = ret
705 707
706 repo.ui.note(_("resolving manifests\n")) 708 repo.ui.note(_("resolving manifests\n"))
707 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n" 709 repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
708 % (bool(branchmerge), bool(force), bool(partial))) 710 % (bool(branchmerge), bool(force), bool(matcher)))
709 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2)) 711 repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
710 712
711 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest() 713 m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
712 copied = set(copy.values()) 714 copied = set(copy.values())
713 copied.update(movewithdir.values()) 715 copied.update(movewithdir.values())
722 # Compare manifests 724 # Compare manifests
723 diff = m1.diff(m2) 725 diff = m1.diff(m2)
724 726
725 actions = {} 727 actions = {}
726 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems(): 728 for f, ((n1, fl1), (n2, fl2)) in diff.iteritems():
727 if partial and not partial(f): 729 if matcher and not matcher(f):
728 continue 730 continue
729 if n1 and n2: # file exists on both local and remote side 731 if n1 and n2: # file exists on both local and remote side
730 if f not in ma: 732 if f not in ma:
731 fa = copy.get(f, None) 733 fa = copy.get(f, None)
732 if fa is not None: 734 if fa is not None:
842 del actions[f] # don't get = keep local deleted 844 del actions[f] # don't get = keep local deleted
843 845
844 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force, 846 def calculateupdates(repo, wctx, mctx, ancestors, branchmerge, force,
845 acceptremote, followcopies, matcher=None): 847 acceptremote, followcopies, matcher=None):
846 "Calculate the actions needed to merge mctx into wctx using ancestors" 848 "Calculate the actions needed to merge mctx into wctx using ancestors"
847 if matcher is None or matcher.always():
848 partial = False
849 else:
850 partial = matcher.matchfn
851
852 if len(ancestors) == 1: # default 849 if len(ancestors) == 1: # default
853 actions, diverge, renamedelete = manifestmerge( 850 actions, diverge, renamedelete = manifestmerge(
854 repo, wctx, mctx, ancestors[0], branchmerge, force, partial, 851 repo, wctx, mctx, ancestors[0], branchmerge, force, matcher,
855 acceptremote, followcopies) 852 acceptremote, followcopies)
856 _checkunknownfiles(repo, wctx, mctx, force, actions) 853 _checkunknownfiles(repo, wctx, mctx, force, actions)
857 854
858 else: # only when merge.preferancestor=* - the default 855 else: # only when merge.preferancestor=* - the default
859 repo.ui.note( 856 repo.ui.note(
864 fbids = {} # mapping filename to bids (action method to list af actions) 861 fbids = {} # mapping filename to bids (action method to list af actions)
865 diverge, renamedelete = None, None 862 diverge, renamedelete = None, None
866 for ancestor in ancestors: 863 for ancestor in ancestors:
867 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor) 864 repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
868 actions, diverge1, renamedelete1 = manifestmerge( 865 actions, diverge1, renamedelete1 = manifestmerge(
869 repo, wctx, mctx, ancestor, branchmerge, force, partial, 866 repo, wctx, mctx, ancestor, branchmerge, force, matcher,
870 acceptremote, followcopies) 867 acceptremote, followcopies)
871 _checkunknownfiles(repo, wctx, mctx, force, actions) 868 _checkunknownfiles(repo, wctx, mctx, force, actions)
872 869
873 # Track the shortest set of warning on the theory that bid 870 # Track the shortest set of warning on the theory that bid
874 # merge will correctly incorporate more information 871 # merge will correctly incorporate more information