File: check-license-headers.py

package info (click to toggle)
phosh 0.53.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 9,936 kB
  • sloc: ansic: 83,383; xml: 3,981; python: 717; sh: 449; makefile: 34; lisp: 22; javascript: 6
file content (94 lines) | stat: -rwxr-xr-x 2,551 bytes parent folder | download | duplicates (2)
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
#!/usr/bin/python3

"""
Copyright © 2020 Zander Brown <zbrown@gnome.org>

SPDX-License-Identifier: GPL-3.0-or-later

Author: Zander Brown <zbrown@gnome.org>
"""

import re
from os import walk
from os.path import join
from sys import stderr, exit

copyright_re = re.compile("Copyright (?:\(C\)|©) (\d{4}(?:-\d{4})?) (.*)")
add_copyright_re = re.compile("(\d{4}(?:-\d{4})?) (.*)")
spdx_re = re.compile("SPDX-License-Identifier: ([\w\-\.]*)")

accepted_spdx = ["GPL-3.0-or-later"]


def fail(path: str, msg: str):
    print(f"FAIL {path}: {msg}", file=stderr)
    exit(1)


def handle_file(path: str, filename: str):
    header = []

    with open(path, "r") as src:
        # Only read the first multi-line comment, if any
        for line in src:
            if line.startswith("/*") or line.startswith(" *"):
                header.append(line[2:].strip())
            else:
                break

    header.reverse()

    if len(header) < 2:
        fail(path, "Expected header")

    line = header.pop()
    if line != "":
        fail(path, f"Unexpected content “{line}”")

    copyright_holders = []

    while header[-1].startswith("C"):
        copyright_line = header.pop()

        match = copyright_re.match(copyright_line)
        if not match:
            fail(path, f"Expected copyright line, got “{copyright_line}”")
        else:
            copyright_holders.append(match.group(2))

    if len(copyright_holders):
        # Additional copyright holders
        while add_copyright_re.match(header[-1]):
            copyright_line = header.pop()
            match = add_copyright_re.match(copyright_line)
            copyright_holders.append(match.group(2))

    copyright_holder = ", ".join(copyright_holders)

    line = header.pop()
    if line != "":
        fail(path, f"Expected blank line before SPDX, got “{line}”")

    spdx_line = header.pop()

    match = spdx_re.match(spdx_line)
    if not match:
        fail(path, f"Expected SPDX line, got “{spdx_line}")
    elif match.group(1) in accepted_spdx:
        spdx = match.group(1)
    else:
        fail(path, f"Unacceptable SPDX “{match.group(1)}”")

    print(f"{filename:>30}: {spdx:<20} {copyright_holder}")


skip_dirs = ["_build", ".git", "subprojects", "contrib", "gtk-list-models"]
for root, dirs, files in walk("."):
    for skip in skip_dirs:
        if skip in dirs:
            dirs.remove(skip)

    for file in files:
        path = join(root, file)
        if path.endswith(".c") or path.endswith(".h"):
            handle_file(path, file)