Add safety check for local --remove-source-files.
[rsync.git] / packaging / year-tweak
1 #!/usr/bin/env python3
2
3 # This uses the output from "support/git-set-file-times --list" to discern
4 # the last-modified year of each *.c & *.h file and updates the copyright
5 # year if it isn't set right.
6
7 import sys, os, re, argparse, subprocess
8 from datetime import datetime
9
10 MAINTAINER_NAME = 'Wayne Davison'
11 MAINTAINER_SUF = ' ' + MAINTAINER_NAME + "\n"
12
13 def main():
14     latest_year = '2000'
15
16     proc = subprocess.Popen('support/git-set-file-times --list'.split(), stdout=subprocess.PIPE, encoding='utf-8')
17     for line in proc.stdout:
18         m = re.match(r'^\S\s+(?P<year>\d\d\d\d)\S+\s+\S+\s+(?P<fn>.+)', line)
19         if not m:
20             print("Failed to parse line from git-set-file-times:", line)
21             sys.exit(1)
22         m = argparse.Namespace(**m.groupdict())
23         if m.year > latest_year:
24             latest_year = m.year
25         if m.fn.startswith('zlib/') or m.fn.startswith('popt/'):
26             continue
27         if re.search(r'\.(c|h|sh|test)$', m.fn):
28             maybe_edit_copyright_year(m.fn, m.year)
29     proc.communicate()
30
31     fn = 'latest-year.h'
32     with open(fn, 'r', encoding='utf-8') as fh:
33         old_txt = fh.read()
34
35     txt = f'#define LATEST_YEAR "{latest_year}"\n'
36     if txt != old_txt:
37         print(f"Updating {fn} with year {latest_year}")
38         with open(fn, 'w', encoding='utf-8') as fh:
39             fh.write(txt)
40
41
42 def maybe_edit_copyright_year(fn, year):
43     opening_lines = [ ]
44     copyright_line = None
45
46     with open(fn, 'r', encoding='utf-8') as fh:
47         for lineno, line in enumerate(fh):
48             opening_lines.append(line)
49             if lineno > 3 and not re.search(r'\S', line):
50                 break
51             m = re.match(r'^(?P<pre>.*Copyright\s+\S+\s+)(?P<year>\d\d\d\d(?:-\d\d\d\d)?(,\s+\d\d\d\d)*)(?P<suf>.+)', line)
52             if not m:
53                 continue
54             copyright_line = argparse.Namespace(**m.groupdict())
55             copyright_line.lineno = len(opening_lines)
56             copyright_line.is_maintainer_line = MAINTAINER_NAME in copyright_line.suf
57             copyright_line.txt = line
58             if copyright_line.is_maintainer_line:
59                 break
60
61         if not copyright_line:
62             return
63
64         if copyright_line.is_maintainer_line:
65             cyears = copyright_line.year.split('-')
66             if year == cyears[0]:
67                 cyears = [ year ]
68             else:
69                 cyears = [ cyears[0], year ]
70             txt = copyright_line.pre + '-'.join(cyears) + MAINTAINER_SUF
71             if txt == copyright_line.txt:
72                 return
73             opening_lines[copyright_line.lineno - 1] = txt
74         else:
75             if fn.startswith('lib/') or fn.startswith('testsuite/'):
76                 return
77             txt = copyright_line.pre + year + MAINTAINER_SUF
78             opening_lines[copyright_line.lineno - 1] += txt
79
80         remaining_txt = fh.read()
81
82     print(f"Updating {fn} with year {year}")
83
84     with open(fn, 'w', encoding='utf-8') as fh:
85         fh.write(''.join(opening_lines))
86         fh.write(remaining_txt)
87
88
89 if __name__ == '__main__':
90     parser = argparse.ArgumentParser(description="Grab the year of last mod for our c & h files and make sure the Copyright comment is up-to-date.")
91     args = parser.parse_args()
92     main()
93
94 # vim: sw=4 et