blob: 43ddb4f467d137806af9f17de283cfb7455e429a [file] [log] [blame]
Christopher Dunndc0f7362011-06-21 21:18:49 +00001"""Updates the license text in source file.
2"""
Christopher Dunnbd1e8952014-11-19 23:30:47 -06003from __future__ import print_function
Christopher Dunndc0f7362011-06-21 21:18:49 +00004
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
Devin Jeanpierre19fc55f2017-04-24 10:49:00 -07009BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 The JsonCpp Authors
Christopher Dunndc0f7362011-06-21 21:18:49 +000010// 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
Christopher Dunn494950a2015-01-24 15:29:52 -060016def update_license(path, dry_run, show_diff):
Christopher Dunndc0f7362011-06-21 21:18:49 +000017 """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 """
Christopher Dunn494950a2015-01-24 15:29:52 -060025 with open(path, 'rt') as fin:
Christopher Dunndc0f7362011-06-21 21:18:49 +000026 original_text = fin.read().replace('\r\n','\n')
27 newline = fin.newlines and fin.newlines[0] or '\n'
Christopher Dunn494950a2015-01-24 15:29:52 -060028 if not original_text.startswith(LICENSE_BEGIN):
Christopher Dunndc0f7362011-06-21 21:18:49 +000029 # No existing license found => prepend it
30 new_text = BRIEF_LICENSE + original_text
31 else:
Christopher Dunn494950a2015-01-24 15:29:52 -060032 license_end_index = original_text.index('\n\n') # search first blank line
Christopher Dunndc0f7362011-06-21 21:18:49 +000033 new_text = BRIEF_LICENSE + original_text[license_end_index+2:]
34 if original_text != new_text:
35 if not dry_run:
Christopher Dunn494950a2015-01-24 15:29:52 -060036 with open(path, 'wb') as fout:
37 fout.write(new_text.replace('\n', newline))
Christopher Dunnbd1e8952014-11-19 23:30:47 -060038 print('Updated', path)
Christopher Dunndc0f7362011-06-21 21:18:49 +000039 if show_diff:
40 import difflib
Christopher Dunn494950a2015-01-24 15:29:52 -060041 print('\n'.join(difflib.unified_diff(original_text.split('\n'),
42 new_text.split('\n'))))
Christopher Dunndc0f7362011-06-21 21:18:49 +000043 return True
44 return False
45
Christopher Dunn494950a2015-01-24 15:29:52 -060046def update_license_in_source_directories(source_dirs, dry_run, show_diff):
Christopher Dunndc0f7362011-06-21 21:18:49 +000047 """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:
Christopher Dunn494950a2015-01-24 15:29:52 -060059 cpp_sources = antglob.glob(source_dir,
Christopher Dunndc0f7362011-06-21 21:18:49 +000060 includes = '''**/*.h **/*.cpp **/*.inl''',
Christopher Dunn494950a2015-01-24 15:29:52 -060061 prune_dirs = prune_dirs)
Christopher Dunndc0f7362011-06-21 21:18:49 +000062 for source in cpp_sources:
Christopher Dunn494950a2015-01-24 15:29:52 -060063 update_license(source, dry_run, show_diff)
Christopher Dunndc0f7362011-06-21 21:18:49 +000064
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()
Christopher Dunn494950a2015-01-24 15:29:52 -060086 update_license_in_source_directories(args, options.dry_run, options.show_diff)
Christopher Dunnbd1e8952014-11-19 23:30:47 -060087 print('Done')
Christopher Dunndc0f7362011-06-21 21:18:49 +000088
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