contrib/check-code.py
author Brodie Rao <brodie@bitheap.org>
Sat, 09 Oct 2010 17:02:28 -0500
changeset 12681 bc13e17067d9
parent 12367 3acd5f7ab9d0
child 12743 4c4aeaab2339
permissions -rwxr-xr-x
update: use higher level wording for "crosses branches" error When using "hg update" to update to a revision on another branch, if the user has uncommitted changes in the working directory, hg aborts with the following message: abort: crosses branches (use 'hg merge' to merge or use 'hg update -C' to discard changes) If the user isn't trying to update to tip and they follow the command examples verbatim, they would end up updating to the wrong revision. This patch removes the command examples in favor of just telling the user to either merge or use --clean: abort: crosses branches (merge branches or use --clean to discard changes) hg also aborts if the user tries to use "hg update" to get to tip (without specifying a revision) and tip is on another branch: abort: crosses branches (use 'hg merge' or use 'hg update -c') This message is changed in the same fashion: abort: crosses branches (merge branches or use --check to force update)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
#!/usr/bin/env python
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     3
# check-code - a style and portability checker for Mercurial
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     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
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     6
#
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
# This software may be used and distributed according to the terms of the
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     8
# GNU General Public License version 2 or any later version.
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     9
11816
e1359ad582f6 check-code: add exit status
Alecs King <alecsk@gmail.com>
parents: 11764
diff changeset
    10
import re, glob, os, sys
10895
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
    11
import optparse
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    12
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    13
def repquote(m):
10722
c4fb2103e734 check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10720
diff changeset
    14
    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
    15
    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
    16
    return m.group('quote') + t + m.group('quote')
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    17
10727
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
    18
def reppython(m):
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
    19
    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
    20
    if comment:
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
    21
        return "#" * len(comment)
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
    22
    return repquote(m)
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    23
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    24
def repcomment(m):
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    25
    return m.group(1) + "#" * len(m.group(2))
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    26
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    27
def repccomment(m):
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    28
    t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    29
    return m.group(1) + t + "*/"
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    30
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    31
def repcallspaces(m):
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    32
    t = re.sub(r"\n\s+", "\n", m.group(2))
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    33
    return m.group(1) + t
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
def repinclude(m):
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
    return m.group(1) + "<foo>"
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    37
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    38
def rephere(m):
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    39
    t = re.sub(r"\S", "x", m.group(2))
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    40
    return m.group(1) + t
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    41
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    42
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    43
testpats = [
10374
3aa35db5e38c check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents: 10373
diff changeset
    44
    (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
    45
    (r'\W\$?\(\([^\)]*\)\)', "don't use (()) or $(()), use 'expr'"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    46
    (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
    47
    (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
    48
    (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
    49
    (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
    50
    (r'^diff.*-\w*N', "don't use 'diff -N'"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
    (r'(^| )wc[^|]*$', "filter wc output"),
10374
3aa35db5e38c check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents: 10373
diff changeset
    52
    (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
    53
    (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
    54
    (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
    55
    (r'printf.*\\x', "don't use printf \\x, use Python"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
    (r'\$\(.*\)', "don't use $(expr), use `expr`"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
    (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
    (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    59
     "use egrep for extended grep syntax"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    60
    (r'/bin/', "don't use explicit paths for tools"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    61
    (r'\$PWD', "don't use $PWD, use `pwd`"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    62
    (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
    63
    (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
    64
    ('^([^"\']|("[^"]*")|(\'[^\']*\'))*\\^', "^ must be quoted"),
11210
0c0088881562 check-code: add check for 'source'
Yuya Nishihara <yuya@tcha.org>
parents: 10905
diff changeset
    65
    (r'^source\b', "don't use 'source', use '.'"),
12367
3acd5f7ab9d0 tests: compatibility fix.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 12366
diff changeset
    66
    (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    67
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    68
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    69
testfilters = [
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    70
    (r"( *)(#([^\n]*\S)?)", repcomment),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    71
    (r"<<(\S+)((.|\n)*?\n\1)", rephere),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    72
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    73
12364
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    74
uprefix = r"^  \$ "
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    75
utestpats = [
12366
c01dc9087d9a tests: drop a bunch of sed calls from unified tests
Matt Mackall <mpm@selenic.com>
parents: 12364
diff changeset
    76
    (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
    77
    (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
    78
    (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
    79
    (uprefix + r'.*\|\| echo.*(fail|error)',
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    80
     "explicit exit code checks unnecessary"),
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    81
    (uprefix + r'set -e', "don't use set -e"),
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    82
]
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    83
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    84
for p, m in testpats:
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    85
    if p.startswith('^'):
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    86
        p = uprefix + p[1:]
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    87
    else:
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    88
        p = uprefix + p
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    89
    utestpats.append((p, m))
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    90
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    91
utestfilters = [
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    92
    (r"( *)(#([^\n]*\S)?)", repcomment),
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    93
]
e128fa4615f2 check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents: 11886
diff changeset
    94
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    95
pypats = [
11568
d5d4e6a30613 check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11522
diff changeset
    96
    (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
    97
     "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
    98
    (r'lambda\s*\(.*,.*\)',
d5d4e6a30613 check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents: 11522
diff changeset
    99
     "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
   100
    (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
   101
    (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
   102
    (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   103
    (r'^\s*\t', "don't use tabs"),
10412
5326800d6937 check-code: import some pylint checks
Matt Mackall <mpm@selenic.com>
parents: 10374
diff changeset
   104
    (r'\S;\s*\n', "semicolon"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   105
    (r'\w,\w', "missing whitespace after ,"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   106
    (r'\w[+/*\-<>]\w', "missing whitespace in expression"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   107
    (r'^\s+\w+=\w+[^,)]$', "missing whitespace in assignment"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   108
    (r'.{85}', "line too long"),
11672
dad185761392 check-code: add warning on lines over 80 characters
Matt Mackall <mpm@selenic.com>
parents: 11604
diff changeset
   109
    (r'.{81}', "warning: line over 80 characters"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   110
    (r'[^\n]\Z', "no trailing newline"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   111
#    (r'^\s+[^_ ][^_. ]+_[^_]+\s*=', "don't use underbars in identifiers"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   112
#    (r'\w*[a-z][A-Z]\w*\s*=', "don't use camelcase in identifiers"),
10286
cc0340ef47f7 check-code: check thyself
Matt Mackall <mpm@selenic.com>
parents: 10281
diff changeset
   113
    (r'^\s*(if|while|def|class|except|try)\s[^[]*:\s*[^\]#\s]+',
cc0340ef47f7 check-code: check thyself
Matt Mackall <mpm@selenic.com>
parents: 10281
diff changeset
   114
     "linebreak after :"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   115
    (r'class\s[^(]:', "old-style class, use class foo(object)"),
10291
61c93743fae0 check-code: del isn't a function
Matt Mackall <mpm@selenic.com>
parents: 10290
diff changeset
   116
    (r'^\s+del\(', "del isn't a function"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   117
    (r'^\s+except\(', "except isn't a function"),
10412
5326800d6937 check-code: import some pylint checks
Matt Mackall <mpm@selenic.com>
parents: 10374
diff changeset
   118
    (r',]', "unneeded trailing ',' in list"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   119
#    (r'class\s[A-Z][^\(]*\((?!Exception)',
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   120
#     "don't capitalize non-exception classes"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   121
#    (r'in range\(', "use xrange"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   122
#    (r'^\s*print\s+', "avoid using print in core and extensions"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   123
    (r'[\x80-\xff]', "non-ASCII character literal"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   124
    (r'("\')\.format\(', "str.format() not available in Python 2.4"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   125
    (r'^\s*with\s+', "with not available in Python 2.4"),
11345
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   126
    (r'(?<!def)\s+(any|all|format)\(',
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   127
     "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
   128
    (r'(?<!def)\s+(callable)\(',
eaa7666ad53f check-code: add test for callable
Martin Geisler <mg@aragost.com>
parents: 11345
diff changeset
   129
     "callable not available in Python 3, use hasattr(f, '__call__')"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   130
    (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   131
    (r'([\(\[]\s\S)|(\S\s[\)\]])', "gratuitous whitespace in () or []"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   132
#    (r'\s\s=', "gratuitous whitespace before ="),
11345
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   133
    (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   134
     "missing whitespace around operator"),
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   135
    (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s',
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   136
     "missing whitespace around operator"),
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   137
    (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S',
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   138
     "missing whitespace around operator"),
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   139
    (r'[^+=*!<>&| -](\s=|=\s)[^= ]',
4b81f82b03e3 check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents: 11343
diff changeset
   140
     "wrong whitespace around ="),
10451
63a9bfad50ff check-code: two more rules
Matt Mackall <mpm@selenic.com>
parents: 10412
diff changeset
   141
    (r'raise Exception', "don't raise generic exceptions"),
11599
6fcc066c0c2c check-code: warn about untranslated ui.warn calls
Martin Geisler <mg@lazybytes.net>
parents: 11522
diff changeset
   142
    (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
   143
     "warning: unwrapped ui message"),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   144
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   145
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   146
pyfilters = [
10727
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
   147
    (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
   148
         ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
   149
          (?P<text>(([^\\]|\\.)*?))
62b8f15683f2 check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10723
diff changeset
   150
          (?P=quote))""", reppython),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   151
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   152
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   153
cpats = [
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   154
    (r'//', "don't use //-style comments"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   155
    (r'^  ', "don't use spaces to indent"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   156
    (r'\S\t', "don't use tabs except for indent"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   157
    (r'(\S\s+|^\s+)\n', "trailing whitespace"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   158
    (r'.{85}', "line too long"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   159
    (r'(while|if|do|for)\(', "use space after while/if/do/for"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   160
    (r'return\(', "return is not a function"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   161
    (r' ;', "no space before ;"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   162
    (r'\w+\* \w+', "use int *foo, not int* foo"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   163
    (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   164
    (r'\S+ (\+\+|--)', "use foo++, not foo ++"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   165
    (r'\w,\w', "missing whitespace after ,"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   166
    (r'\w[+/*]\w', "missing whitespace in expression"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   167
    (r'^#\s+\w', "use #foo, not # foo"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   168
    (r'[^\n]\Z', "no trailing newline"),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   169
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   170
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   171
cfilters = [
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   172
    (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
10722
c4fb2103e734 check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10720
diff changeset
   173
    (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   174
    (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   175
    (r'(\()([^)]+\))', repcallspaces),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   176
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   177
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   178
checks = [
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   179
    ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   180
    ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   181
    ('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
   182
    ('unified test', r'.*\.t$', utestfilters, utestpats),
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   183
]
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   184
10719
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   185
class norepeatlogger(object):
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   186
    def __init__(self):
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   187
        self._lastseen = None
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   188
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   189
    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
   190
        """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
   191
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   192
        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
   193
        of multiple errors.
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   194
10719
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   195
        :fname: filename
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   196
        :lineno: line number
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   197
        :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
   198
        :msg: error message
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   199
        """
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   200
        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
   201
        if msgid != self._lastseen:
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   202
            if blame:
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   203
                print "%s:%d (%s):" % (fname, lineno, blame)
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   204
            else:
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   205
                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
   206
            print " > %s" % line
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   207
            self._lastseen = msgid
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   208
        print " " + msg
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   209
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   210
_defaultlogger = norepeatlogger()
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   211
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   212
def getblame(f):
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   213
    lines = []
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   214
    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
   215
        start, line = l.split(':', 1)
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   216
        user, rev = start.split()
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   217
        lines.append((line[1:-1], user, rev))
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   218
    return lines
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   219
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   220
def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   221
              blame=False):
10719
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   222
    """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
   223
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   224
    :f: filepath
3be9ae49b628 code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10718
diff changeset
   225
    :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
   226
              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
   227
    :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
   228
             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
   229
fbcccf9ec58f check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10719
diff changeset
   230
    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
   231
    """
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   232
    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
   233
    result = True
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   234
    for name, match, filters, pats in checks:
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   235
        fc = 0
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   236
        if not re.match(match, f):
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   237
            continue
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   238
        pre = post = open(f).read()
10287
5da892be3497 check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents: 10286
diff changeset
   239
        if "no-" + "check-code" in pre:
5da892be3497 check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents: 10286
diff changeset
   240
            break
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   241
        for p, r in filters:
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   242
            post = re.sub(p, r, post)
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   243
        # print post # uncomment to show filtered version
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   244
        z = enumerate(zip(pre.splitlines(), post.splitlines(True)))
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   245
        for n, l in z:
10287
5da892be3497 check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents: 10286
diff changeset
   246
            if "check-code" + "-ignore" in l[0]:
5da892be3497 check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents: 10286
diff changeset
   247
                continue
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   248
            for p, msg in pats:
10895
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   249
                if not warnings and msg.startswith("warning"):
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   250
                    continue
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   251
                if re.search(p, l[1]):
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   252
                    bd = ""
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   253
                    if blame:
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   254
                        bd = 'working directory'
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   255
                        if not blamecache:
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   256
                            blamecache = getblame(f)
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   257
                        if n < len(blamecache):
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   258
                            bl, bu, br = blamecache[n]
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   259
                            if bl == l[0]:
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   260
                                bd = '%s@%s' % (bu, br)
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   261
                    logfunc(f, n + 1, l[0], msg, bd)
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   262
                    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
   263
                    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
   264
            if maxerr is not None and fc >= maxerr:
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   265
                print " (too many errors, giving up)"
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   266
                break
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   267
        break
10720
fbcccf9ec58f check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10719
diff changeset
   268
    return result
10717
b1f4fcef99b3 check-code: Add a ``checkfile`` function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10716
diff changeset
   269
10716
5f92bde72eef check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10707
diff changeset
   270
if __name__ == "__main__":
10895
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   271
    parser = optparse.OptionParser("%prog [options] [files]")
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   272
    parser.add_option("-w", "--warnings", action="store_true",
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   273
                      help="include warning-level checks")
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   274
    parser.add_option("-p", "--per-file", type="int",
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   275
                      help="max warnings per file")
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   276
    parser.add_option("-b", "--blame", action="store_true",
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   277
                      help="use annotate to generate blame info")
10895
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   278
11604
c5d40818b270 check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents: 11602
diff changeset
   279
    parser.set_defaults(per_file=15, warnings=False, blame=False)
10895
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   280
    (options, args) = parser.parse_args()
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   281
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   282
    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
   283
        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
   284
    else:
10895
217557b26bc7 check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents: 10814
diff changeset
   285
        check = args
10281
e7d3b509af8b Introduce check-code.py
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
   286
10716
5f92bde72eef check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents: 10707
diff changeset
   287
    for f in check:
11816
e1359ad582f6 check-code: add exit status
Alecs King <alecsk@gmail.com>
parents: 11764
diff changeset
   288
        ret = 0
e1359ad582f6 check-code: add exit status
Alecs King <alecsk@gmail.com>
parents: 11764
diff changeset
   289
        if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
e1359ad582f6 check-code: add exit status
Alecs King <alecsk@gmail.com>
parents: 11764
diff changeset
   290
                         blame=options.blame):
e1359ad582f6 check-code: add exit status
Alecs King <alecsk@gmail.com>
parents: 11764
diff changeset
   291
            ret = 1
e1359ad582f6 check-code: add exit status
Alecs King <alecsk@gmail.com>
parents: 11764
diff changeset
   292
    sys.exit(ret)