Mercurial > public > mercurial-scm > hg-stable
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]) |