contrib/check-commit
changeset 43659 99e231afc29c
parent 43112 24a07347aa60
child 45830 c102b704edb5
equal deleted inserted replaced
43658:0796e266d26b 43659:99e231afc29c
    25 afterheader = commitheader + r"(?!#)"
    25 afterheader = commitheader + r"(?!#)"
    26 beforepatch = afterheader + r"(?!\n(?!@@))"
    26 beforepatch = afterheader + r"(?!\n(?!@@))"
    27 
    27 
    28 errors = [
    28 errors = [
    29     (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"),
    29     (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"),
    30     (beforepatch + r".*[(]issue \d\d\d",
    30     (
    31      "no space allowed between issue and number"),
    31         beforepatch + r".*[(]issue \d\d\d",
       
    32         "no space allowed between issue and number",
       
    33     ),
    32     (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
    34     (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"),
    33     (commitheader + r"# User [^@\n]+\n", "username is not an email address"),
    35     (commitheader + r"# User [^@\n]+\n", "username is not an email address"),
    34     (commitheader + r"(?!merge with )[^#]\S+[^:] ",
    36     (
    35      "summary line doesn't start with 'topic: '"),
    37         commitheader + r"(?!merge with )[^#]\S+[^:] ",
       
    38         "summary line doesn't start with 'topic: '",
       
    39     ),
    36     (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"),
    40     (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"),
    37     (afterheader + r"^\S+: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
    41     (afterheader + r"^\S+: *[A-Z][a-z]\S+", "don't capitalize summary lines"),
    38     (afterheader + r"\S*[^A-Za-z0-9-_]\S*: ",
    42     (
    39      "summary keyword should be most user-relevant one-word command or topic"),
    43         afterheader + r"\S*[^A-Za-z0-9-_]\S*: ",
       
    44         "summary keyword should be most user-relevant one-word command or topic",
       
    45     ),
    40     (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"),
    46     (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"),
    41     (afterheader + r".{79,}", "summary line too long (limit is 78)"),
    47     (afterheader + r".{79,}", "summary line too long (limit is 78)"),
    42 ]
    48 ]
    43 
    49 
    44 word = re.compile(r'\S')
    50 word = re.compile(r'\S')
       
    51 
       
    52 
    45 def nonempty(first, second):
    53 def nonempty(first, second):
    46     if word.search(first):
    54     if word.search(first):
    47         return first
    55         return first
    48     return second
    56     return second
    49 
    57 
       
    58 
    50 def checkcommit(commit, node=None):
    59 def checkcommit(commit, node=None):
    51     exitcode = 0
    60     exitcode = 0
    52     printed = node is None
    61     printed = node is None
    53     hits = []
    62     hits = []
    54     signtag = (afterheader +
    63     signtag = (
    55           r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}')
    64         afterheader + r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}'
       
    65     )
    56     if re.search(signtag, commit):
    66     if re.search(signtag, commit):
    57         return 0
    67         return 0
    58     for exp, msg in errors:
    68     for exp, msg in errors:
    59         for m in re.finditer(exp, commit):
    69         for m in re.finditer(exp, commit):
    60             end = m.end()
    70             end = m.end()
    82                 del hits[0]
    92                 del hits[0]
    83             last = nonempty(l, last)
    93             last = nonempty(l, last)
    84 
    94 
    85     return exitcode
    95     return exitcode
    86 
    96 
       
    97 
    87 def readcommit(node):
    98 def readcommit(node):
    88     return os.popen("hg export %s" % node).read()
    99     return os.popen("hg export %s" % node).read()
       
   100 
    89 
   101 
    90 if __name__ == "__main__":
   102 if __name__ == "__main__":
    91     exitcode = 0
   103     exitcode = 0
    92     node = os.environ.get("HG_NODE")
   104     node = os.environ.get("HG_NODE")
    93 
   105