"""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() | |