annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
1 #!/usr/bin/env python
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
2 #
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
3 # Mercurial hook to check for inappropriate whitespace. Currently it
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
4 # only checks Python files.
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
5 #
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
6 # This script is based on the code in the Mercurial book
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
7 # <http://hgbook.red-bean.com/read/handling-repository-events-with-hooks.html#id403945>
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
8
3
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
9 '''hook to refuse commits that introduce some bad inputs.
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
10 Inputs that are refused are conflict markers (rows of < or >
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
11 characters), and tabs and trailing white space in Python sources.
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
12
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
13 Usage: in your ~/.hgrc file add:
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
14 [hooks]
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
15 pretxncommit.whitespace = python:/path/to/check_whitespace.py:hook
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
16 pretxnchangegroup.whitespace = python:/path/to/check_whitespace.py:hook
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
17 '''
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
18
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
19 import re
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
20
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
21 def trailing_whitespace(difflines):
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
22 linenum = 0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
23 header = False
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
24 filename = ''
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
25 fnre = re.compile(r'(?:---|\+\+\+) (?P<filename>[^\t\r\n]+)')
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
26 lnre = re.compile(r'@@ -\d+,\d+ \+(?P<lineno>\d+),')
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
27 wsre = re.compile(r'\+.*[ \t]$')
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
28 tbre = re.compile(r'\+.*\t')
2
adc4e99b4a4a Added test for conflict markers.
Sjoerd Mullender <sjoerd@acm.org>
parents: 0
diff changeset
29 resre = re.compile(r'\+(<<<<<<<|>>>>>>>)')
6
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
30 adding = False
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
31
5
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
32 for chunk in difflines:
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
33 for line in chunk.split('\n'):
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
34 if header:
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
35 # remember the name of the file that this diff affects
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
36 m = fnre.match(line)
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
37 if m is not None and m.group('filename') != '/dev/null':
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
38 filename = m.group('filename').split('/', 1)[-1]
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
39 if line.startswith('+++ '):
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
40 header = False
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
41 continue
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
42 if line.startswith('diff '):
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
43 header = True
6
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
44 adding = False
5
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
45 continue
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
46 # hunk header - save the line number
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
47 m = lnre.match(line)
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
48 if m is not None:
5
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
49 linenum = int(m.group('lineno'))
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
50 continue
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
51 if header or not filename:
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
52 continue
6
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
53 if line[:1] == '+':
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
54 adding = True
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
55 elif line[:1] in (' ', '-'):
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
56 adding = False
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
57 elif adding and line.startswith(r'\ No newline at end of file'):
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
58 adding = False
95e8189b5fb4 Check for newline at end of file.
Sjoerd Mullender <sjoerd@acm.org>
parents: 5
diff changeset
59 yield filename, linenum, 'no newline at end of file'
5
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
60 # hunk body - check for an added line with bad whitespace
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
61 if filename[-3:] == '.py' or filename[-5:] == '.py.in':
5
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
62 m = tbre.match(line)
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
63 if m is not None:
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
64 yield filename, linenum, 'TABs'
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
65 # trailing whitespace, for now only in Python source
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
66 m = wsre.match(line)
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
67 if m is not None:
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
68 if filename[-3:] == '.py' or filename[-5:] == '.py.in':
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
69 yield filename, linenum, 'trailing whitespace'
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
70 # conflict markers
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
71 m = resre.match(line)
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
72 if m is not None:
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
73 yield filename, linenum, 'conflict marker'
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
74 if line and line[0] in ' +':
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
75 linenum += 1
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
76
3
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
77 def hook(ui, repo, hooktype, node, **kwargs):
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
78 import os, sys, subprocess
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
79
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
80 added = 0
5
32c51a111990 Fix checking for errors in merge changeset.
Sjoerd Mullender <sjoerd@acm.org>
parents: 4
diff changeset
81 for filename, linenum, msg in trailing_whitespace(repo[node].diff()):
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
82 print >> sys.stderr, ('%s, line %d: %s added' %
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
83 (filename, linenum, msg))
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
84 added += 1
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
85 if added:
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
86 # save the commit message so we don't need to retype it
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
87 cmtsv = os.path.join('.hg','commit.save')
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
88 subprocess.call(['hg', 'tip', '--template', '{desc}'],
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
89 stdout=open(cmtsv, 'w'))
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
90 print >> sys.stderr, 'commit message saved to %s' % cmtsv
3
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
91 return True
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
92
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
93 if __name__ == '__main__':
561cb4f73b83 Turn into proper hook function (with backward compatibility).
Sjoerd Mullender <sjoerd@acm.org>
parents: 2
diff changeset
94 if hook(None, None, None, None):
0
ae8465e44eec Script to check for inappropriate whitespace.
Sjoerd Mullender <sjoerd@acm.org>
parents:
diff changeset
95 sys.exit(1)