Home | History | Annotate | Download | only in devtools
      1 """Updates the license text in source file.
      2 """
      3 from __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.
      7 LICENSE_BEGIN = "// Copyright "
      8 
      9 BRIEF_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 
     16 def 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 
     46 def 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 
     65 def main():
     66     usage = """%prog DIR [DIR2...]
     67 Updates license text in sources of the project in source files found
     68 in the directory specified on the command-line.
     69 
     70 Example of call:
     71 python devtools\licenseupdater.py include src -n --diff
     72 => Show change that would be made to the sources.
     73 
     74 python 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 
     89 if __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