##// END OF EJS Templates
check-config: escape period in regexp for inline comments
timeless -
r27312:f925d492 default
parent child Browse files
Show More
@@ -1,98 +1,98 b''
1 1 #!/usr/bin/env python
2 2 #
3 3 # check-config - a config flag documentation checker for Mercurial
4 4 #
5 5 # Copyright 2015 Matt Mackall <mpm@selenic.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 import re
11 11 import sys
12 12
13 13 foundopts = {}
14 14 documented = {}
15 15
16 16 configre = (r"""ui\.config(|int|bool|list)\(['"](\S+)['"], ?"""
17 17 r"""['"](\S+)['"](,\s(?:default=)?(\S+?))?\)""")
18 18
19 19 def main(args):
20 20 for f in args:
21 21 sect = ''
22 22 prevname = ''
23 23 confsect = ''
24 24 for l in open(f):
25 25
26 26 # check topic-like bits
27 27 m = re.match('\s*``(\S+)``', l)
28 28 if m:
29 29 prevname = m.group(1)
30 30 if re.match('^\s*-+$', l):
31 31 sect = prevname
32 32 prevname = ''
33 33
34 34 if sect and prevname:
35 35 name = sect + '.' + prevname
36 36 documented[name] = 1
37 37
38 38 # check docstring bits
39 39 m = re.match(r'^\s+\[(\S+)\]', l)
40 40 if m:
41 41 confsect = m.group(1)
42 42 continue
43 43 m = re.match(r'^\s+(?:#\s*)?(\S+) = ', l)
44 44 if m:
45 45 name = confsect + '.' + m.group(1)
46 46 documented[name] = 1
47 47
48 48 # like the bugzilla extension
49 49 m = re.match(r'^\s*(\S+\.\S+)$', l)
50 50 if m:
51 51 documented[m.group(1)] = 1
52 52
53 53 # like convert
54 54 m = re.match(r'^\s*:(\S+\.\S+):\s+', l)
55 55 if m:
56 56 documented[m.group(1)] = 1
57 57
58 58 # quoted in help or docstrings
59 59 m = re.match(r'.*?``(\S+\.\S+)``', l)
60 60 if m:
61 61 documented[m.group(1)] = 1
62 62
63 63 # look for ignore markers
64 64 m = re.search(r'# (?:internal|experimental|deprecated|developer)'
65 ' config: (\S+.\S+)$', l)
65 ' config: (\S+\.\S+)$', l)
66 66 if m:
67 67 documented[m.group(1)] = 1
68 68
69 69 # look for code-like bits
70 70 m = re.search(configre, l)
71 71 if m:
72 72 ctype = m.group(1)
73 73 if not ctype:
74 74 ctype = 'str'
75 75 name = m.group(2) + "." + m.group(3)
76 76 default = m.group(5)
77 77 if default in (None, 'False', 'None', '0', '[]', '""', "''"):
78 78 default = ''
79 79 if re.match('[a-z.]+$', default):
80 80 default = '<variable>'
81 81 if name in foundopts and (ctype, default) != foundopts[name]:
82 82 print l
83 83 print "conflict on %s: %r != %r" % (name, (ctype, default),
84 84 foundopts[name])
85 85 foundopts[name] = (ctype, default)
86 86
87 87 for name in sorted(foundopts):
88 88 if name not in documented:
89 89 if not (name.startswith("devel.") or
90 90 name.startswith("experimental.") or
91 91 name.startswith("debug.")):
92 92 ctype, default = foundopts[name]
93 93 if default:
94 94 default = ' [%s]' % default
95 95 print "undocumented: %s (%s)%s" % (name, ctype, default)
96 96
97 97 if __name__ == "__main__":
98 98 sys.exit(main(sys.argv[1:]))
General Comments 0
You need to be logged in to leave comments. Login now