view check_whitespace.py @ 0:ae8465e44eec

Script to check for inappropriate whitespace.
author Sjoerd Mullender <sjoerd@acm.org>
date Thu, 22 Apr 2010 16:50:31 +0200 (2010-04-22)
parents
children adc4e99b4a4a
line wrap: on
line source
#!/usr/bin/env python
#
# Mercurial hook to check for inappropriate whitespace.  Currently it
# only checks Python files.
#
# This script is based on the code in the Mercurial book
# <http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html#id403945>

import re

def trailing_whitespace(difflines):
    linenum = 0
    header = False
    filename = ''
    fnre = re.compile(r'(?:---|\+\+\+) (?P<filename>[^\t\r\n]+)')
    lnre = re.compile(r'@@ -\d+,\d+ \+(?P<lineno>\d+),')
    wsre = re.compile(r'\+.*[ \t]$')
    tbre = re.compile(r'\+.*\t')

    for line in difflines:
        if header:
            # remember the name of the file that this diff affects
            m = fnre.match(line)
            if m is not None and m.group('filename') != '/dev/null':
                filename = m.group('filename').split('/', 1)[-1]
            if line.startswith('+++ '):
                header = False
            continue
        if line.startswith('diff '):
            header = True
            continue
        # hunk header - save the line number
        m = lnre.match(line)
        if m is not None:
            linenum = int(m.group('lineno'))
            continue
        if header or not filename:
            continue
        # hunk body - check for an added line with bad whitespace
        if filename[-3:] == '.py' or filename[-5:] == '.py.in':
            m = tbre.match(line)
            if m is not None:
                yield filename, linenum, 'TABs'
        m = wsre.match(line)
        if m is not None:
            if filename[-3:] == '.py' or filename[-5:] == '.py.in':
                yield filename, linenum, 'trailing whitespace'
        if line and line[0] in ' +':
            linenum += 1

if __name__ == '__main__':
    import os, sys, subprocess

    added = 0
    for filename, linenum, msg in trailing_whitespace(subprocess.Popen(['hg', 'export', 'tip'], stdout=subprocess.PIPE).stdout):
        print >> sys.stderr, ('%s, line %d: %s added' %
                              (filename, linenum, msg))
        added += 1
    if added:
        # save the commit message so we don't need to retype it
        cmtsv = os.path.join('.hg','commit.save')
        subprocess.call(['hg', 'tip', '--template', '{desc}'],
                        stdout=open(cmtsv, 'w'))
        print >> sys.stderr, 'commit message saved to %s' % cmtsv
        sys.exit(1)