diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -2087,6 +2087,12 @@ _(b'write a (binary) serialised (new) nodemap on stdin'), ), ('', b'dump-disk', False, _(b'dump on-disk data on stdin')), + ( + '', + b'check', + False, + _(b'check that the data on disk data are correct.'), + ), ], ) def debugnodemap(ui, repo, **args): @@ -2102,6 +2108,11 @@ cl = unfi.changelog data = nodemap.persisted_data(cl) ui.write(data) + elif args['check']: + unfi = repo.unfiltered() + cl = unfi.changelog + data = nodemap.persisted_data(cl) + return nodemap.check_data(ui, cl.index, data) @command( diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py --- a/mercurial/revlogutils/nodemap.py +++ b/mercurial/revlogutils/nodemap.py @@ -340,3 +340,37 @@ else: block[idx] = _transform_rev(v) return block + + +# debug utility + + +def check_data(ui, index, data): + """verify that the provided nodemap data are valid for the given idex""" + ret = 0 + ui.status((b"revision in index: %d\n") % len(index)) + root = parse_data(data) + all_revs = set(_all_revisions(root)) + ui.status((b"revision in nodemap: %d\n") % len(all_revs)) + for r in range(len(index)): + if r not in all_revs: + msg = b" revision missing from nodemap: %d\n" % r + ui.write_err(msg) + ret = 1 + else: + all_revs.remove(r) + if all_revs: + for r in sorted(all_revs): + msg = b" extra revision in nodemap: %d\n" % r + ui.write_err(msg) + ret = 1 + return ret + + +def _all_revisions(root): + """return all revisions stored in a Trie""" + for block in _walk_trie(root): + for v in block: + if v is None or isinstance(v, Block): + continue + yield v diff --git a/tests/test-completion.t b/tests/test-completion.t --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -290,7 +290,7 @@ debugmanifestfulltextcache: clear, add debugmergestate: debugnamecomplete: - debugnodemap: dump-new, dump-disk + debugnodemap: dump-new, dump-disk, check debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template debugp1copies: rev debugp2copies: rev diff --git a/tests/test-persistent-nodemap.t b/tests/test-persistent-nodemap.t --- a/tests/test-persistent-nodemap.t +++ b/tests/test-persistent-nodemap.t @@ -36,6 +36,9 @@ 00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 00f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + $ hg debugnodemap --check + revision in index: 5001 + revision in nodemap: 5001 add a new commit @@ -48,3 +51,6 @@ .hg/store/00changelog.n: size=18 $ f --sha256 .hg/store/00changelog-*.nd --size .hg/store/00changelog-????????????????.nd: size=245760, sha256=e6ee5d59afaab2cb1afae1077715be280578d29df508bd3dd9d74a994bc555e7 (glob) + $ hg debugnodemap --check + revision in index: 5002 + revision in nodemap: 5002