aboutsummaryrefslogtreecommitdiff
blob: 3690d31d365137d44b40582383c4beb0721958f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python3
# gentoo-infra: infra/githooks.git:local/git.gentoo.org/pre-receive.gentoo-news
#       vim:fileencoding=utf-8 et st=4 sts=4
# Copyright 2012-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
# $Id$

# Author: Michał Górny <mgorny@gentoo.org>
# Author: Robin H. Johnson <robbat2@gentoo.org> (hook fixups)
# Based on work of: Ulrich Müller <ulm@gentoo.org>

import datetime
import os
import re
import subprocess
import sys
import fileinput

PATH_REGEX = re.compile(r'''
(?P<year> \d{4}) - (?P<month> \d{2}) - (?P<day> \d{2})
          - (?P<name> [a-z0-9+_-]+) /
(?P=year) - (?P=month) - (?P=day) - (?P=name)
          . (?P<lang> [a-z]{2}) .txt (?: .asc )?
''', re.VERBOSE)

# special git commit id
ZEROS = '0000000000000000000000000000000000000000'

def main(prog, *argv):
    if 'GIT_DIR' not in os.environ:
        return '%s: GIT_DIR unset' % (prog, )
    results = []
    for line in fileinput.input():
        if isinstance(line, bytes):
            line = line.decode()
        # <old-value> SP <new-value> SP <ref-name> LF
        (oldrev, newrev, refname) = line.split()
        results += [validate(oldrev, newrev, refname)]
    results = [x for x in results if x != 0]
    if len(results) == 0:
        return 0

    print('%s: errors in commits' % (prog, ))
    print(''.join([x+"\n" for x in results]))
    return 1

def validate(oldrev, newrev, refname):
    # Deletion of a branch means no work to do anyway.
    # And git-diff will fail
    if newrev == ZEROS:
        return 0

    # New branch or tag, find where it forked from master
    if oldrev == ZEROS:
        proc = subprocess.Popen( \
                ['git', 'merge-base', \
                    'refs/heads/master', newrev],
                stdout=subprocess.PIPE)
        merge_base = proc.communicate()[0].rstrip()
        if isinstance(merge_base, bytes):
            merge_base = merge_base.decode()
        if len(merge_base) > 0:
            oldrev = merge_base

    proc = subprocess.Popen( \
            ['git', 'diff', \
                '--name-only', '--diff-filter=A',  \
                '%s..%s' % (oldrev, newrev)],
            stdout=subprocess.PIPE)
    added = proc.communicate()[0]
    if isinstance(added, bytes):
        added = added.decode()
    added = added.rstrip().split('\n')

    for filename in [f for f in added if len(f) > 0]:
        # GLEP 42: name should take the form of:
        # yyyy-mm-dd-<name>/yyyy-mm-dd-<name>.<lang>.txt[.asc]
        # where <name>: [a-z0-9+_-]+, <lang>: [a-z][a-z]

        match = PATH_REGEX.match(filename)
        if not match:
            return 'Path syntax invalid: %s' % filename
        date = [int(match.group(x)) for x in ('year', 'month', 'day')]

        try:
            datetime.date(*date)
        except ValueError:
            return 'Date invalid: %s' % '-'.join(date)

    # return nothing if good
    return 0

if __name__ == '__main__':
    _args = sys.argv[1:]
    sys.exit(main(sys.argv[0], *_args))