Patchwork D987: copies: add a config to limit the number of candidates to check in heuristics

login
register
mail settings
Submitter phabricator
Date Oct. 17, 2017, 9:30 p.m.
Message ID <56ba5215a6a32e334423a7a86288b1c4@localhost.localdomain>
Download mbox | patch
Permalink /patch/25144/
State Not Applicable
Headers show

Comments

phabricator - Oct. 17, 2017, 9:30 p.m.
pulkit updated this revision to Diff 2947.
pulkit edited the summary of this revision.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D987?vs=2539&id=2947

REVISION DETAIL
  https://phab.mercurial-scm.org/D987

AFFECTED FILES
  mercurial/configitems.py
  mercurial/copies.py
  tests/test-copytrace-heuristics.t

CHANGE DETAILS




To: pulkit, #hg-reviewers, yuja
Cc: stash, yuja, mercurial-devel

Patch

diff --git a/tests/test-copytrace-heuristics.t b/tests/test-copytrace-heuristics.t
--- a/tests/test-copytrace-heuristics.t
+++ b/tests/test-copytrace-heuristics.t
@@ -201,6 +201,65 @@ 
   $ cd ..
   $ rm -rf repo
 
+Test the copytrace.movecandidateslimit with many move candidates
+----------------------------------------------------------------
+
+  $ hg init repo
+  $ initclient repo
+  $ cd repo
+  $ echo a > a
+  $ hg add a
+  $ hg ci -m initial
+  $ hg mv a foo
+  $ echo a > b
+  $ echo a > c
+  $ echo a > d
+  $ echo a > e
+  $ echo a > f
+  $ echo a > g
+  $ hg add b
+  $ hg add c
+  $ hg add d
+  $ hg add e
+  $ hg add f
+  $ hg add g
+  $ hg ci -m 'mv a foo, add many files'
+  $ hg up -q ".^"
+  $ echo b > a
+  $ hg ci -m 'mod a'
+  created new head
+
+  $ hg log -G -T 'changeset: {node}\n desc: {desc}\n'
+  @  changeset: ef716627c70bf4ca0bdb623cfb0d6fe5b9acc51e
+  |   desc: mod a
+  | o  changeset: 8329d5c6bf479ec5ca59b9864f3f45d07213f5a4
+  |/    desc: mv a foo, add many files
+  o  changeset: 1451231c87572a7d3f92fc210b4b35711c949a98
+      desc: initial
+
+With small limit
+
+  $ hg rebase -s 2 -d 1 --config experimental.copytrace.movecandidateslimit=0
+  rebasing 2:ef716627c70b "mod a" (tip)
+  skipping copytracing for 'a', more candidates than the limit: 7
+  other [source] changed a which local [dest] deleted
+  use (c)hanged version, leave (d)eleted, or leave (u)nresolved? u
+  unresolved conflicts (see hg resolve, then hg rebase --continue)
+  [1]
+
+  $ hg rebase --abort
+  rebase aborted
+
+With default limit which is 100
+
+  $ hg rebase -s 2 -d 1
+  rebasing 2:ef716627c70b "mod a" (tip)
+  merging foo and a to foo
+  saved backup bundle to $TESTTMP/repo/.hg/strip-backup/ef716627c70b-24681561-rebase.hg (glob)
+
+  $ cd ..
+  $ rm -rf repo
+
 Move file in one branch and delete it in another
 -----------------------------------------------
 
diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -11,6 +11,8 @@ 
 import heapq
 import os
 
+from .i18n import _
+
 from . import (
     match as matchmod,
     node,
@@ -644,6 +646,11 @@ 
 
         [experimental]
         copytrace = heuristics
+
+    In some cases the copy/move candidates found by heuristics can be very large
+    in number and that will make the algorithm slow. The number of possible
+    candidates to check can be limited by using the config
+    `experimental.copytrace.movecandidateslimit` which defaults to 100.
     """
 
     if c1.rev() is None:
@@ -704,6 +711,17 @@ 
             # f is guaranteed to be present in c2, that's why
             # c2.filectx(f) won't fail
             f2 = c2.filectx(f)
+            # we can have a lot of candidates which can slow down the heuristics
+            # config value to limit the number of candidates moves to check
+            maxcandidates = repo.ui.configint('experimental',
+                                           'copytrace.movecandidateslimit')
+
+            if len(movecandidates) > maxcandidates:
+                repo.ui.status(_("skipping copytracing for '%s', more "
+                                 "candidates than the limit: %d\n")
+                                 % (f, len(movecandidates)))
+                continue
+
             for candidate in movecandidates:
                 f1 = c1.filectx(candidate)
                 if _related(f1, f2, anc.rev()):
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -330,6 +330,9 @@ 
 coreconfigitem('experimental', 'copytrace',
     default='on',
 )
+coreconfigitem('experimental', 'copytrace.movecandidateslimit',
+    default=100,
+)
 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
     default=100,
 )