annotate contrib/check-commit @ 36005:66c11a66ad1a

spartan: render changesets server-side on /graph page
author Anton Shestakov <av6@dwimlabs.net>
date Mon, 04 Dec 2017 19:08:41 +0800 (2017-12-04)
parents 2fb3ae89e4e1
children 47084b5ffd80
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 #!/usr/bin/env python
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # Copyright 2014 Matt Mackall <mpm@selenic.com>
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
5 # A tool/hook to run basic sanity checks on commits/patches for
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
6 # submission to Mercurial. Install by adding the following to your
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7 # .hg/hgrc:
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
8 #
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
9 # [hooks]
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
10 # pretxncommit = contrib/check-commit
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11 #
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
12 # The hook can be temporarily bypassed with:
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
13 #
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14 # $ BYPASS= hg commit
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
15 #
27047
4b0fc75f9403 urls: bulk-change primary website URLs
Matt Mackall <mpm@selenic.com>
parents: 26197
diff changeset
16 # See also: https://mercurial-scm.org/wiki/ContributingChanges
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
17
29914
91f35b1a34cf py3: make contrib/check-commit use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29913
diff changeset
18 from __future__ import absolute_import, print_function
29913
bf7fd815b083 py3: make contrib/check-commit use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28714
diff changeset
19
bf7fd815b083 py3: make contrib/check-commit use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28714
diff changeset
20 import os
bf7fd815b083 py3: make contrib/check-commit use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28714
diff changeset
21 import re
bf7fd815b083 py3: make contrib/check-commit use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28714
diff changeset
22 import sys
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
23
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
24 commitheader = r"^(?:# [^\n]*\n)*"
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
25 afterheader = commitheader + r"(?!#)"
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
26 beforepatch = afterheader + r"(?!\n(?!@@))"
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
27
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
28 errors = [
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
29 (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"),
28713
08e0c4082903 check-commit: wrap too long line
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28684
diff changeset
30 (beforepatch + r".*[(]issue \d\d\d",
08e0c4082903 check-commit: wrap too long line
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28684
diff changeset
31 "no space allowed between issue and number"),
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
32 (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
33 (commitheader + r"# User [^@\n]+\n", "username is not an email address"),
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
34 (commitheader + r"(?!merge with )[^#]\S+[^:] ",
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
35 "summary line doesn't start with 'topic: '"),
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
36 (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"),
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
37 (afterheader + r"[^\n]*: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
30840
8e805cf27caa check-commit: allow underscore as commit topic
Mathias De Maré <mathias.de_mare@nokia.com>
parents: 30477
diff changeset
38 (afterheader + r"\S*[^A-Za-z0-9-_]\S*: ",
28347
e0465035def9 check-commit: try to curb bad commit summary keywords
Matt Mackall <mpm@selenic.com>
parents: 27839
diff changeset
39 "summary keyword should be most user-relevant one-word command or topic"),
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
40 (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"),
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
41 (afterheader + r".{79,}", "summary line too long (limit is 78)"),
28684
e529b5f1b9e3 check-commit: check for double-addition of blank lines
Matt Mackall <mpm@selenic.com>
parents: 28683
diff changeset
42 (r"\n\+\n( |\+)\n", "adds double empty line"),
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
43 (r"\n \n\+\n", "adds double empty line"),
30477
37b6f0ec6241 check-commit: allow underbars in cffi_-prefix function names
Augie Fackler <augie@google.com>
parents: 29914
diff changeset
44 # Forbid "_" in function name.
37b6f0ec6241 check-commit: allow underbars in cffi_-prefix function names
Augie Fackler <augie@google.com>
parents: 29914
diff changeset
45 #
37b6f0ec6241 check-commit: allow underbars in cffi_-prefix function names
Augie Fackler <augie@google.com>
parents: 29914
diff changeset
46 # We skip the check for cffi related functions. They use names mapping the
37b6f0ec6241 check-commit: allow underbars in cffi_-prefix function names
Augie Fackler <augie@google.com>
parents: 29914
diff changeset
47 # name of the C function. C function names may contain "_".
37b6f0ec6241 check-commit: allow underbars in cffi_-prefix function names
Augie Fackler <augie@google.com>
parents: 29914
diff changeset
48 (r"\n\+[ \t]+def (?!cffi)[a-z]+_[a-z]",
37b6f0ec6241 check-commit: allow underbars in cffi_-prefix function names
Augie Fackler <augie@google.com>
parents: 29914
diff changeset
49 "adds a function with foo_bar naming"),
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
50 ]
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
51
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
52 word = re.compile('\S')
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
53 def nonempty(first, second):
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
54 if word.search(first):
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
55 return first
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
56 return second
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
57
28714
ac4684c21f73 check-commit: omit whitespace
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 28713
diff changeset
58 def checkcommit(commit, node=None):
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
59 exitcode = 0
28436
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
60 printed = node is None
28438
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
61 hits = []
31622
2fb3ae89e4e1 contrib: fix check-commit to not reject commits from `hg sign` and `hg tag`
Augie Fackler <augie@google.com>
parents: 30840
diff changeset
62 signtag = (afterheader +
2fb3ae89e4e1 contrib: fix check-commit to not reject commits from `hg sign` and `hg tag`
Augie Fackler <augie@google.com>
parents: 30840
diff changeset
63 r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}')
2fb3ae89e4e1 contrib: fix check-commit to not reject commits from `hg sign` and `hg tag`
Augie Fackler <augie@google.com>
parents: 30840
diff changeset
64 if re.search(signtag, commit):
2fb3ae89e4e1 contrib: fix check-commit to not reject commits from `hg sign` and `hg tag`
Augie Fackler <augie@google.com>
parents: 30840
diff changeset
65 return 0
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
66 for exp, msg in errors:
28683
897b2fcf079f check-commit: scan for multiple instances of error patterns
Matt Mackall <mpm@selenic.com>
parents: 28438
diff changeset
67 for m in re.finditer(exp, commit):
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
68 end = m.end()
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
69 trailing = re.search(r'(\\n)+$', exp)
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
70 if trailing:
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
71 end -= len(trailing.group()) / 2
28438
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
72 hits.append((end, exp, msg))
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
73 if hits:
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
74 hits.sort()
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
75 pos = 0
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
76 last = ''
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
77 for n, l in enumerate(commit.splitlines(True)):
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
78 pos += len(l)
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
79 while len(hits):
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
80 end, exp, msg = hits[0]
28437
7291c8165e33 check-commit: try to fix multiline handling
timeless <timeless@mozdev.org>
parents: 28436
diff changeset
81 if pos < end:
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
82 break
28438
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
83 if not printed:
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
84 printed = True
29914
91f35b1a34cf py3: make contrib/check-commit use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29913
diff changeset
85 print("node: %s" % node)
91f35b1a34cf py3: make contrib/check-commit use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29913
diff changeset
86 print("%d: %s" % (n, msg))
91f35b1a34cf py3: make contrib/check-commit use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 29913
diff changeset
87 print(" %s" % nonempty(l, last)[:-1])
28438
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
88 if "BYPASS" not in os.environ:
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
89 exitcode = 1
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
90 del hits[0]
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
91 last = nonempty(l, last)
1d095371de47 check-commit: sort errors by line number
timeless <timeless@mozdev.org>
parents: 28437
diff changeset
92
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
93 return exitcode
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
95 def readcommit(node):
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
96 return os.popen("hg export %s" % node).read()
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
97
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
98 if __name__ == "__main__":
28436
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
99 exitcode = 0
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
100 node = os.environ.get("HG_NODE")
22043
1274ff3f20a8 contrib: add check-commit hook script to sanity-check commits
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
101
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
102 if node:
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
103 commit = readcommit(node)
28436
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
104 exitcode = checkcommit(commit)
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
105 elif sys.argv[1:]:
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
106 for node in sys.argv[1:]:
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
107 exitcode |= checkcommit(readcommit(node), node)
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
108 else:
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
109 commit = sys.stdin.read()
28436
2af351bd289c check-commit: support REVs as commandline arguments
timeless <timeless@mozdev.org>
parents: 28435
diff changeset
110 exitcode = checkcommit(commit)
28435
f47185f09533 check-commit: modularize
timeless <timeless@mozdev.org>
parents: 28434
diff changeset
111 sys.exit(exitcode)