[RFC] checkpatch.py
Giorgos Keramidas
keramida at ceid.upatras.gr
Fri Jul 3 19:54:02 CDT 2009
On Sat, 04 Jul 2009 00:59:57 +0200, Stefano Mioli <jstevie at gmail.com> wrote:
> Hi devs,
> here is a script I wrote to check a patch created by hg export against
> some of the coding style rules that can be found at
>
> http://mercurial.selenic.com/wiki/BasicCodingStyle
>
> It's still very simple, but Matt said he would like to have such a
> tool in contrib, so here it is.
It's a very good start indeed, thanks! :)
> It only does extra-simple checks for now, namely:
>
> - leading tabs
> - trailing whitespaces
> - DOS-style line endings
> - lines longer than 80 characters
These should probably be encoded in a dictionary or array of tuples, or
even a small class of checks, so we can write as many checks as possible
by simply adding new regexps to a vector instead of having to modify the
checking code?
def initchecks():
'''Compile a list of regexps and return a list of tuples with
(regexp, compiled-regexp, description text).'''
checkres = [ ( r'^ *\t{1,}[\s\S]*',
"leading indentation contains literal TAB" ),
( r'[ \t]+$', "trailing whitespace" ),
( r'\r\n$', "DOS-style line end" ), ]
checks = []
for re, desc in checkres:
try:
cre = re.compile(re)
checks.append((re, cre, desc))
except Exception, inst:
sys.stderr.write("invalid regular expression: %s" % str(inst))
sys.stderr.write("disabling check '%s'" % re)
return checks
def checkpatch(fname):
addre = None
try:
addre = re.compile(r'^\+[^\+].*')
except Exception, inst:
sys.stderr.write("invalid regular expression: %s" % str(inst))
return None
try:
f = file(fname)
except IOError, inst:
sys.stderr.write("%s: cannot read patch file" % fname)
return None
checks = initchecks()
err = []
warn = []
lc = 0
for l in lines:
lc += 1
l = l[1:]
if addre and not addre.match(l):
continue
for (re, cre, msg) in checks:
if cre and cre.match(l):
err.append("%s:%d: error: %s" % (fname, lc, msg))
if len(l) > 80:
warn.append("%s:%d: line too long" % (fname, lc))
if len(err) == 0 and len(warn) == 0:
print "patch %s looks good" % fname
return True
for e in err:
print e
for w in warn:
print w
return None
> +if (__name__ == '__main__'):
> + if (len(sys.argv) < 2):
> + print 'usage: ./checkpatch.py patch-to-check\n'
> + sys.exit(1)
> +
> + filepath = str(sys.argv[1])
> +
> + patchfile = open(filepath, 'r')
> + lines = patchfile.readlines()
> + patchfile.close()
> +
> + checkpatch(lines)
Since you are handling already one file at a time in checkpatch() it may
be worth supporting more than one input file, so one can type in a
directory full of patch files:
yourscript.py *.patch
How about something like?
progname = os.path.basename(sys.argv[0])
if len(sys.argv) == 1:
print "usage: %s patchfile [patchfile ...]" % progname
sys.exit(1)
for fn in sys.argv[1:]:
checkpatch(fn)
More information about the Mercurial-devel
mailing list