| """Updates the license text in source file. | |
| """ | |
| # An existing license is found if the file starts with the string below, | |
| # and ends with the first blank line. | |
| LICENSE_BEGIN = "// Copyright " | |
| BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur | |
| // Distributed under MIT license, or public domain if desired and | |
| // recognized in your jurisdiction. | |
| // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
| """.replace('\r\n','\n') | |
| def update_license( path, dry_run, show_diff ): | |
| """Update the license statement in the specified file. | |
| Parameters: | |
| path: path of the C++ source file to update. | |
| dry_run: if True, just print the path of the file that would be updated, | |
| but don't change it. | |
| show_diff: if True, print the path of the file that would be modified, | |
| as well as the change made to the file. | |
| """ | |
| with open( path, 'rt' ) as fin: | |
| original_text = fin.read().replace('\r\n','\n') | |
| newline = fin.newlines and fin.newlines[0] or '\n' | |
| if not original_text.startswith( LICENSE_BEGIN ): | |
| # No existing license found => prepend it | |
| new_text = BRIEF_LICENSE + original_text | |
| else: | |
| license_end_index = original_text.index( '\n\n' ) # search first blank line | |
| new_text = BRIEF_LICENSE + original_text[license_end_index+2:] | |
| if original_text != new_text: | |
| if not dry_run: | |
| with open( path, 'wb' ) as fout: | |
| fout.write( new_text.replace('\n', newline ) ) | |
| print 'Updated', path | |
| if show_diff: | |
| import difflib | |
| print '\n'.join( difflib.unified_diff( original_text.split('\n'), | |
| new_text.split('\n') ) ) | |
| return True | |
| return False | |
| def update_license_in_source_directories( source_dirs, dry_run, show_diff ): | |
| """Updates license text in C++ source files found in directory source_dirs. | |
| Parameters: | |
| source_dirs: list of directory to scan for C++ sources. Directories are | |
| scanned recursively. | |
| dry_run: if True, just print the path of the file that would be updated, | |
| but don't change it. | |
| show_diff: if True, print the path of the file that would be modified, | |
| as well as the change made to the file. | |
| """ | |
| from devtools import antglob | |
| prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' | |
| for source_dir in source_dirs: | |
| cpp_sources = antglob.glob( source_dir, | |
| includes = '''**/*.h **/*.cpp **/*.inl''', | |
| prune_dirs = prune_dirs ) | |
| for source in cpp_sources: | |
| update_license( source, dry_run, show_diff ) | |
| def main(): | |
| usage = """%prog DIR [DIR2...] | |
| Updates license text in sources of the project in source files found | |
| in the directory specified on the command-line. | |
| Example of call: | |
| python devtools\licenseupdater.py include src -n --diff | |
| => Show change that would be made to the sources. | |
| python devtools\licenseupdater.py include src | |
| => Update license statement on all sources in directories include/ and src/. | |
| """ | |
| from optparse import OptionParser | |
| parser = OptionParser(usage=usage) | |
| parser.allow_interspersed_args = False | |
| parser.add_option('-n', '--dry-run', dest="dry_run", action='store_true', default=False, | |
| help="""Only show what files are updated, do not update the files""") | |
| parser.add_option('--diff', dest="show_diff", action='store_true', default=False, | |
| help="""On update, show change made to the file.""") | |
| parser.enable_interspersed_args() | |
| options, args = parser.parse_args() | |
| update_license_in_source_directories( args, options.dry_run, options.show_diff ) | |
| print 'Done' | |
| if __name__ == '__main__': | |
| import sys | |
| import os.path | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| main() | |