comparison mercurial/copies.py @ 39393:a41497b5117c

copies: improve logic of deciding copytracing on based of config options Few months ago or maybe a year ago, I imported Fb's heuristics based copytracing algorithms. While importing that, I renamed `experimental.disablecopytrace` with `experimental.copytrace` and the behavior of the new config option was like this: * "heuristics" : Fb's heuristic copytracing algorithm * "off" : copytracing is turned off * something else: copytracing is on This is the behavior right now also and this is bad because it hardcodes the string 'off' to turn off the copytracing. On big repositories, copytracing is very slow and people wants to turn copytracing off. However if the user sets it to 'False', 'Off', '0', none of them is going to disbale copytracing while they should. I lacked the understanding of why this can be bad when I coded it. After this patch, the new behavior of the config option will be: * "heuristics": Fb's heuristic copytracing algorithm * '0', 'false', 'off', 'never', 'no', 'NO', all the values which repo.ui.configbool() evaluates to False: copytracing in turned off * something else: copytracing is on Since 'off' still evaluates to copytracing being turned off, this is not BC. Also the config option is experimental. Differential Revision: https://phab.mercurial-scm.org/D4416
author Pulkit Goyal <pulkit@yandex-team.ru>
date Wed, 29 Aug 2018 18:52:09 +0300
parents eebd591803ab
children 85c8ff26d698
comparison
equal deleted inserted replaced
39392:659e2bbd0c20 39393:a41497b5117c
17 match as matchmod, 17 match as matchmod,
18 node, 18 node,
19 pathutil, 19 pathutil,
20 scmutil, 20 scmutil,
21 util, 21 util,
22 )
23 from .utils import (
24 stringutil,
22 ) 25 )
23 26
24 def _findlimit(repo, a, b): 27 def _findlimit(repo, a, b):
25 """ 28 """
26 Find the last revision that needs to be checked to ensure that a full 29 Find the last revision that needs to be checked to ensure that a full
364 # avoid silly behavior for parent -> working dir 367 # avoid silly behavior for parent -> working dir
365 if c2.node() is None and c1.node() == repo.dirstate.p1(): 368 if c2.node() is None and c1.node() == repo.dirstate.p1():
366 return repo.dirstate.copies(), {}, {}, {}, {} 369 return repo.dirstate.copies(), {}, {}, {}, {}
367 370
368 copytracing = repo.ui.config('experimental', 'copytrace') 371 copytracing = repo.ui.config('experimental', 'copytrace')
372 boolctrace = stringutil.parsebool(copytracing)
369 373
370 # Copy trace disabling is explicitly below the node == p1 logic above 374 # Copy trace disabling is explicitly below the node == p1 logic above
371 # because the logic above is required for a simple copy to be kept across a 375 # because the logic above is required for a simple copy to be kept across a
372 # rebase. 376 # rebase.
373 if copytracing == 'off': 377 if copytracing == 'heuristics':
374 return {}, {}, {}, {}, {}
375 elif copytracing == 'heuristics':
376 # Do full copytracing if only non-public revisions are involved as 378 # Do full copytracing if only non-public revisions are involved as
377 # that will be fast enough and will also cover the copies which could 379 # that will be fast enough and will also cover the copies which could
378 # be missed by heuristics 380 # be missed by heuristics
379 if _isfullcopytraceable(repo, c1, base): 381 if _isfullcopytraceable(repo, c1, base):
380 return _fullcopytracing(repo, c1, c2, base) 382 return _fullcopytracing(repo, c1, c2, base)
381 return _heuristicscopytracing(repo, c1, c2, base) 383 return _heuristicscopytracing(repo, c1, c2, base)
384 elif boolctrace is False:
385 # stringutil.parsebool() returns None when it is unable to parse the
386 # value, so we should rely on making sure copytracing is on such cases
387 return {}, {}, {}, {}, {}
382 else: 388 else:
383 return _fullcopytracing(repo, c1, c2, base) 389 return _fullcopytracing(repo, c1, c2, base)
384 390
385 def _isfullcopytraceable(repo, c1, base): 391 def _isfullcopytraceable(repo, c1, base):
386 """ Checks that if base, source and destination are all no-public branches, 392 """ Checks that if base, source and destination are all no-public branches,
868 filter copy records. Any copies that occur between fromrev and 874 filter copy records. Any copies that occur between fromrev and
869 skiprev will not be duplicated, even if they appear in the set of 875 skiprev will not be duplicated, even if they appear in the set of
870 copies between fromrev and rev. 876 copies between fromrev and rev.
871 """ 877 """
872 exclude = {} 878 exclude = {}
879 ctraceconfig = repo.ui.config('experimental', 'copytrace')
880 bctrace = stringutil.parsebool(ctraceconfig)
873 if (skiprev is not None and 881 if (skiprev is not None and
874 repo.ui.config('experimental', 'copytrace') != 'off'): 882 (ctraceconfig == 'heuristics' or bctrace or bctrace is None)):
875 # copytrace='off' skips this line, but not the entire function because 883 # copytrace='off' skips this line, but not the entire function because
876 # the line below is O(size of the repo) during a rebase, while the rest 884 # the line below is O(size of the repo) during a rebase, while the rest
877 # of the function is much faster (and is required for carrying copy 885 # of the function is much faster (and is required for carrying copy
878 # metadata across the rebase anyway). 886 # metadata across the rebase anyway).
879 exclude = pathcopies(repo[fromrev], repo[skiprev]) 887 exclude = pathcopies(repo[fromrev], repo[skiprev])