maintainer-scripts: build the libgdiagnostics docs for the website [PR117883]
[gcc.git] / contrib / check-MAINTAINERS.py
blob144d8815772f21ce55be47c0d0a487c826f9abd0
1 #!/usr/bin/env python3
3 # Copyright (C) 2022-2024 Free Software Foundation, Inc.
5 # This file is part of GCC.
7 # GCC is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
10 # any later version.
12 # GCC is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with GCC; see the file COPYING. If not, write to
19 # the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 # Boston, MA 02110-1301, USA.
22 # Check that names in the file are sorted
23 # alphabetically by surname.
25 import locale
26 import sys
27 from difflib import ndiff
28 from itertools import groupby
30 import unidecode
32 locale.setlocale(locale.LC_ALL, 'en_US.utf8')
34 exit_code = 0
36 if len(sys.argv) != 2:
37 print('Usage: ./check-MAINTAINERS.py path-to/MAINTAINERS')
38 sys.exit(1)
41 def get_surname(name):
42 parts = name.split()
43 surname = parts[-1]
45 # Special-case some names
46 if name == 'Stefan Schulze Frielinghaus':
47 surname = parts[1]
48 elif name == 'Kris Van Hees':
49 surname = parts[1]
50 elif surname == "d'Humieres":
51 surname = 'Humieres'
53 # Remove accents
54 return unidecode.unidecode(surname)
57 def check_group(name, lines, columns):
58 global exit_code
60 named_lines = []
61 for line in lines:
62 if line.startswith(' '):
63 print(f'Line should not start with space: "{line}"')
64 exit_code = 2
65 continue
67 if line.endswith(' '):
68 print(f'Line should not end with space: "{line}"')
69 exit_code = 3
70 continue
72 # Special-case some names
73 if line == 'James Norris':
74 named_lines.append((get_surname(line), line + "\n"))
75 continue
77 pieces = []
78 for i, column in enumerate(columns):
79 piece = ""
80 if len(line) <= column:
81 print(f'Line too short: "{line}"')
82 exit_code = 4
83 elif column > 0 and line[column - 1] != ' ':
84 print(f'Column {column - 1} should be empty: "{line}"')
85 exit_code = 5
86 elif line[column] == ' ':
87 print(f'Column {column} should be nonempty: "{line}"')
88 exit_code = 6
89 elif i == len(columns) - 1:
90 piece = line[column:].rstrip()
91 else:
92 piece = line[column:columns[i + 1]].rstrip()
94 if " " in piece:
95 print(f'Malformed field at column {column}: "{line}"')
96 exit_code = 7
98 pieces.append(piece)
100 named_lines.append((get_surname(pieces[0]), line + "\n"))
102 email = pieces[-1]
103 if email and (not email.startswith('<') or not email.endswith('>')):
104 print(f'Malformed email address: "{line}"')
105 exit_code = 8
107 lines = [line + "\n" for line in lines]
108 sorted_lines = [line for _, line in sorted(named_lines)]
109 if lines != sorted_lines:
110 exit_code = 1
111 diff = ndiff(lines, sorted_lines)
112 print(f'Wrong order for {name}:\n')
113 print(''.join(diff))
114 else:
115 print(f'{name} are fine!')
118 text = open(sys.argv[1]).read()
119 if '\t' in text:
120 print('The file should not contain tabs')
121 exit_code = 9
123 sections = [
124 # heading, paragraph index, column numbers
125 ('Global Reviewers', 1, [0, 48]),
126 ('Write After Approval', 2, [0, 32, 48]),
127 ('Bug database only accounts', 1, [0, 48]),
128 ('Contributing under the DCO', 2, [0, 48])
131 i = 0
132 count = 0
133 for is_empty, lines in groupby(text.splitlines(), lambda x: not x):
134 if is_empty:
135 continue
136 lines = list(lines)
137 if count > 0:
138 count -= 1
139 if count == 0:
140 check_group(sections[i][0], lines, sections[i][2])
141 i += 1
142 elif len(lines) == 1 and i < len(sections) and sections[i][0] in lines[0]:
143 count = sections[i][1]
145 if i < len(sections):
146 print(f'Missing "{sections[i][0]}" section')
147 exit_code = 10
149 sys.exit(exit_code)