annotate contrib/check-config.py @ 35032:cd235d6f851b stable

dispatch: add option to not strip command args parsed by _earlygetopt() This allows us to parse the original args later by full-blown getopt() in order to verify the result of the faulty early parsing. Still we need the 'strip=True' behavior for shell aliases. Note that this series is RFC because it seems to change too much to be included in stable release.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 11 Nov 2017 16:46:41 +0900
parents e470f12d7d05
children 143d7b27b09c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 #!/usr/bin/env python
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # check-config - a config flag documentation checker for Mercurial
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
5 # Copyright 2015 Matt Mackall <mpm@selenic.com>
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
6 #
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7 # This software may be used and distributed according to the terms of the
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
8 # GNU General Public License version 2 or any later version.
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
9
28352
a92ee4d8a574 check-config: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 27992
diff changeset
10 from __future__ import absolute_import, print_function
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11 import re
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
12 import sys
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
13
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14 foundopts = {}
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
15 documented = {}
33195
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
16 allowinconsistent = set()
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
17
32847
e5a6a540ae63 check-config: use compiled regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28352
diff changeset
18 configre = re.compile(r'''
e5a6a540ae63 check-config: use compiled regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28352
diff changeset
19 # Function call
32848
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
20 ui\.config(?P<ctype>|int|bool|list)\(
32847
e5a6a540ae63 check-config: use compiled regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28352
diff changeset
21 # First argument.
32848
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
22 ['"](?P<section>\S+)['"],\s*
32847
e5a6a540ae63 check-config: use compiled regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28352
diff changeset
23 # Second argument
32848
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
24 ['"](?P<option>\S+)['"](,\s+
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
25 (?:default=)?(?P<default>\S+?))?
32847
e5a6a540ae63 check-config: use compiled regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28352
diff changeset
26 \)''', re.VERBOSE | re.MULTILINE)
e5a6a540ae63 check-config: use compiled regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 28352
diff changeset
27
32849
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
28 configwithre = re.compile('''
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
29 ui\.config(?P<ctype>with)\(
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
30 # First argument is callback function. This doesn't parse robustly
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
31 # if it is e.g. a function call.
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
32 [^,]+,\s*
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
33 ['"](?P<section>\S+)['"],\s*
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
34 ['"](?P<option>\S+)['"](,\s+
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
35 (?:default=)?(?P<default>\S+?))?
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
36 \)''', re.VERBOSE | re.MULTILINE)
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
37
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
38 configpartialre = (r"""ui\.config""")
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
39
33195
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
40 ignorere = re.compile(r'''
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
41 \#\s(?P<reason>internal|experimental|deprecated|developer|inconsistent)\s
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
42 config:\s(?P<config>\S+\.\S+)$
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
43 ''', re.VERBOSE | re.MULTILINE)
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
44
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
45 def main(args):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
46 for f in args:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
47 sect = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
48 prevname = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
49 confsect = ''
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
50 carryover = ''
33570
e470f12d7d05 check-config: mention the file and line of the error
Ryan McElroy <rmcelroy@fb.com>
parents: 33195
diff changeset
51 linenum = 0
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
52 for l in open(f):
33570
e470f12d7d05 check-config: mention the file and line of the error
Ryan McElroy <rmcelroy@fb.com>
parents: 33195
diff changeset
53 linenum += 1
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
54
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
55 # check topic-like bits
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
56 m = re.match('\s*``(\S+)``', l)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
57 if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
58 prevname = m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
59 if re.match('^\s*-+$', l):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
60 sect = prevname
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
61 prevname = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
62
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
63 if sect and prevname:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
64 name = sect + '.' + prevname
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
65 documented[name] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
66
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
67 # check docstring bits
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
68 m = re.match(r'^\s+\[(\S+)\]', l)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
69 if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
70 confsect = m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
71 continue
27311
24a1c24fad6e check-config: allow numbers in configs
timeless <timeless@mozdev.org>
parents: 27310
diff changeset
72 m = re.match(r'^\s+(?:#\s*)?(\S+) = ', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
73 if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
74 name = confsect + '.' + m.group(1)
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
75 documented[name] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
76
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
77 # like the bugzilla extension
27311
24a1c24fad6e check-config: allow numbers in configs
timeless <timeless@mozdev.org>
parents: 27310
diff changeset
78 m = re.match(r'^\s*(\S+\.\S+)$', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
79 if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
80 documented[m.group(1)] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
81
27310
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
82 # like convert
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
83 m = re.match(r'^\s*:(\S+\.\S+):\s+', l)
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
84 if m:
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
85 documented[m.group(1)] = 1
9c98fe1416c2 check-config: recognize convert style documentation
timeless <timeless@mozdev.org>
parents: 25849
diff changeset
86
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
87 # quoted in help or docstrings
27311
24a1c24fad6e check-config: allow numbers in configs
timeless <timeless@mozdev.org>
parents: 27310
diff changeset
88 m = re.match(r'.*?``(\S+\.\S+)``', l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
89 if m:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
90 documented[m.group(1)] = 1
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
91
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
92 # look for ignore markers
33195
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
93 m = ignorere.search(l)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94 if m:
33195
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
95 if m.group('reason') == 'inconsistent':
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
96 allowinconsistent.add(m.group('config'))
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
97 else:
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
98 documented[m.group('config')] = 1
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
99
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
100 # look for code-like bits
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
101 line = carryover + l
32849
e9fc5550be46 check-config: look for ui.configwith
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32848
diff changeset
102 m = configre.search(line) or configwithre.search(line)
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
103 if m:
32848
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
104 ctype = m.group('ctype')
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
105 if not ctype:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
106 ctype = 'str'
32848
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
107 name = m.group('section') + "." + m.group('option')
485b8e87e244 check-config: use named groups in regexp
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32847
diff changeset
108 default = m.group('default')
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
109 if default in (None, 'False', 'None', '0', '[]', '""', "''"):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
110 default = ''
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
111 if re.match('[a-z.]+$', default):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
112 default = '<variable>'
33195
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
113 if (name in foundopts and (ctype, default) != foundopts[name]
5d8942dbe49e check-config: syntax to allow inconsistent config values
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32849
diff changeset
114 and name not in allowinconsistent):
33570
e470f12d7d05 check-config: mention the file and line of the error
Ryan McElroy <rmcelroy@fb.com>
parents: 33195
diff changeset
115 print(l.rstrip())
28352
a92ee4d8a574 check-config: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 27992
diff changeset
116 print("conflict on %s: %r != %r" % (name, (ctype, default),
a92ee4d8a574 check-config: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 27992
diff changeset
117 foundopts[name]))
33570
e470f12d7d05 check-config: mention the file and line of the error
Ryan McElroy <rmcelroy@fb.com>
parents: 33195
diff changeset
118 print("at %s:%d:" % (f, linenum))
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
119 foundopts[name] = (ctype, default)
27313
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
120 carryover = ''
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
121 else:
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
122 m = re.search(configpartialre, line)
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
123 if m:
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
124 carryover = line
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
125 else:
9d155accd8f1 check-config: handle multiline config
timeless <timeless@mozdev.org>
parents: 27312
diff changeset
126 carryover = ''
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
127
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
128 for name in sorted(foundopts):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
129 if name not in documented:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
130 if not (name.startswith("devel.") or
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
131 name.startswith("experimental.") or
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
132 name.startswith("debug.")):
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
133 ctype, default = foundopts[name]
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
134 if default:
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
135 default = ' [%s]' % default
28352
a92ee4d8a574 check-config: use absolute_import and print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 27992
diff changeset
136 print("undocumented: %s (%s)%s" % (name, ctype, default))
25790
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
137
db5b6a1c064d check-config: add config option checker
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
138 if __name__ == "__main__":
27992
8f244b75cc5e tests: execute check-config.py without xargs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27313
diff changeset
139 if len(sys.argv) > 1:
8f244b75cc5e tests: execute check-config.py without xargs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27313
diff changeset
140 sys.exit(main(sys.argv[1:]))
8f244b75cc5e tests: execute check-config.py without xargs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27313
diff changeset
141 else:
8f244b75cc5e tests: execute check-config.py without xargs
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 27313
diff changeset
142 sys.exit(main([l.rstrip() for l in sys.stdin]))