Mercurial > hg
annotate contrib/check-code.py @ 15183:59e8bc22506e
rollback: avoid unsafe rollback when not at tip (issue2998)
You can get into trouble if you commit, update back to an older
changeset, and then rollback. The update removes your valuable changes
from the working dir, then rollback removes them history. Oops: you've
just irretrievably lost data running nothing but core Mercurial
commands. (More subtly: rollback from a shared clone that was already
at an older changeset -- no update required, just rollback from the
wrong directory.)
The fix assumes that only "commit" transactions have irreplaceable
data, and allows rolling back non-commit transactions as always. But
when rolling back a commit, check that the working dir is checked out
to tip, i.e. the changeset we're about to destroy. If not, abort. You
can get back the old (dangerous) behaviour with --force.
author | Greg Ward <greg@gerg.ca> |
---|---|
date | Fri, 30 Sep 2011 21:58:54 -0400 |
parents | 5a0fdc715769 |
children | aeeb2afcdc25 d4addef0ec74 |
rev | line source |
---|---|
10281 | 1 #!/usr/bin/env python |
2 # | |
3 # check-code - a style and portability checker for Mercurial | |
4 # | |
10290
7cc60de189d7
check-code: fix copyright date
Matt Mackall <mpm@selenic.com>
parents:
10287
diff
changeset
|
5 # Copyright 2010 Matt Mackall <mpm@selenic.com> |
10281 | 6 # |
7 # This software may be used and distributed according to the terms of the | |
8 # GNU General Public License version 2 or any later version. | |
9 | |
11816
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
10 import re, glob, os, sys |
13074
637627f31c74
check-code: check for gratuitous whitespace after Python keywords
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13031
diff
changeset
|
11 import keyword |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
12 import optparse |
10281 | 13 |
14 def repquote(m): | |
10722
c4fb2103e734
check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10720
diff
changeset
|
15 t = re.sub(r"\w", "x", m.group('text')) |
10451
63a9bfad50ff
check-code: two more rules
Matt Mackall <mpm@selenic.com>
parents:
10412
diff
changeset
|
16 t = re.sub(r"[^\sx]", "o", t) |
10722
c4fb2103e734
check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10720
diff
changeset
|
17 return m.group('quote') + t + m.group('quote') |
10281 | 18 |
10727
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
19 def reppython(m): |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
20 comment = m.group('comment') |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
21 if comment: |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
22 return "#" * len(comment) |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
23 return repquote(m) |
10281 | 24 |
25 def repcomment(m): | |
26 return m.group(1) + "#" * len(m.group(2)) | |
27 | |
28 def repccomment(m): | |
29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2)) | |
30 return m.group(1) + t + "*/" | |
31 | |
32 def repcallspaces(m): | |
33 t = re.sub(r"\n\s+", "\n", m.group(2)) | |
34 return m.group(1) + t | |
35 | |
36 def repinclude(m): | |
37 return m.group(1) + "<foo>" | |
38 | |
39 def rephere(m): | |
40 t = re.sub(r"\S", "x", m.group(2)) | |
41 return m.group(1) + t | |
42 | |
43 | |
44 testpats = [ | |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
45 [ |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
46 (r'(pushd|popd)', "don't use 'pushd' or 'popd', use 'cd'"), |
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
47 (r'\W\$?\(\([^\)]*\)\)', "don't use (()) or $(()), use 'expr'"), |
10281 | 48 (r'^function', "don't use 'function', use old style"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), |
10373
e4c7972002e4
check-code.py: escape backslash
Mads Kiilerich <mads@kiilerich.com>
parents:
10291
diff
changeset
|
50 (r'echo.*\\n', "don't use 'echo \\n', use printf"), |
11884
932448701e7d
check-code: catch "echo -n" in tests
Martin Geisler <mg@lazybytes.net>
parents:
11599
diff
changeset
|
51 (r'echo -n', "don't use 'echo -n', use printf"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
52 (r'^diff.*-\w*N', "don't use 'diff -N'"), |
10281 | 53 (r'(^| )wc[^|]*$', "filter wc output"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
54 (r'head -c', "don't use 'head -c', use 'dd'"), |
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
55 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"), |
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
56 (r'printf.*\\\d\d\d', "don't use 'printf \NNN', use Python"), |
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
57 (r'printf.*\\x', "don't use printf \\x, use Python"), |
10281 | 58 (r'\$\(.*\)', "don't use $(expr), use `expr`"), |
59 (r'rm -rf \*', "don't use naked rm -rf, target a directory"), | |
60 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', | |
61 "use egrep for extended grep syntax"), | |
62 (r'/bin/', "don't use explicit paths for tools"), | |
63 (r'\$PWD', "don't use $PWD, use `pwd`"), | |
64 (r'[^\n]\Z', "no trailing newline"), | |
10658
95c7c4b7e67a
test-merge-default and check-code.py: No "export x=x" in sh
Mads Kiilerich <mads@kiilerich.com>
parents:
10451
diff
changeset
|
65 (r'export.*=', "don't export and assign at once"), |
10802
6e4cf8319f54
check-code.py: Check for bare ^
Mads Kiilerich <mads@kiilerich.com>
parents:
10658
diff
changeset
|
66 ('^([^"\']|("[^"]*")|(\'[^\']*\'))*\\^', "^ must be quoted"), |
11210
0c0088881562
check-code: add check for 'source'
Yuya Nishihara <yuya@tcha.org>
parents:
10905
diff
changeset
|
67 (r'^source\b', "don't use 'source', use '.'"), |
12367
3acd5f7ab9d0
tests: compatibility fix.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
12366
diff
changeset
|
68 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), |
13301
4b07578967e6
check-code: do not complain about 'ls x | foo -v'
Martin Geisler <mg@aragost.com>
parents:
13161
diff
changeset
|
69 (r'ls\s+[^|-]+\s+-', "options to 'ls' must come before filenames"), |
13524
121c89dd7983
check-code: catch "echo > $HGRCPATH" too
Martin Geisler <mg@aragost.com>
parents:
13522
diff
changeset
|
70 (r'[^>]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), |
14831
0407b7613e99
treediscovery: rename stop() in tests to fix failures on AIX.
Jim Hague <jim.hague@acm.org>
parents:
14763
diff
changeset
|
71 (r'stop\(\)', "don't use 'stop' as a shell function name"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
72 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
73 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
74 [] |
10281 | 75 ] |
76 | |
77 testfilters = [ | |
78 (r"( *)(#([^\n]*\S)?)", repcomment), | |
79 (r"<<(\S+)((.|\n)*?\n\1)", rephere), | |
80 ] | |
81 | |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
82 uprefix = r"^ \$ " |
12743
4c4aeaab2339
check-code: add 'no tab indent' check for unified tests
Adrian Buehlmann <adrian@cadifra.com>
parents:
12367
diff
changeset
|
83 uprefixc = r"^ > " |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
84 utestpats = [ |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
85 [ |
12785
c7d23b4ca4ba
check-code: warning and fixes for whitespace in unified tests
Matt Mackall <mpm@selenic.com>
parents:
12770
diff
changeset
|
86 (r'^(\S| $ ).*(\S\s+|^\s+)\n', "trailing whitespace on non-output"), |
12366
c01dc9087d9a
tests: drop a bunch of sed calls from unified tests
Matt Mackall <mpm@selenic.com>
parents:
12364
diff
changeset
|
87 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"), |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
88 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
89 (uprefix + r'.*\$\?', "explicit exit code checks unnecessary"), |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
90 (uprefix + r'.*\|\| echo.*(fail|error)', |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
91 "explicit exit code checks unnecessary"), |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
92 (uprefix + r'set -e', "don't use set -e"), |
12743
4c4aeaab2339
check-code: add 'no tab indent' check for unified tests
Adrian Buehlmann <adrian@cadifra.com>
parents:
12367
diff
changeset
|
93 (uprefixc + r'( *)\t', "don't use tabs to indent"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
94 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
95 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
96 [] |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
97 ] |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
98 |
14203
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
99 for i in [0, 1]: |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
100 for p, m in testpats[i]: |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
101 if p.startswith('^'): |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
102 p = uprefix + p[1:] |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
103 else: |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
104 p = uprefix + p |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
105 utestpats[i].append((p, m)) |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
106 |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
107 utestfilters = [ |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
108 (r"( *)(#([^\n]*\S)?)", repcomment), |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
109 ] |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
110 |
10281 | 111 pypats = [ |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
112 [ |
11568
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
113 (r'^\s*def\s*\w+\s*\(.*,\s*\(', |
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
114 "tuple parameter unpacking not available in Python 3+"), |
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
115 (r'lambda\s*\(.*,.*\)', |
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
116 "tuple parameter unpacking not available in Python 3+"), |
11764
16723af520b0
check-code: added a check for calls to the builtin cmp function
Renato Cunha <renatoc@gmail.com>
parents:
11672
diff
changeset
|
117 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), |
11569
f8576644a222
check-code: added check for reduce usage
Renato Cunha <renatoc@gmail.com>
parents:
11568
diff
changeset
|
118 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"), |
11602
ba2520dd1e29
check-code: catch dict.has_key
Martin Geisler <mg@lazybytes.net>
parents:
11601
diff
changeset
|
119 (r'\.has_key\b', "dict.has_key is not available in Python 3+"), |
10281 | 120 (r'^\s*\t', "don't use tabs"), |
10412
5326800d6937
check-code: import some pylint checks
Matt Mackall <mpm@selenic.com>
parents:
10374
diff
changeset
|
121 (r'\S;\s*\n', "semicolon"), |
10281 | 122 (r'\w,\w', "missing whitespace after ,"), |
123 (r'\w[+/*\-<>]\w', "missing whitespace in expression"), | |
124 (r'^\s+\w+=\w+[^,)]$', "missing whitespace in assignment"), | |
125 (r'.{85}', "line too long"), | |
126 (r'[^\n]\Z', "no trailing newline"), | |
12770
614f0d8724ab
check-code: find trailing whitespace
Martin Geisler <mg@lazybytes.net>
parents:
12743
diff
changeset
|
127 (r'(\S\s+|^\s+)\n', "trailing whitespace"), |
10281 | 128 # (r'^\s+[^_ ][^_. ]+_[^_]+\s*=', "don't use underbars in identifiers"), |
129 # (r'\w*[a-z][A-Z]\w*\s*=', "don't use camelcase in identifiers"), | |
10286 | 130 (r'^\s*(if|while|def|class|except|try)\s[^[]*:\s*[^\]#\s]+', |
131 "linebreak after :"), | |
14763
b071cd58af50
check-code: fix class style checking (with tests)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
14709
diff
changeset
|
132 (r'class\s[^( ]+:', "old-style class, use class foo(object)"), |
b071cd58af50
check-code: fix class style checking (with tests)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
14709
diff
changeset
|
133 (r'class\s[^( ]+\(\):', |
b071cd58af50
check-code: fix class style checking (with tests)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
14709
diff
changeset
|
134 "class foo() not available in Python 2.4, use class foo(object)"), |
13076
a861c7155f09
check-code: single check for Python keywords used as a function
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13074
diff
changeset
|
135 (r'\b(%s)\(' % '|'.join(keyword.kwlist), |
a861c7155f09
check-code: single check for Python keywords used as a function
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13074
diff
changeset
|
136 "Python keyword is not a function"), |
10412
5326800d6937
check-code: import some pylint checks
Matt Mackall <mpm@selenic.com>
parents:
10374
diff
changeset
|
137 (r',]', "unneeded trailing ',' in list"), |
10281 | 138 # (r'class\s[A-Z][^\(]*\((?!Exception)', |
139 # "don't capitalize non-exception classes"), | |
140 # (r'in range\(', "use xrange"), | |
141 # (r'^\s*print\s+', "avoid using print in core and extensions"), | |
142 (r'[\x80-\xff]', "non-ASCII character literal"), | |
143 (r'("\')\.format\(', "str.format() not available in Python 2.4"), | |
144 (r'^\s*with\s+', "with not available in Python 2.4"), | |
14267
6332c02b3d68
check-code: complain about set.isdisjoint
Matt Mackall <mpm@selenic.com>
parents:
14203
diff
changeset
|
145 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"), |
13160
07d08c130892
check-code: catch "except as"
Matt Mackall <mpm@selenic.com>
parents:
13076
diff
changeset
|
146 (r'^\s*except.* as .*:', "except as not available in Python 2.4"), |
13161
11eb53464e68
check-code: catch os.path.relpath
Matt Mackall <mpm@selenic.com>
parents:
13160
diff
changeset
|
147 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"), |
11345
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
148 (r'(?<!def)\s+(any|all|format)\(', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
149 "any/all/format not available in Python 2.4"), |
11522
eaa7666ad53f
check-code: add test for callable
Martin Geisler <mg@aragost.com>
parents:
11345
diff
changeset
|
150 (r'(?<!def)\s+(callable)\(', |
14978
5a0fdc715769
check-code: disallow use of hasattr()
Augie Fackler <durin42@gmail.com>
parents:
14831
diff
changeset
|
151 "callable not available in Python 3, use getattr(f, '__call__', None)"), |
10281 | 152 (r'if\s.*\selse', "if ... else form not available in Python 2.4"), |
13074
637627f31c74
check-code: check for gratuitous whitespace after Python keywords
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13031
diff
changeset
|
153 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), |
637627f31c74
check-code: check for gratuitous whitespace after Python keywords
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13031
diff
changeset
|
154 "gratuitous whitespace after Python keyword"), |
10281 | 155 (r'([\(\[]\s\S)|(\S\s[\)\]])', "gratuitous whitespace in () or []"), |
156 # (r'\s\s=', "gratuitous whitespace before ="), | |
11345
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
157 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
158 "missing whitespace around operator"), |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
159 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
160 "missing whitespace around operator"), |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
161 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
162 "missing whitespace around operator"), |
14303
e2be0bba0d83
check-code: add /= to operator list
Sune Foldager <cryo@cyanite.org>
parents:
14267
diff
changeset
|
163 (r'[^+=*/!<>&| -](\s=|=\s)[^= ]', |
11345
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
164 "wrong whitespace around ="), |
10451
63a9bfad50ff
check-code: two more rules
Matt Mackall <mpm@selenic.com>
parents:
10412
diff
changeset
|
165 (r'raise Exception', "don't raise generic exceptions"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
166 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
167 (r' [=!]=\s+(True|False|None)', |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
168 "comparison with singleton, use 'is' or 'is not' instead"), |
14494
1ffeeb91c55d
check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents:
14303
diff
changeset
|
169 (r'^\s*(while|if) [01]:', |
1ffeeb91c55d
check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents:
14303
diff
changeset
|
170 "use True/False for constant Boolean expression"), |
14978
5a0fdc715769
check-code: disallow use of hasattr()
Augie Fackler <durin42@gmail.com>
parents:
14831
diff
changeset
|
171 (r'(?<!def)\s+hasattr', |
5a0fdc715769
check-code: disallow use of hasattr()
Augie Fackler <durin42@gmail.com>
parents:
14831
diff
changeset
|
172 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'), |
14169
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
173 (r'opener\([^)]*\).read\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
174 "use opener.read() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
175 (r'opener\([^)]*\).write\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
176 "use opener.write() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
177 (r'[\s\(](open|file)\([^)]*\)\.read\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
178 "use util.readfile() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
179 (r'[\s\(](open|file)\([^)]*\)\.write\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
180 "use util.readfile() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
181 (r'^[\s\(]*(open(er)?|file)\([^)]*\)', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
182 "always assign an opened file to a variable, and close it afterwards"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
183 (r'[\s\(](open|file)\([^)]*\)\.', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
184 "always assign an opened file to a variable, and close it afterwards"), |
14549
48ec0763afbb
check-code: catch misspellings of descendant
Matt Mackall <mpm@selenic.com>
parents:
14494
diff
changeset
|
185 (r'(?i)descendent', "the proper spelling is descendAnt"), |
14709
6c7283faa967
check-code: don't mark debug messages for translation
Matt Mackall <mpm@selenic.com>
parents:
14549
diff
changeset
|
186 (r'\.debug\(\_', "don't mark debug messages for translation"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
187 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
188 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
189 [ |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
190 (r'.{81}', "warning: line over 80 characters"), |
14005
bb391e0515ba
check-code: warn about naked except clauses
Idan Kamara <idankk86@gmail.com>
parents:
13748
diff
changeset
|
191 (r'^\s*except:$', "warning: naked except clause"), |
11599
6fcc066c0c2c
check-code: warn about untranslated ui.warn calls
Martin Geisler <mg@lazybytes.net>
parents:
11522
diff
changeset
|
192 (r'ui\.(status|progress|write|note|warn)\([\'\"]x', |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
193 "warning: unwrapped ui message"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
194 ] |
10281 | 195 ] |
196 | |
197 pyfilters = [ | |
10727
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
198 (r"""(?msx)(?P<comment>\#.*?$)| |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
199 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
200 (?P<text>(([^\\]|\\.)*?)) |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
201 (?P=quote))""", reppython), |
10281 | 202 ] |
203 | |
204 cpats = [ | |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
205 [ |
10281 | 206 (r'//', "don't use //-style comments"), |
207 (r'^ ', "don't use spaces to indent"), | |
208 (r'\S\t', "don't use tabs except for indent"), | |
209 (r'(\S\s+|^\s+)\n', "trailing whitespace"), | |
210 (r'.{85}', "line too long"), | |
211 (r'(while|if|do|for)\(', "use space after while/if/do/for"), | |
212 (r'return\(', "return is not a function"), | |
213 (r' ;', "no space before ;"), | |
214 (r'\w+\* \w+', "use int *foo, not int* foo"), | |
215 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"), | |
216 (r'\S+ (\+\+|--)', "use foo++, not foo ++"), | |
217 (r'\w,\w', "missing whitespace after ,"), | |
13736
f3c4421e121c
osutil: fix up check-code issues
Matt Mackall <mpm@selenic.com>
parents:
13524
diff
changeset
|
218 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), |
10281 | 219 (r'^#\s+\w', "use #foo, not # foo"), |
220 (r'[^\n]\Z', "no trailing newline"), | |
13748
26f8844d1757
osutil: replace #import with #include, and add a check for it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13736
diff
changeset
|
221 (r'^\s*#import\b', "use only #include in standard C code"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
222 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
223 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
224 [] |
10281 | 225 ] |
226 | |
227 cfilters = [ | |
228 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), | |
10722
c4fb2103e734
check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10720
diff
changeset
|
229 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), |
10281 | 230 (r'''(#\s*include\s+<)([^>]+)>''', repinclude), |
231 (r'(\()([^)]+\))', repcallspaces), | |
232 ] | |
233 | |
14137
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
234 inutilpats = [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
235 [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
236 (r'\bui\.', "don't use ui in util"), |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
237 ], |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
238 # warnings |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
239 [] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
240 ] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
241 |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
242 inrevlogpats = [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
243 [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
244 (r'\brepo\.', "don't use repo in revlog"), |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
245 ], |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
246 # warnings |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
247 [] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
248 ] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
249 |
10281 | 250 checks = [ |
251 ('python', r'.*\.(py|cgi)$', pyfilters, pypats), | |
252 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats), | |
253 ('c', r'.*\.c$', cfilters, cpats), | |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
254 ('unified test', r'.*\.t$', utestfilters, utestpats), |
14137
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
255 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters, |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
256 inrevlogpats), |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
257 ('layering violation ui in util', r'mercurial/util\.py', pyfilters, |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
258 inutilpats), |
10281 | 259 ] |
260 | |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
261 class norepeatlogger(object): |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
262 def __init__(self): |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
263 self._lastseen = None |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
264 |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
265 def log(self, fname, lineno, line, msg, blame): |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
266 """print error related a to given line of a given file. |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
267 |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
268 The faulty line will also be printed but only once in the case |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
269 of multiple errors. |
10281 | 270 |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
271 :fname: filename |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
272 :lineno: line number |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
273 :line: actual content of the line |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
274 :msg: error message |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
275 """ |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
276 msgid = fname, lineno, line |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
277 if msgid != self._lastseen: |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
278 if blame: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
279 print "%s:%d (%s):" % (fname, lineno, blame) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
280 else: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
281 print "%s:%d:" % (fname, lineno) |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
282 print " > %s" % line |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
283 self._lastseen = msgid |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
284 print " " + msg |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
285 |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
286 _defaultlogger = norepeatlogger() |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
287 |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
288 def getblame(f): |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
289 lines = [] |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
290 for l in os.popen('hg annotate -un %s' % f): |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
291 start, line = l.split(':', 1) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
292 user, rev = start.split() |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
293 lines.append((line[1:-1], user, rev)) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
294 return lines |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
295 |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
296 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False, |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
297 blame=False, debug=False): |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
298 """checks style and portability of a given file |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
299 |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
300 :f: filepath |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
301 :logfunc: function used to report error |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
302 logfunc(filename, linenumber, linecontent, errormessage) |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
303 :maxerr: number of error to display before arborting. |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
304 Set to None (default) to report all errors |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
305 |
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
306 return True if no error is found, False otherwise. |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
307 """ |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
308 blamecache = None |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
309 result = True |
10281 | 310 for name, match, filters, pats in checks: |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
311 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
312 print name, f |
10281 | 313 fc = 0 |
314 if not re.match(match, f): | |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
315 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
316 print "Skipping %s for %s it doesn't match %s" % ( |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
317 name, match, f) |
10281 | 318 continue |
13400
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13301
diff
changeset
|
319 fp = open(f) |
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13301
diff
changeset
|
320 pre = post = fp.read() |
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13301
diff
changeset
|
321 fp.close() |
10287
5da892be3497
check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents:
10286
diff
changeset
|
322 if "no-" + "check-code" in pre: |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
323 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
324 print "Skipping %s for %s it has no- and check-code" % ( |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
325 name, f) |
10287
5da892be3497
check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents:
10286
diff
changeset
|
326 break |
10281 | 327 for p, r in filters: |
328 post = re.sub(p, r, post) | |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
329 if warnings: |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
330 pats = pats[0] + pats[1] |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
331 else: |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
332 pats = pats[0] |
10281 | 333 # print post # uncomment to show filtered version |
334 z = enumerate(zip(pre.splitlines(), post.splitlines(True))) | |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
335 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
336 print "Checking %s for %s" % (name, f) |
10281 | 337 for n, l in z: |
10287
5da892be3497
check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents:
10286
diff
changeset
|
338 if "check-code" + "-ignore" in l[0]: |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
339 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
340 print "Skipping %s for %s:%s (check-code -ignore)" % ( |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
341 name, f, n) |
10287
5da892be3497
check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents:
10286
diff
changeset
|
342 continue |
10281 | 343 for p, msg in pats: |
344 if re.search(p, l[1]): | |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
345 bd = "" |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
346 if blame: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
347 bd = 'working directory' |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
348 if not blamecache: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
349 blamecache = getblame(f) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
350 if n < len(blamecache): |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
351 bl, bu, br = blamecache[n] |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
352 if bl == l[0]: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
353 bd = '%s@%s' % (bu, br) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
354 logfunc(f, n + 1, l[0], msg, bd) |
10281 | 355 fc += 1 |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
356 result = False |
10718
f18c37fd624f
check-code: Add a ``maxerr`` argument to the ``checkfile`` function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10717
diff
changeset
|
357 if maxerr is not None and fc >= maxerr: |
10281 | 358 print " (too many errors, giving up)" |
359 break | |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
360 return result |
10717
b1f4fcef99b3
check-code: Add a ``checkfile`` function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10716
diff
changeset
|
361 |
10716
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
362 if __name__ == "__main__": |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
363 parser = optparse.OptionParser("%prog [options] [files]") |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
364 parser.add_option("-w", "--warnings", action="store_true", |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
365 help="include warning-level checks") |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
366 parser.add_option("-p", "--per-file", type="int", |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
367 help="max warnings per file") |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
368 parser.add_option("-b", "--blame", action="store_true", |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
369 help="use annotate to generate blame info") |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
370 parser.add_option("", "--debug", action="store_true", |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
371 help="show debug information") |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
372 |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
373 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False) |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
374 (options, args) = parser.parse_args() |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
375 |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
376 if len(args) == 0: |
10716
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
377 check = glob.glob("*") |
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
378 else: |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
379 check = args |
10281 | 380 |
10716
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
381 for f in check: |
11816
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
382 ret = 0 |
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
383 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings, |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
384 blame=options.blame, debug=options.debug): |
11816
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
385 ret = 1 |
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
386 sys.exit(ret) |