Mercurial > hg > check_whitespace
view check_whitespace.py @ 6:95e8189b5fb4
Check for newline at end of file.
author | Sjoerd Mullender <sjoerd@acm.org> |
---|---|
date | Fri, 31 Oct 2014 16:19:24 +0100 (2014-10-31) |
parents | 32c51a111990 |
children | 2ac85cc1e11b |
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> '''hook to refuse commits that introduce some bad inputs. Inputs that are refused are conflict markers (rows of < or > characters), and tabs and trailing white space in Python sources. Usage: in your ~/.hgrc file add: [hooks] pretxncommit.whitespace = python:/path/to/check_whitespace.py:hook pretxnchangegroup.whitespace = python:/path/to/check_whitespace.py:hook ''' 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') resre = re.compile(r'\+(<<<<<<<|>>>>>>>)') adding = False for chunk in difflines: for line in chunk.split('\n'): 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 adding = False 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 if line[:1] == '+': adding = True elif line[:1] in (' ', '-'): adding = False elif adding and line.startswith(r'\ No newline at end of file'): adding = False yield filename, linenum, 'no newline at end of file' # 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' # trailing whitespace, for now only in Python source m = wsre.match(line) if m is not None: if filename[-3:] == '.py' or filename[-5:] == '.py.in': yield filename, linenum, 'trailing whitespace' # conflict markers m = resre.match(line) if m is not None: yield filename, linenum, 'conflict marker' if line and line[0] in ' +': linenum += 1 def hook(ui, repo, hooktype, node, **kwargs): import os, sys, subprocess added = 0 for filename, linenum, msg in trailing_whitespace(repo[node].diff()): 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 return True if __name__ == '__main__': if hook(None, None, None, None): sys.exit(1)