contrib/check-commit
author timeless <timeless@mozdev.org>
Thu, 07 Jan 2016 00:55:45 +0000
changeset 27780 f47185f09533
parent 27779 b2479d305c10
child 27781 2af351bd289c
permissions -rwxr-xr-x
check-commit: modularize

#!/usr/bin/env python
#
# Copyright 2014 Matt Mackall <mpm@selenic.com>
#
# 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
#
# See also: https://mercurial-scm.org/wiki/ContributingChanges

import re, sys, os

errors = [
    (r"[(]bc[)]", "(BC) needs to be uppercase"),
    (r"[(]issue \d\d\d", "no space allowed between issue and number"),
    (r"[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
    (r"^# User [^@\n]+$", "username is not an email address"),
    (r"^# .*\n(?!merge with )[^#]\S+[^:] ",
     "summary line doesn't start with 'topic: '"),
    (r"^# .*\n[A-Z][a-z]\S+", "don't capitalize summary lines"),
    (r"^# .*\n[^\n]*: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
    (r"^# [^\n]*\n\S*[^A-Za-z0-9-]\S*: ",
     "summary keyword should be most user-relevant one-word command or topic"),
    (r"^# .*\n.*\.\s+$", "don't add trailing period on summary line"),
    (r"^# .*\n[^#].{78,}", "summary line too long (limit is 78)"),
    (r"^\+\n \n", "adds double empty line"),
    (r"^ \n\+\n", "adds double empty line"),
    (r"^\+[ \t]+def [a-z]+_[a-z]", "adds a function with foo_bar naming"),
]

def checkcommit(commit):
    exitcode = 0
    for exp, msg in errors:
        m = re.search(exp, commit, re.MULTILINE)
        if m:
            pos = 0
            for n, l in enumerate(commit.splitlines(True)):
                pos += len(l)
                if pos >= m.end():
                    print "%d: %s" % (n, msg)
                    print " %s" % l[:-1]
                    if "BYPASS" not in os.environ:
                        exitcode = 1
                    break
    return exitcode

def readcommit(node):
    return os.popen("hg export %s" % node).read()

if __name__ == "__main__":
    node = os.environ.get("HG_NODE")

    if node:
        commit = readcommit(node)
    else:
        commit = sys.stdin.read()

    exitcode = checkcommit(commit)
    sys.exit(exitcode)