diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -1470,6 +1470,12 @@ _(b'repair revisions listed in this report file'), _(b'FILE'), ), + ( + b'', + b'paranoid', + False, + _(b'check that both detection methods do the same thing'), + ), ] + cmdutil.dryrunopts, ) @@ -1491,6 +1497,11 @@ Note that this does *not* mean that this repairs future affected revisions, that needs a separate fix at the exchange level that hasn't been written yet (as of 5.9rc0). + + There is a `--paranoid` flag to test that the fast implementation is correct + by checking it against the slow implementation. Since this matter is quite + urgent and testing every edge-case is probably quite costly, we use this + method to test on large repositories as a fuzzing method of sorts. """ cmdutil.check_incompatible_arguments( opts, 'to_report', ['from_report', 'dry_run'] @@ -1498,6 +1509,7 @@ dry_run = opts.get('dry_run') to_report = opts.get('to_report') from_report = opts.get('from_report') + paranoid = opts.get('paranoid') # TODO maybe add filelog pattern and revision pattern parameters to help # narrow down the search for users that know what they're looking for? @@ -1506,7 +1518,12 @@ raise error.Abort(_(msg)) rewrite.repair_issue6528( - ui, repo, dry_run=dry_run, to_report=to_report, from_report=from_report + ui, + repo, + dry_run=dry_run, + to_report=to_report, + from_report=from_report, + paranoid=paranoid, ) diff --git a/mercurial/revlogutils/rewrite.py b/mercurial/revlogutils/rewrite.py --- a/mercurial/revlogutils/rewrite.py +++ b/mercurial/revlogutils/rewrite.py @@ -669,7 +669,9 @@ _reorder_filelog_parents(repo, fl, sorted(to_fix)) -def repair_issue6528(ui, repo, dry_run=False, to_report=None, from_report=None): +def repair_issue6528( + ui, repo, dry_run=False, to_report=None, from_report=None, paranoid=False +): from .. import store # avoid cycle @contextlib.contextmanager @@ -716,6 +718,12 @@ affected = _is_revision_affected_fast( repo, fl, filerev, filename, affected_chain ) + if paranoid: + slow = _is_revision_affected(repo.ui, fl, filerev) + if slow != affected: + msg = b"paranoid check failed for '%s' node %s" + node = binascii.hexlify(fl.node(filerev)) + raise error.ProgrammingError(msg % (filename, node)) if affected: msg = b"found affected revision %d for filelog '%s'\n" ui.warn(msg % (filerev, path)) diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -267,7 +267,7 @@ config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template continue: dry-run copy: forget, after, at-rev, force, include, exclude, dry-run - debug-repair-issue6528: to-report, from-report, dry-run + debug-repair-issue6528: to-report, from-report, paranoid, dry-run debugancestor: debugantivirusrunning: debugapplystreamclonebundle: