blob: 8cb71d737b3dadb04f7a3dabcdb7b5b7938d91e6 [file] [log] [blame]
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04001"""Updates the license text in source file.
2"""
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -05003from __future__ import print_function
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -04004
5# An existing license is found if the file starts with the string below,
6# and ends with the first blank line.
7LICENSE_BEGIN = "// Copyright "
8
9BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur
10// Distributed under MIT license, or public domain if desired and
11// recognized in your jurisdiction.
12// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
13
14""".replace('\r\n','\n')
15
16def update_license( path, dry_run, show_diff ):
17 """Update the license statement in the specified file.
18 Parameters:
19 path: path of the C++ source file to update.
20 dry_run: if True, just print the path of the file that would be updated,
21 but don't change it.
22 show_diff: if True, print the path of the file that would be modified,
23 as well as the change made to the file.
24 """
25 with open( path, 'rt' ) as fin:
26 original_text = fin.read().replace('\r\n','\n')
27 newline = fin.newlines and fin.newlines[0] or '\n'
28 if not original_text.startswith( LICENSE_BEGIN ):
29 # No existing license found => prepend it
30 new_text = BRIEF_LICENSE + original_text
31 else:
32 license_end_index = original_text.index( '\n\n' ) # search first blank line
33 new_text = BRIEF_LICENSE + original_text[license_end_index+2:]
34 if original_text != new_text:
35 if not dry_run:
36 with open( path, 'wb' ) as fout:
37 fout.write( new_text.replace('\n', newline ) )
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050038 print('Updated', path)
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040039 if show_diff:
40 import difflib
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050041 print('\n'.join( difflib.unified_diff( original_text.split('\n'),
42 new_text.split('\n') ) ))
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040043 return True
44 return False
45
46def update_license_in_source_directories( source_dirs, dry_run, show_diff ):
47 """Updates license text in C++ source files found in directory source_dirs.
48 Parameters:
49 source_dirs: list of directory to scan for C++ sources. Directories are
50 scanned recursively.
51 dry_run: if True, just print the path of the file that would be updated,
52 but don't change it.
53 show_diff: if True, print the path of the file that would be modified,
54 as well as the change made to the file.
55 """
56 from devtools import antglob
57 prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
58 for source_dir in source_dirs:
59 cpp_sources = antglob.glob( source_dir,
60 includes = '''**/*.h **/*.cpp **/*.inl''',
61 prune_dirs = prune_dirs )
62 for source in cpp_sources:
63 update_license( source, dry_run, show_diff )
64
65def main():
66 usage = """%prog DIR [DIR2...]
67Updates license text in sources of the project in source files found
68in the directory specified on the command-line.
69
70Example of call:
71python devtools\licenseupdater.py include src -n --diff
72=> Show change that would be made to the sources.
73
74python devtools\licenseupdater.py include src
75=> Update license statement on all sources in directories include/ and src/.
76"""
77 from optparse import OptionParser
78 parser = OptionParser(usage=usage)
79 parser.allow_interspersed_args = False
80 parser.add_option('-n', '--dry-run', dest="dry_run", action='store_true', default=False,
81 help="""Only show what files are updated, do not update the files""")
82 parser.add_option('--diff', dest="show_diff", action='store_true', default=False,
83 help="""On update, show change made to the file.""")
84 parser.enable_interspersed_args()
85 options, args = parser.parse_args()
86 update_license_in_source_directories( args, options.dry_run, options.show_diff )
Derek Sollenberger2eb3b4d2016-01-11 14:41:40 -050087 print('Done')
Leon Scroggins IIIf59fb0e2014-05-28 15:19:42 -040088
89if __name__ == '__main__':
90 import sys
91 import os.path
92 sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
93 main()
94