1"""Updates the license text in source file. 2""" 3from __future__ import print_function 4 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 and The JsonCpp Authors 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)) 38 print('Updated', path) 39 if show_diff: 40 import difflib 41 print('\n'.join(difflib.unified_diff(original_text.split('\n'), 42 new_text.split('\n')))) 43 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) 87 print('Done') 88 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 95