168 lines
7.1 KiB
Python
168 lines
7.1 KiB
Python
# 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):
|
|
# Python 3 strings are unicode, we don't need to encode stderr
|
|
if sys.version_info > (3, 0):
|
|
return sys.stderr
|
|
|
|
# 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)
|
|
file_reader.do_association_check(host.scm().checkout_root)
|
|
else:
|
|
changed_files = paths if options.diff_files else None
|
|
patch = host.scm().create_patch(options.git_commit, changed_files=changed_files, git_index=options.git_index)
|
|
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)
|