##// END OF EJS Templates
dirstate-tracked-key: update the config value to match latest discussion...
dirstate-tracked-key: update the config value to match latest discussion Special cases are not special enough, we align the option name on the other. The `version` value is undocumented for now as it can only have a single value. It is supported in the code to properly detect and abort if more value are introduced in the future value. Differential Revision: https://phab.mercurial-scm.org/D12184

File last commit:

r47575:d4ba4d51 default
r49623:79a96712 default
Show More
check-commit
115 lines | 3.2 KiB | text/plain | TextLexer
Gregory Szorc
global: use python3 in shebangs...
r46434 #!/usr/bin/env python3
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043 #
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2014 Olivia Mackall <olivia@selenic.com>
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043 #
# A tool/hook to run basic sanity checks on commits/patches for
# submission to Mercurial. Install by adding the following to your
# .hg/hgrc:
#
# [hooks]
# pretxncommit = contrib/check-commit
#
# The hook can be temporarily bypassed with:
#
# $ BYPASS= hg commit
#
Matt Mackall
urls: bulk-change primary website URLs
r26421 # See also: https://mercurial-scm.org/wiki/ContributingChanges
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043
Pulkit Goyal
py3: make contrib/check-commit use print_function
r29164 from __future__ import absolute_import, print_function
Pulkit Goyal
py3: make contrib/check-commit use absolute_import
r29163
import os
import re
import sys
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043
timeless
check-commit: try to fix multiline handling...
r27782 commitheader = r"^(?:# [^\n]*\n)*"
afterheader = commitheader + r"(?!#)"
beforepatch = afterheader + r"(?!\n(?!@@))"
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043 errors = [
timeless
check-commit: try to fix multiline handling...
r27782 (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"),
Gregory Szorc
black: blacken scripts...
r44058 (
beforepatch + r".*[(]issue \d\d\d",
"no space allowed between issue and number",
),
timeless
check-commit: try to fix multiline handling...
r27782 (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
(commitheader + r"# User [^@\n]+\n", "username is not an email address"),
Gregory Szorc
black: blacken scripts...
r44058 (
commitheader + r"(?!merge with )[^#]\S+[^:] ",
"summary line doesn't start with 'topic: '",
),
timeless
check-commit: try to fix multiline handling...
r27782 (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"),
Martin von Zweigbergk
check-commit: disallow capitalization only right after topic...
r40988 (afterheader + r"^\S+: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
Gregory Szorc
black: blacken scripts...
r44058 (
afterheader + r"\S*[^A-Za-z0-9-_]\S*: ",
"summary keyword should be most user-relevant one-word command or topic",
),
timeless
check-commit: try to fix multiline handling...
r27782 (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"),
(afterheader + r".{79,}", "summary line too long (limit is 78)"),
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043 ]
Gregory Szorc
check-commit: use raw string for regular expression...
r41680 word = re.compile(r'\S')
Gregory Szorc
black: blacken scripts...
r44058
timeless
check-commit: try to fix multiline handling...
r27782 def nonempty(first, second):
if word.search(first):
return first
return second
Gregory Szorc
black: blacken scripts...
r44058
FUJIWARA Katsunori
check-commit: omit whitespace...
r28043 def checkcommit(commit, node=None):
timeless
check-commit: modularize
r27780 exitcode = 0
timeless
check-commit: support REVs as commandline arguments...
r27781 printed = node is None
timeless
check-commit: sort errors by line number
r27783 hits = []
Gregory Szorc
black: blacken scripts...
r44058 signtag = (
afterheader + r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}'
)
Augie Fackler
contrib: fix check-commit to not reject commits from `hg sign` and `hg tag`...
r30843 if re.search(signtag, commit):
return 0
timeless
check-commit: modularize
r27780 for exp, msg in errors:
Matt Mackall
check-commit: scan for multiple instances of error patterns
r28012 for m in re.finditer(exp, commit):
timeless
check-commit: try to fix multiline handling...
r27782 end = m.end()
trailing = re.search(r'(\\n)+$', exp)
if trailing:
end -= len(trailing.group()) / 2
timeless
check-commit: sort errors by line number
r27783 hits.append((end, exp, msg))
if hits:
hits.sort()
pos = 0
last = ''
for n, l in enumerate(commit.splitlines(True)):
pos += len(l)
while len(hits):
end, exp, msg = hits[0]
timeless
check-commit: try to fix multiline handling...
r27782 if pos < end:
timeless
check-commit: modularize
r27780 break
timeless
check-commit: sort errors by line number
r27783 if not printed:
printed = True
Pulkit Goyal
py3: make contrib/check-commit use print_function
r29164 print("node: %s" % node)
print("%d: %s" % (n, msg))
print(" %s" % nonempty(l, last)[:-1])
timeless
check-commit: sort errors by line number
r27783 if "BYPASS" not in os.environ:
exitcode = 1
del hits[0]
last = nonempty(l, last)
timeless
check-commit: modularize
r27780 return exitcode
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043
Gregory Szorc
black: blacken scripts...
r44058
timeless
check-commit: modularize
r27780 def readcommit(node):
return os.popen("hg export %s" % node).read()
Gregory Szorc
black: blacken scripts...
r44058
timeless
check-commit: modularize
r27780 if __name__ == "__main__":
timeless
check-commit: support REVs as commandline arguments...
r27781 exitcode = 0
timeless
check-commit: modularize
r27780 node = os.environ.get("HG_NODE")
Matt Mackall
contrib: add check-commit hook script to sanity-check commits
r22043
timeless
check-commit: modularize
r27780 if node:
commit = readcommit(node)
timeless
check-commit: support REVs as commandline arguments...
r27781 exitcode = checkcommit(commit)
elif sys.argv[1:]:
for node in sys.argv[1:]:
exitcode |= checkcommit(readcommit(node), node)
timeless
check-commit: modularize
r27780 else:
commit = sys.stdin.read()
timeless
check-commit: support REVs as commandline arguments...
r27781 exitcode = checkcommit(commit)
timeless
check-commit: modularize
r27780 sys.exit(exitcode)