licenseupdater.py 3.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """Updates the license text in source file.
  2. """
  3. from __future__ import print_function
  4. # An existing license is found if the file starts with the string below,
  5. # and ends with the first blank line.
  6. LICENSE_BEGIN = "// Copyright "
  7. BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur and The JsonCpp Authors
  8. // Distributed under MIT license, or public domain if desired and
  9. // recognized in your jurisdiction.
  10. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
  11. """.replace('\r\n','\n')
  12. def update_license(path, dry_run, show_diff):
  13. """Update the license statement in the specified file.
  14. Parameters:
  15. path: path of the C++ source file to update.
  16. dry_run: if True, just print the path of the file that would be updated,
  17. but don't change it.
  18. show_diff: if True, print the path of the file that would be modified,
  19. as well as the change made to the file.
  20. """
  21. with open(path, 'rt') as fin:
  22. original_text = fin.read().replace('\r\n','\n')
  23. newline = fin.newlines and fin.newlines[0] or '\n'
  24. if not original_text.startswith(LICENSE_BEGIN):
  25. # No existing license found => prepend it
  26. new_text = BRIEF_LICENSE + original_text
  27. else:
  28. license_end_index = original_text.index('\n\n') # search first blank line
  29. new_text = BRIEF_LICENSE + original_text[license_end_index+2:]
  30. if original_text != new_text:
  31. if not dry_run:
  32. with open(path, 'wb') as fout:
  33. fout.write(new_text.replace('\n', newline))
  34. print('Updated', path)
  35. if show_diff:
  36. import difflib
  37. print('\n'.join(difflib.unified_diff(original_text.split('\n'),
  38. new_text.split('\n'))))
  39. return True
  40. return False
  41. def update_license_in_source_directories(source_dirs, dry_run, show_diff):
  42. """Updates license text in C++ source files found in directory source_dirs.
  43. Parameters:
  44. source_dirs: list of directory to scan for C++ sources. Directories are
  45. scanned recursively.
  46. dry_run: if True, just print the path of the file that would be updated,
  47. but don't change it.
  48. show_diff: if True, print the path of the file that would be modified,
  49. as well as the change made to the file.
  50. """
  51. from devtools import antglob
  52. prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
  53. for source_dir in source_dirs:
  54. cpp_sources = antglob.glob(source_dir,
  55. includes = '''**/*.h **/*.cpp **/*.inl''',
  56. prune_dirs = prune_dirs)
  57. for source in cpp_sources:
  58. update_license(source, dry_run, show_diff)
  59. def main():
  60. usage = """%prog DIR [DIR2...]
  61. Updates license text in sources of the project in source files found
  62. in the directory specified on the command-line.
  63. Example of call:
  64. python devtools\licenseupdater.py include src -n --diff
  65. => Show change that would be made to the sources.
  66. python devtools\licenseupdater.py include src
  67. => Update license statement on all sources in directories include/ and src/.
  68. """
  69. from optparse import OptionParser
  70. parser = OptionParser(usage=usage)
  71. parser.allow_interspersed_args = False
  72. parser.add_option('-n', '--dry-run', dest="dry_run", action='store_true', default=False,
  73. help="""Only show what files are updated, do not update the files""")
  74. parser.add_option('--diff', dest="show_diff", action='store_true', default=False,
  75. help="""On update, show change made to the file.""")
  76. parser.enable_interspersed_args()
  77. options, args = parser.parse_args()
  78. update_license_in_source_directories(args, options.dry_run, options.show_diff)
  79. print('Done')
  80. if __name__ == '__main__':
  81. import sys
  82. import os.path
  83. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  84. main()