##// END OF EJS Templates
configitems: declare items in a TOML file...
configitems: declare items in a TOML file Mercurial ships with Rust code that also needs to read from the config. Having a way of presenting `configitems` to both Python and Rust is needed to prevent duplication, drift, and have the appropriate devel warnings. Abstracting away from Python means choosing a config format. No single format is perfect, and I have yet to come across a developer that doesn't hate all of them in some way. Since we have a strict no-dependencies policy for Mercurial, we either need to use whatever comes with Python, vendor a library, or implement a custom format ourselves. Python stdlib means using JSON, which doesn't support comments and isn't great for humans, or `configparser` which is an obscure, untyped format that nobody uses and doesn't have a commonplace Rust parser. Implementing a custom format is error-prone, tedious and subject to the same issues as picking an existing format. Vendoring opens us to the vast array of common config formats. The ones being picked for most modern software are YAML and TOML. YAML is older and common in the Python community, but TOML is much simpler and less error-prone. I would much rather be responsible for the <1000 lines of `tomli`, on top of TOML being the choice of the Rust community, with robust crates for reading it. The structure of `configitems.toml` is explained inline.

File last commit:

r49730:6000f5b2 default
r51655:c51b178b default
Show More
check-commit
114 lines | 3.1 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 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)