17ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman'''
27ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanCopyright 2011 Google Inc.
37ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
47ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanUse of this source code is governed by a BSD-style license that can be
57ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanfound in the LICENSE file.
67ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman'''
77ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
87ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman'''
97ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanUpdates all copyright headers within our code:
107ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman- For files that already have a copyright header, the header is modified
117ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  while keeping the year and holder intact.
127ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman- For files that don't have a copyright header, we add one with the current
137ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman  year and default holder.
147ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
157ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman@author: epoger@google.com
167ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman'''
177ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
187ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanimport os
197ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanimport sys
207ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
217ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmanimport fileparser
227ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
237ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman# Only modify copyright stanzas if the copyright holder is one of these.
247ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanALLOWED_COPYRIGHT_HOLDERS = [
257ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    'Google Inc.',
267ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    'Skia',
277ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    'The Android Open Source Project',
287ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman]
297ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
307ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmandef Main(root_directory):
317ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """Run everything.
327ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
337ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    @param root_directory root directory within which to modify all files
347ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
357ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    filepaths = GetAllFilepaths(root_directory)
367ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    for filepath in filepaths:
37e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        parser = fileparser.CreateParser(filepath)
387ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        if not parser:
397ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            ReportWarning('cannot find a parser for file %s, skipping...' %
407ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman                          filepath)
417ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            continue
427ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        old_file_contents = ReadFileIntoString(filepath)
43b33f8e3e55932d0e15a686ef0c598da8dbc37acdJay Foad        comment_blocks = parser.FindAllCommentBlocks(old_file_contents)
447ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        if not comment_blocks:
457ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            ReportWarning('cannot find any comment blocks in file %s' %
467ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman                          filepath)
477ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        old_copyright_block = parser.FindCopyrightBlock(comment_blocks)
487ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        if not old_copyright_block:
497ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            ReportWarning('cannot find copyright block in file %s' % filepath)
507ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        (year, holder) = parser.GetCopyrightBlockAttributes(old_copyright_block)
517ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        if holder and not ConfirmAllowedCopyrightHolder(holder):
527ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            ReportWarning(
537ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman                'unrecognized copyright holder "%s" in file %s, skipping...' % (
547ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman                    holder, filepath))
557ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            continue
567ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        new_copyright_block = parser.CreateCopyrightBlock(year, holder)
577ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        if old_copyright_block:
587ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            new_file_contents = old_file_contents.replace(
5957240ff6e2252f8986f6e47e4010bc52fbae25d1Benjamin Kramer                old_copyright_block, new_copyright_block, 1)
607ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        else:
617ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            new_file_contents = new_copyright_block + old_file_contents
627ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        WriteStringToFile(new_file_contents, filepath)
637ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
647ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmandef GetAllFilepaths(root_directory):
657ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """Return a list of all files (absolute path for each one) within a tree.
667ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
677ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    @param root_directory root directory within which to find all files
687ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
697ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    path_list = []
707ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    for dirpath, dirnames, filenames in os.walk(root_directory):
717ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        for filename in filenames:
727ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman            path_list.append(os.path.abspath(os.path.join(dirpath, filename)))
737ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return path_list
747ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
757ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmandef ReportWarning(text):
767ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """Report a warning, but continue.
777ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
787ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    print 'warning: %s' % text
797ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
807ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmandef ReportError(text):
817ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """Report an error and raise an exception.
827ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
837ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    raise IOError(text)
847ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
857ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmandef ReadFileIntoString(filepath):
867ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """Returns the full contents of this file as a string.
877ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
887ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    with open(filepath, 'r') as file_handle:
897ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman        contents = file_handle.read()
907ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return contents
917ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
927ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukmandef WriteStringToFile(string, filepath):
937ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """Writes this string out to filepath, replacing the file if it already
947ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    exists.
957ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
96e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    with open(filepath, 'w') as file_handle:
97e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer        file_handle.write(string)
98e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
99e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramerdef ConfirmAllowedCopyrightHolder(holder):
100e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer    """Returns True if this is one of our allowed copyright holders.
101e4b9c93fc1b531fe0cfe25a042f6b81c1e7c15c0Benjamin Kramer
1027ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    @param holder copyright holder as a string
1037ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    """
1047ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman    return holder in ALLOWED_COPYRIGHT_HOLDERS
1057ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1067ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman
1077ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha BrukmanMain(sys.argv[1])
1087ae6ff442a26212a0cc4c1929b8b0a105dc988e4Misha Brukman