master
py 83 lines 1.91 KB
Raw
1 import glob
2 import sys
3 import re
4 import os.path
5
6 EXPECTED_HEADER = '.*Copyright \\(c\\) Microsoft.*All rights reserved.*'.casefold()
7 EXTENSIONS = ['.c', '.cpp', '.cxx', '.h', '.hpp', '.hxx']
8
9 def has_header(path: str) -> bool:
10 with open(path, 'rb') as fd:
11 lines = fd.read().decode('utf-8', 'ignore').replace('\r', '').split('\n')
12
13 in_multiline_comment = False
14
15 for e in lines[:50]:
16 if e.startswith('/*'): # Simplified comment parsing
17 in_multiline_comment = True
18
19 if '*/' in e:
20 in_multiline_comment = False
21
22 if e.strip().startswith('//') or in_multiline_comment:
23 if re.match(EXPECTED_HEADER, e.casefold()):
24 return True
25
26
27 return False
28
29 def is_source_file(path: str) -> bool:
30 return any(e for e in EXTENSIONS if path.casefold().endswith(e))
31
32 def generate_header(path: str):
33 with open(path, 'rb') as fd:
34 content = fd.read().decode('utf-8', 'ignore')
35
36 header = f'''/*++
37
38 Copyright (c) Microsoft. All rights reserved.
39
40 Module Name:
41
42 {os.path.basename(path)}
43
44 Abstract:
45
46 TODO
47
48 --*/
49 '''.replace('\n', '\r\n')
50
51 with open(path, 'wb') as fd:
52 fd.write((header + content).encode('utf-8'))
53
54
55 def main(path: str, fix: bool):
56 files = glob.glob(f'{path}/**', recursive=True)
57
58 source_files = [e for e in files if is_source_file(e)]
59 print(f'Validate copyright headers for {len(source_files)} files')
60
61 missing_headers = [e for e in source_files if not has_header(e)]
62
63 if missing_headers:
64 if fix:
65 for e in missing_headers:
66 generate_header(e)
67
68 files = "\n".join(missing_headers)
69 print(f'{len(missing_headers)} files are missing a copyright header:\n{files}')
70 sys.exit(1)
71
72
73 if __name__ == '__main__':
74 path = '.'
75 fix = False
76
77 for e in sys.argv[1:]:
78 if e == '--fix':
79 fix = True
80 else:
81 path = e
82
83 main(path, fix)