added python script to fix copyright years based on git log
[debian/gnuradio] / dtools / bin / fix-copyright-years
1 #!/usr/bin/env python
2
3 import re
4 import datetime
5 import subprocess
6 import multiprocessing
7
8 def command(*args): return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
9
10 def is_gnuradio_co_source(lines):
11     for line in lines[:20]:
12         if 'GNU Radio is free software' in line: return True
13     return False
14
15 def get_gnuradio_co_line(lines):
16     for i, line in enumerate(lines[:5]):
17         if 'Copyright' in line and 'Free Software Foundation' in line: return line, i
18     return None
19
20 def fix_co_years(files):
21     for file in files:
22         print file
23         lines = open(file).readlines()
24         if not is_gnuradio_co_source(lines): continue
25
26         #extract the years from the git history
27         years = set(map(
28             lambda l: int(l.split()[-2]),
29             filter(
30                 lambda l: l.startswith('Date'),
31                 command('git', 'log', file).splitlines(),
32             ),
33         ))
34
35         #extract line and line number for co line
36         try: line, num = get_gnuradio_co_line(lines)
37         except: continue
38
39         #extract years from co string
40         try:
41             co_years_str = re.match('^.*Copyright (.*) Free Software Foundation.*$', line).groups()[0]
42             co_years = set(map(int, co_years_str.split(',')))
43         except: print '    format error on line %d: "%s"'%(num, line); continue
44
45         #update the years if missing any
46         all_years = co_years.union(years)
47         if all_years != co_years:
48             print '    missing years: %s'%(', '.join(map(str, sorted(all_years - co_years))))
49             all_years.add(datetime.datetime.now().year) #add the current year
50             all_years_str = ', '.join(map(str, sorted(all_years)))
51             new_text = ''.join(lines[:num] + [line.replace(co_years_str, all_years_str)] + lines[num+1:])
52             open(file, 'w').write(new_text)
53
54 if __name__ == "__main__":
55     #get recursive list of files in the repo
56     files = command('git', 'ls-tree', '--name-only', 'HEAD', '-r').splitlines()
57
58     #start n+1 processes to handle the files
59     num_procs = multiprocessing.cpu_count()
60     procs = [multiprocessing.Process(
61         target=lambda *files: fix_co_years(files),
62         args=files[num::num_procs],
63     ) for num in range(num_procs)]
64     map(multiprocessing.Process.start, procs)
65     map(multiprocessing.Process.join, procs)