diff --git a/mercurial/merge.py b/mercurial/merge.py --- a/mercurial/merge.py +++ b/mercurial/merge.py @@ -786,7 +786,7 @@ def driverconclude(repo, ms, wctx, label 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 @@ def manifestmerge(repo, wctx, p2, pa, br 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 @@ def calculateupdates(repo, wctx, mctx, a 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 diff --git a/tests/test-graft.t b/tests/test-graft.t --- a/tests/test-graft.t +++ b/tests/test-graft.t @@ -186,7 +186,6 @@ Graft out of order, skipping a merge and ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746 e: remote is newer -> g getting e - b: remote unchanged -> k committing files: e committing manifest @@ -203,7 +202,6 @@ Graft out of order, skipping a merge and preserving e for resolve of e d: remote is newer -> g getting d - b: remote unchanged -> k e: versions differ -> m (premerge) picked tool ':merge' for e (binary False symlink False changedelete False) merging e diff --git a/tests/test-issue672.t b/tests/test-issue672.t --- a/tests/test-issue672.t +++ b/tests/test-issue672.t @@ -38,7 +38,6 @@ https://bz.mercurial-scm.org/672 removing 1 1a: remote created -> g getting 1a - 2: remote unchanged -> k 1 files updated, 0 files merged, 1 files removed, 0 files unresolved (branch merge, don't forget to commit) diff --git a/tests/test-rename-merge2.t b/tests/test-rename-merge2.t --- a/tests/test-rename-merge2.t +++ b/tests/test-rename-merge2.t @@ -89,7 +89,6 @@ args: preserving a for resolve of b preserving rev for resolve of rev starting 4 threads for background file closing (?) - a: remote unchanged -> k b: remote copied from a -> m (premerge) picked tool 'python ../merge' for b (binary False symlink False changedelete False) merging a and b to b @@ -652,7 +651,6 @@ m "um a c" "um x c" " " "10 do merg preserving b for resolve of b preserving rev for resolve of rev starting 4 threads for background file closing (?) - a: remote unchanged -> k b: both created -> m (premerge) picked tool 'python ../merge' for b (binary False symlink False changedelete False) merging b