Show More
@@ -0,0 +1,57 b'' | |||||
|
1 | # dirstatenonnormalcheck.py - extension to check the consistency of the | |||
|
2 | # dirstate's non-normal map | |||
|
3 | # | |||
|
4 | # For most operations on dirstate, this extensions checks that the nonnormalset | |||
|
5 | # contains the right entries. | |||
|
6 | # It compares the nonnormal file to a nonnormalset built from the map of all | |||
|
7 | # the files in the dirstate to check that they contain the same files. | |||
|
8 | ||||
|
9 | from __future__ import absolute_import | |||
|
10 | ||||
|
11 | from mercurial import ( | |||
|
12 | dirstate, | |||
|
13 | extensions, | |||
|
14 | ) | |||
|
15 | ||||
|
16 | def nonnormalentries(dmap): | |||
|
17 | """Compute nonnormal entries from dirstate's dmap""" | |||
|
18 | res = set() | |||
|
19 | for f, e in dmap.iteritems(): | |||
|
20 | if e[0] != 'n' or e[3] == -1: | |||
|
21 | res.add(f) | |||
|
22 | return res | |||
|
23 | ||||
|
24 | def checkconsistency(ui, orig, dmap, _nonnormalset, label): | |||
|
25 | """Compute nonnormalset from dmap, check that it matches _nonnormalset""" | |||
|
26 | nonnormalcomputedmap = nonnormalentries(dmap) | |||
|
27 | if _nonnormalset != nonnormalcomputedmap: | |||
|
28 | ui.develwarn("%s call to %s\n" % (label, orig)) | |||
|
29 | ui.develwarn("inconsistency in nonnormalset\n") | |||
|
30 | ui.develwarn("[nonnormalset] %s\n" % _nonnormalset) | |||
|
31 | ui.develwarn("[map] %s\n" % nonnormalcomputedmap) | |||
|
32 | ||||
|
33 | def _checkdirstate(orig, self, arg): | |||
|
34 | """Check nonnormal set consistency before and after the call to orig""" | |||
|
35 | checkconsistency(self._ui, orig, self._map, self._nonnormalset, "before") | |||
|
36 | r = orig(self, arg) | |||
|
37 | checkconsistency(self._ui, orig, self._map, self._nonnormalset, "after") | |||
|
38 | return r | |||
|
39 | ||||
|
40 | def extsetup(ui): | |||
|
41 | """Wrap functions modifying dirstate to check nonnormalset consistency""" | |||
|
42 | dirstatecl = dirstate.dirstate | |||
|
43 | devel = ui.configbool('devel', 'all-warnings') | |||
|
44 | paranoid = ui.configbool('experimental', 'nonnormalparanoidcheck') | |||
|
45 | if devel: | |||
|
46 | extensions.wrapfunction(dirstatecl, '_writedirstate', _checkdirstate) | |||
|
47 | if paranoid: | |||
|
48 | # We don't do all these checks when paranoid is disable as it would | |||
|
49 | # make the extension run very slowly on large repos | |||
|
50 | extensions.wrapfunction(dirstatecl, 'normallookup', _checkdirstate) | |||
|
51 | extensions.wrapfunction(dirstatecl, 'otherparent', _checkdirstate) | |||
|
52 | extensions.wrapfunction(dirstatecl, 'normal', _checkdirstate) | |||
|
53 | extensions.wrapfunction(dirstatecl, 'write', _checkdirstate) | |||
|
54 | extensions.wrapfunction(dirstatecl, 'add', _checkdirstate) | |||
|
55 | extensions.wrapfunction(dirstatecl, 'remove', _checkdirstate) | |||
|
56 | extensions.wrapfunction(dirstatecl, 'merge', _checkdirstate) | |||
|
57 | extensions.wrapfunction(dirstatecl, 'drop', _checkdirstate) |
@@ -0,0 +1,22 b'' | |||||
|
1 | $ cat >> $HGRCPATH << EOF | |||
|
2 | > [ui] | |||
|
3 | > logtemplate="{rev}:{node|short} ({phase}) [{tags} {bookmarks}] {desc|firstline}\n" | |||
|
4 | > [extensions] | |||
|
5 | > dirstateparanoidcheck = $TESTDIR/../contrib/dirstatenonnormalcheck.py | |||
|
6 | > [experimental] | |||
|
7 | > nonnormalparanoidcheck = True | |||
|
8 | > [devel] | |||
|
9 | > all-warnings=True | |||
|
10 | > EOF | |||
|
11 | $ mkcommit() { | |||
|
12 | > echo "$1" > "$1" | |||
|
13 | > hg add "$1" | |||
|
14 | > hg ci -m "add $1" | |||
|
15 | > } | |||
|
16 | ||||
|
17 | $ hg init testrepo | |||
|
18 | $ cd testrepo | |||
|
19 | $ mkcommit a | |||
|
20 | $ mkcommit b | |||
|
21 | $ mkcommit c | |||
|
22 | $ hg status |
General Comments 0
You need to be logged in to leave comments.
Login now