180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru'''
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruCopyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruUse of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querufound in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru'''
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru'''
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruUpdates all copyright headers within our code:
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru- For files that already have a copyright header, the header is modified
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru  while keeping the year and holder intact.
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru- For files that don't have a copyright header, we add one with the current
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru  year and default holder.
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru@author: epoger@google.com
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru'''
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport os
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport sys
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport fileparser
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru# Only modify copyright stanzas if the copyright holder is one of these.
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruALLOWED_COPYRIGHT_HOLDERS = [
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    'Google Inc.',
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    'Skia',
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    'The Android Open Source Project',
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru]
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef Main(root_directory):
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Run everything.
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    @param root_directory root directory within which to modify all files
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    filepaths = GetAllFilepaths(root_directory)
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for filepath in filepaths:
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        parser = fileparser.CreateParser(filepath)
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if not parser:
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ReportWarning('cannot find a parser for file %s, skipping...' %
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          filepath)
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        old_file_contents = ReadFileIntoString(filepath)
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        comment_blocks = parser.FindAllCommentBlocks(old_file_contents)
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if not comment_blocks:
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ReportWarning('cannot find any comment blocks in file %s' %
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                          filepath)
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        old_copyright_block = parser.FindCopyrightBlock(comment_blocks)
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if not old_copyright_block:
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ReportWarning('cannot find copyright block in file %s' % filepath)
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        (year, holder) = parser.GetCopyrightBlockAttributes(old_copyright_block)
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if holder and not ConfirmAllowedCopyrightHolder(holder):
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            ReportWarning(
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                'unrecognized copyright holder "%s" in file %s, skipping...' % (
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    holder, filepath))
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            continue
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        new_copyright_block = parser.CreateCopyrightBlock(year, holder)
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if old_copyright_block:
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            new_file_contents = old_file_contents.replace(
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                old_copyright_block, new_copyright_block, 1)
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        else:
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            new_file_contents = new_copyright_block + old_file_contents
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        WriteStringToFile(new_file_contents, filepath)
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef GetAllFilepaths(root_directory):
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Return a list of all files (absolute path for each one) within a tree.
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    @param root_directory root directory within which to find all files
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    path_list = []
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for dirpath, dirnames, filenames in os.walk(root_directory):
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        for filename in filenames:
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            path_list.append(os.path.abspath(os.path.join(dirpath, filename)))
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return path_list
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef ReportWarning(text):
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Report a warning, but continue.
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    print 'warning: %s' % text
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef ReportError(text):
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Report an error and raise an exception.
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    raise IOError(text)
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef ReadFileIntoString(filepath):
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Returns the full contents of this file as a string.
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    with open(filepath, 'r') as file_handle:
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        contents = file_handle.read()
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return contents
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef WriteStringToFile(string, filepath):
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Writes this string out to filepath, replacing the file if it already
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    exists.
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    with open(filepath, 'w') as file_handle:
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        file_handle.write(string)
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef ConfirmAllowedCopyrightHolder(holder):
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """Returns True if this is one of our allowed copyright holders.
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    @param holder copyright holder as a string
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    """
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return holder in ALLOWED_COPYRIGHT_HOLDERS
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruMain(sys.argv[1])
108