--- a/mercurial/merge.py Tue May 02 23:47:10 2017 -0700
+++ b/mercurial/merge.py Wed May 03 10:43:59 2017 -0700
@@ -786,7 +786,7 @@
return True
def manifestmerge(repo, wctx, p2, pa, branchmerge, force, matcher,
- acceptremote, followcopies):
+ acceptremote, followcopies, forcefulldiff=False):
"""
Merge wctx and p2 with ancestor pa and generate merge action list
@@ -821,6 +821,26 @@
if any(wctx.sub(s).dirty() for s in wctx.substate):
m1['.hgsubstate'] = modifiednodeid
+ # Don't use m2-vs-ma optimization if:
+ # - ma is the same as m1 or m2, which we're just going to diff again later
+ # - The matcher is set already, so we can't override it
+ # - The caller specifically asks for a full diff, which is useful during bid
+ # merge.
+ if (pa not in ([wctx, p2] + wctx.parents()) and
+ matcher is None and not forcefulldiff):
+ # Identify which files are relevant to the merge, so we can limit the
+ # total m1-vs-m2 diff to just those files. This has significant
+ # performance benefits in large repositories.
+ relevantfiles = set(ma.diff(m2).keys())
+
+ # For copied and moved files, we need to add the source file too.
+ for copykey, copyvalue in copy.iteritems():
+ if copyvalue in relevantfiles:
+ relevantfiles.add(copykey)
+ for movedirkey in movewithdir.iterkeys():
+ relevantfiles.add(movedirkey)
+ matcher = scmutil.matchfiles(repo, relevantfiles)
+
diff = m1.diff(m2, match=matcher)
if matcher is None:
@@ -974,7 +994,7 @@
repo.ui.note(_('\ncalculating bids for ancestor %s\n') % ancestor)
actions, diverge1, renamedelete1 = manifestmerge(
repo, wctx, mctx, ancestor, branchmerge, force, matcher,
- acceptremote, followcopies)
+ acceptremote, followcopies, forcefulldiff=True)
_checkunknownfiles(repo, wctx, mctx, force, actions, mergeforce)
# Track the shortest set of warning on the theory that bid