123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions
- # are met:
- # 1. Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- # 2. Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- #
- # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
- # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- import codecs
- import logging
- import sys
- import webkitpy.style.checker as checker
- from webkitpy.style.patchreader import PatchReader
- from webkitpy.style.checker import StyleProcessor
- from webkitpy.style.filereader import TextFileReader
- from webkitpy.common.host import Host
- _log = logging.getLogger(__name__)
- def change_directory(filesystem, checkout_root, paths):
- """Change the working directory to the WebKit checkout root, if possible.
- If every path in the paths parameter is below the checkout root (or if
- the paths parameter is empty or None), this method changes the current
- working directory to the checkout root and converts the paths parameter
- as described below.
- This allows the paths being checked to be displayed relative to the
- checkout root, and for path-specific style checks to work as expected.
- Path-specific checks include whether files should be skipped, whether
- custom style rules should apply to certain files, etc.
- Returns:
- paths: A copy of the paths parameter -- possibly converted, as follows.
- If this method changed the current working directory to the
- checkout root, then the list is the paths parameter converted to
- normalized paths relative to the checkout root.
- Args:
- paths: A list of paths to the files that should be checked for style.
- This argument can be None or the empty list if a git commit
- or all changes under the checkout root should be checked.
- checkout_root: The path to the root of the WebKit checkout.
- """
- if paths is not None:
- paths = list(paths)
- if paths:
- # Then try converting all of the paths to paths relative to
- # the checkout root.
- rel_paths = []
- for path in paths:
- rel_path = filesystem.relpath(path, checkout_root)
- if rel_path.startswith(filesystem.pardir):
- # Then the path is not below the checkout root. Since all
- # paths should be interpreted relative to the same root,
- # do not interpret any of the paths as relative to the
- # checkout root. Interpret all of them relative to the
- # current working directory, and do not change the current
- # working directory.
- _log.warn(
- """Path-dependent style checks may not work correctly:
- One of the given paths is outside the WebKit checkout of the current
- working directory:
- Path: %s
- Checkout root: %s
- Pass only files below the checkout root to ensure correct results.
- See the help documentation for more info.
- """
- % (path, checkout_root))
- return paths
- rel_paths.append(rel_path)
- # If we got here, the conversion was successful.
- paths = rel_paths
- _log.debug("Changing to checkout root: " + checkout_root)
- filesystem.chdir(checkout_root)
- return paths
- class CheckWebKitStyle(object):
- def _engage_awesome_stderr_hacks(self):
- # Change stderr to write with replacement characters so we don't die
- # if we try to print something containing non-ASCII characters.
- stderr = codecs.StreamReaderWriter(sys.stderr,
- codecs.getreader('utf8'),
- codecs.getwriter('utf8'),
- 'replace')
- # Setting an "encoding" attribute on the stream is necessary to
- # prevent the logging module from raising an error. See
- # the checker.configure_logging() function for more information.
- stderr.encoding = "UTF-8"
- # FIXME: Change webkitpy.style so that we do not need to overwrite
- # the global sys.stderr. This involves updating the code to
- # accept a stream parameter where necessary, and not calling
- # sys.stderr explicitly anywhere.
- sys.stderr = stderr
- return stderr
- def main(self):
- args = sys.argv[1:]
- host = Host()
- host.initialize_scm()
- stderr = self._engage_awesome_stderr_hacks()
- # Checking for the verbose flag before calling check_webkit_style_parser()
- # lets us enable verbose logging earlier.
- is_verbose = "-v" in args or "--verbose" in args
- checker.configure_logging(stream=stderr, is_verbose=is_verbose)
- _log.debug("Verbose logging enabled.")
- parser = checker.check_webkit_style_parser()
- (paths, options) = parser.parse(args)
- configuration = checker.check_webkit_style_configuration(options)
- paths = change_directory(host.filesystem, checkout_root=host.scm().checkout_root, paths=paths)
- style_processor = StyleProcessor(configuration)
- file_reader = TextFileReader(host.filesystem, style_processor)
- if paths and not options.diff_files:
- file_reader.process_paths(paths)
- else:
- changed_files = paths if options.diff_files else None
- patch = host.scm().create_patch(options.git_commit, changed_files=changed_files)
- patch_checker = PatchReader(file_reader)
- patch_checker.check(patch)
- error_count = style_processor.error_count
- file_count = file_reader.file_count
- delete_only_file_count = file_reader.delete_only_file_count
- _log.info("Total errors found: %d in %d files" % (error_count, file_count))
- # We fail when style errors are found or there are no checked files.
- return error_count > 0 or (file_count == 0 and delete_only_file_count == 0)
|