1 ''' 2 Copyright 2011 Google Inc. 3 4 Use of this source code is governed by a BSD-style license that can be 5 found in the LICENSE file. 6 ''' 7 8 ''' 9 Updates all copyright headers within our code: 10 - For files that already have a copyright header, the header is modified 11 while keeping the year and holder intact. 12 - For files that don't have a copyright header, we add one with the current 13 year and default holder. 14 15 @author: epoger@google.com 16 ''' 17 18 import os 19 import sys 20 21 import fileparser 22 23 # Only modify copyright stanzas if the copyright holder is one of these. 24 ALLOWED_COPYRIGHT_HOLDERS = [ 25 'Google Inc.', 26 'Skia', 27 'The Android Open Source Project', 28 ] 29 30 def Main(root_directory): 31 """Run everything. 32 33 @param root_directory root directory within which to modify all files 34 """ 35 filepaths = GetAllFilepaths(root_directory) 36 for filepath in filepaths: 37 parser = fileparser.CreateParser(filepath) 38 if not parser: 39 ReportWarning('cannot find a parser for file %s, skipping...' % 40 filepath) 41 continue 42 old_file_contents = ReadFileIntoString(filepath) 43 comment_blocks = parser.FindAllCommentBlocks(old_file_contents) 44 if not comment_blocks: 45 ReportWarning('cannot find any comment blocks in file %s' % 46 filepath) 47 old_copyright_block = parser.FindCopyrightBlock(comment_blocks) 48 if not old_copyright_block: 49 ReportWarning('cannot find copyright block in file %s' % filepath) 50 (year, holder) = parser.GetCopyrightBlockAttributes(old_copyright_block) 51 if holder and not ConfirmAllowedCopyrightHolder(holder): 52 ReportWarning( 53 'unrecognized copyright holder "%s" in file %s, skipping...' % ( 54 holder, filepath)) 55 continue 56 new_copyright_block = parser.CreateCopyrightBlock(year, holder) 57 if old_copyright_block: 58 new_file_contents = old_file_contents.replace( 59 old_copyright_block, new_copyright_block, 1) 60 else: 61 new_file_contents = new_copyright_block + old_file_contents 62 WriteStringToFile(new_file_contents, filepath) 63 64 def GetAllFilepaths(root_directory): 65 """Return a list of all files (absolute path for each one) within a tree. 66 67 @param root_directory root directory within which to find all files 68 """ 69 path_list = [] 70 for dirpath, _, filenames in os.walk(root_directory): 71 for filename in filenames: 72 path_list.append(os.path.abspath(os.path.join(dirpath, filename))) 73 return path_list 74 75 def ReportWarning(text): 76 """Report a warning, but continue. 77 """ 78 print 'warning: %s' % text 79 80 def ReportError(text): 81 """Report an error and raise an exception. 82 """ 83 raise IOError(text) 84 85 def ReadFileIntoString(filepath): 86 """Returns the full contents of this file as a string. 87 """ 88 with open(filepath, 'r') as file_handle: 89 contents = file_handle.read() 90 return contents 91 92 def WriteStringToFile(string, filepath): 93 """Writes this string out to filepath, replacing the file if it already 94 exists. 95 """ 96 with open(filepath, 'w') as file_handle: 97 file_handle.write(string) 98 99 def ConfirmAllowedCopyrightHolder(holder): 100 """Returns True if this is one of our allowed copyright holders. 101 102 @param holder copyright holder as a string 103 """ 104 return holder in ALLOWED_COPYRIGHT_HOLDERS 105 106 107 Main(sys.argv[1]) 108