mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
289 lines
11 KiB
Python
289 lines
11 KiB
Python
# Copyright 2014 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Presubmit script for mojo
|
|
|
|
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
|
|
for more details about the presubmit API built into depot_tools.
|
|
"""
|
|
|
|
import os.path
|
|
import re
|
|
|
|
# NOTE: The EDK allows all external paths, so doesn't need a whitelist.
|
|
_PACKAGE_WHITELISTED_EXTERNAL_PATHS = {
|
|
"SDK": ["//build/module_args/mojo.gni",
|
|
"//build/module_args/dart.gni",
|
|
"//testing/gtest",
|
|
"//third_party/cython",
|
|
"//third_party/khronos"],
|
|
"services": ["//build/module_args/mojo.gni",
|
|
"//testing/gtest"],
|
|
}
|
|
|
|
# These files are not part of the exported package.
|
|
_PACKAGE_IGNORED_BUILD_FILES = {
|
|
"SDK": {},
|
|
"EDK": {},
|
|
"services": {"mojo/services/BUILD.gn"},
|
|
}
|
|
|
|
|
|
_PACKAGE_PATH_PREFIXES = {"SDK": "mojo/public/",
|
|
"EDK": "mojo/edk/",
|
|
"services": "mojo/services"}
|
|
|
|
# TODO(etiennej): python_binary_source_set added due to crbug.com/443147
|
|
_PACKAGE_SOURCE_SET_TYPES = {"SDK": ["mojo_sdk_source_set",
|
|
"python_binary_source_set"],
|
|
"EDK": ["mojo_edk_source_set"],
|
|
"services": ["mojo_sdk_source_set"]}
|
|
|
|
_ILLEGAL_EXTERNAL_PATH_WARNING_MESSAGE = \
|
|
"Found disallowed external paths within SDK buildfiles."
|
|
|
|
_ILLEGAL_SERVICES_ABSOLUTE_PATH_WARNING_MESSAGE = \
|
|
"Found references to services' public buildfiles via absolute paths " \
|
|
"within services' public buildfiles."
|
|
|
|
_ILLEGAL_EDK_ABSOLUTE_PATH_WARNING_MESSAGE = \
|
|
"Found references to the EDK via absolute paths within EDK buildfiles."
|
|
|
|
_ILLEGAL_SDK_ABSOLUTE_PATH_WARNING_MESSAGE_TEMPLATE = \
|
|
"Found references to the SDK via absolute paths within %s buildfiles."
|
|
|
|
_ILLEGAL_SDK_ABSOLUTE_PATH_WARNING_MESSAGES = {
|
|
"SDK": _ILLEGAL_SDK_ABSOLUTE_PATH_WARNING_MESSAGE_TEMPLATE % "SDK",
|
|
"EDK": _ILLEGAL_SDK_ABSOLUTE_PATH_WARNING_MESSAGE_TEMPLATE % "EDK",
|
|
"services": _ILLEGAL_SDK_ABSOLUTE_PATH_WARNING_MESSAGE_TEMPLATE
|
|
% "services' public",
|
|
}
|
|
|
|
_INCORRECT_SOURCE_SET_TYPE_WARNING_MESSAGE_TEMPLATE = \
|
|
"All source sets in %s must be constructed via %s."
|
|
|
|
_INCORRECT_SOURCE_SET_TYPE_WARNING_MESSAGES = {
|
|
"SDK": _INCORRECT_SOURCE_SET_TYPE_WARNING_MESSAGE_TEMPLATE
|
|
% ("the SDK", _PACKAGE_SOURCE_SET_TYPES["SDK"]),
|
|
"EDK": _INCORRECT_SOURCE_SET_TYPE_WARNING_MESSAGE_TEMPLATE
|
|
% ("the EDK", _PACKAGE_SOURCE_SET_TYPES["EDK"]),
|
|
"services": _INCORRECT_SOURCE_SET_TYPE_WARNING_MESSAGE_TEMPLATE
|
|
% ("services' client libs", _PACKAGE_SOURCE_SET_TYPES["services"]),
|
|
}
|
|
|
|
def _IsBuildFileWithinPackage(f, package):
|
|
"""Returns whether |f| specifies a GN build file within |package|."""
|
|
assert package in _PACKAGE_PATH_PREFIXES
|
|
package_path_prefix = _PACKAGE_PATH_PREFIXES[package]
|
|
|
|
if not f.LocalPath().startswith(package_path_prefix):
|
|
return False
|
|
if (not f.LocalPath().endswith("/BUILD.gn") and
|
|
not f.LocalPath().endswith(".gni")):
|
|
return False
|
|
if f.LocalPath() in _PACKAGE_IGNORED_BUILD_FILES[package]:
|
|
return False
|
|
return True
|
|
|
|
def _AffectedBuildFilesWithinPackage(input_api, package):
|
|
"""Returns all the affected build files within |package|."""
|
|
return [f for f in input_api.AffectedFiles()
|
|
if _IsBuildFileWithinPackage(f, package)]
|
|
|
|
def _FindIllegalAbsolutePathsInBuildFiles(input_api, package):
|
|
"""Finds illegal absolute paths within the build files in
|
|
|input_api.AffectedFiles()| that are within |package|.
|
|
An illegal absolute path within the SDK or a service's SDK is one that is to
|
|
the SDK itself or a non-whitelisted external path. An illegal absolute path
|
|
within the EDK is one that is to the SDK or the EDK.
|
|
Returns any such references in a list of (file_path, line_number,
|
|
referenced_path) tuples."""
|
|
illegal_references = []
|
|
for f in _AffectedBuildFilesWithinPackage(input_api, package):
|
|
for line_num, line in f.ChangedContents():
|
|
# Determine if this is a reference to an absolute path.
|
|
m = re.search(r'"(//[^"]*)"', line)
|
|
if not m:
|
|
continue
|
|
referenced_path = m.group(1)
|
|
|
|
if not referenced_path.startswith("//mojo"):
|
|
# In the EDK, all external absolute paths are allowed.
|
|
if package == "EDK":
|
|
continue
|
|
|
|
# Determine if this is a whitelisted external path.
|
|
if referenced_path in _PACKAGE_WHITELISTED_EXTERNAL_PATHS[package]:
|
|
continue
|
|
|
|
illegal_references.append((f.LocalPath(), line_num, referenced_path))
|
|
|
|
return illegal_references
|
|
|
|
def _PathReferenceInBuildFileWarningItem(build_file, line_num, referenced_path):
|
|
"""Returns a string expressing a warning item that |referenced_path| is
|
|
referenced at |line_num| in |build_file|."""
|
|
return "%s, line %d (%s)" % (build_file, line_num, referenced_path)
|
|
|
|
def _IncorrectSourceSetTypeWarningItem(build_file, line_num):
|
|
"""Returns a string expressing that the error occurs at |line_num| in
|
|
|build_file|."""
|
|
return "%s, line %d" % (build_file, line_num)
|
|
|
|
def _CheckNoIllegalAbsolutePathsInBuildFiles(input_api, output_api, package):
|
|
"""Makes sure that the BUILD.gn files within |package| do not reference the
|
|
SDK/EDK via absolute paths, and do not reference disallowed external
|
|
dependencies."""
|
|
sdk_references = []
|
|
edk_references = []
|
|
external_deps_references = []
|
|
services_references = []
|
|
|
|
# Categorize any illegal references.
|
|
illegal_references = _FindIllegalAbsolutePathsInBuildFiles(input_api, package)
|
|
for build_file, line_num, referenced_path in illegal_references:
|
|
reference_string = _PathReferenceInBuildFileWarningItem(build_file,
|
|
line_num,
|
|
referenced_path)
|
|
if referenced_path.startswith("//mojo/public"):
|
|
sdk_references.append(reference_string)
|
|
elif package == "SDK":
|
|
external_deps_references.append(reference_string)
|
|
elif package == "services":
|
|
if referenced_path.startswith("//mojo/services"):
|
|
services_references.append(reference_string)
|
|
else:
|
|
external_deps_references.append(reference_string)
|
|
elif referenced_path.startswith("//mojo/edk"):
|
|
edk_references.append(reference_string)
|
|
|
|
# Package up categorized illegal references into results.
|
|
results = []
|
|
if sdk_references:
|
|
results.extend([output_api.PresubmitError(
|
|
_ILLEGAL_SDK_ABSOLUTE_PATH_WARNING_MESSAGES[package],
|
|
items=sdk_references)])
|
|
|
|
if external_deps_references:
|
|
assert package == "SDK" or package == "services"
|
|
results.extend([output_api.PresubmitError(
|
|
_ILLEGAL_EXTERNAL_PATH_WARNING_MESSAGE,
|
|
items=external_deps_references)])
|
|
|
|
if services_references:
|
|
assert package == "services"
|
|
results.extend([output_api.PresubmitError(
|
|
_ILLEGAL_SERVICES_ABSOLUTE_PATH_WARNING_MESSAGE,
|
|
items=services_references)])
|
|
|
|
if edk_references:
|
|
assert package == "EDK"
|
|
results.extend([output_api.PresubmitError(
|
|
_ILLEGAL_EDK_ABSOLUTE_PATH_WARNING_MESSAGE,
|
|
items=edk_references)])
|
|
|
|
return results
|
|
|
|
def _CheckSourceSetsAreOfCorrectType(input_api, output_api, package):
|
|
"""Makes sure that the BUILD.gn files always use the correct wrapper type for
|
|
|package|, which can be one of ["SDK", "EDK"], to construct source_set
|
|
targets."""
|
|
assert package in _PACKAGE_SOURCE_SET_TYPES
|
|
required_source_set_type = _PACKAGE_SOURCE_SET_TYPES[package]
|
|
|
|
problems = []
|
|
for f in _AffectedBuildFilesWithinPackage(input_api, package):
|
|
for line_num, line in f.ChangedContents():
|
|
m = re.search(r"[a-z_]*source_set\(", line)
|
|
if not m:
|
|
continue
|
|
source_set_type = m.group(0)[:-1]
|
|
if source_set_type in required_source_set_type:
|
|
continue
|
|
problems.append(_IncorrectSourceSetTypeWarningItem(f.LocalPath(),
|
|
line_num))
|
|
|
|
if not problems:
|
|
return []
|
|
return [output_api.PresubmitError(
|
|
_INCORRECT_SOURCE_SET_TYPE_WARNING_MESSAGES[package],
|
|
items=problems)]
|
|
|
|
def _CheckChangePylintsClean(input_api, output_api):
|
|
# Additional python module paths (we're in src/mojo/); not everyone needs
|
|
# them, but it's easiest to add them to everyone's path.
|
|
# For ply and jinja2:
|
|
third_party_path = os.path.join(
|
|
input_api.PresubmitLocalPath(), "..", "third_party")
|
|
# For the bindings generator:
|
|
mojo_public_bindings_pylib_path = os.path.join(
|
|
input_api.PresubmitLocalPath(), "public", "tools", "bindings", "pylib")
|
|
# For the python bindings:
|
|
mojo_python_bindings_path = os.path.join(
|
|
input_api.PresubmitLocalPath(), "public", "python")
|
|
# For the python bindings tests:
|
|
mojo_python_bindings_tests_path = os.path.join(
|
|
input_api.PresubmitLocalPath(), "python", "tests")
|
|
# For the roll tools scripts:
|
|
mojo_roll_tools_path = os.path.join(
|
|
input_api.PresubmitLocalPath(), "tools", "roll")
|
|
# For all mojo/tools scripts:
|
|
mopy_path = os.path.join(input_api.PresubmitLocalPath(), "tools")
|
|
# For all mojo/devtools scripts:
|
|
devtools_path = os.path.join(input_api.PresubmitLocalPath(), "devtools")
|
|
# TODO(vtl): Don't lint these files until the (many) problems are fixed
|
|
# (possibly by deleting/rewriting some files).
|
|
temporary_black_list = (
|
|
r".*\bpublic[\\\/]tools[\\\/]bindings[\\\/]pylib[\\\/]mojom[\\\/]"
|
|
r"generate[\\\/].+\.py$",
|
|
r".*\bpublic[\\\/]tools[\\\/]bindings[\\\/]generators[\\\/].+\.py$")
|
|
black_list = input_api.DEFAULT_BLACK_LIST + temporary_black_list + (
|
|
# Imported from Android tools, we might want not to fix the warnings
|
|
# raised for it to make it easier to compare the code with the original.
|
|
r".*\bdevtools[\\\/]common[\\\/]android_stack_parser[\\\/].+\.py$",)
|
|
|
|
results = []
|
|
pylint_extra_paths = [
|
|
third_party_path,
|
|
mojo_public_bindings_pylib_path,
|
|
mojo_python_bindings_path,
|
|
mojo_python_bindings_tests_path,
|
|
mojo_roll_tools_path,
|
|
mopy_path,
|
|
devtools_path
|
|
]
|
|
results.extend(input_api.canned_checks.RunPylint(
|
|
input_api, output_api, extra_paths_list=pylint_extra_paths,
|
|
black_list=black_list))
|
|
return results
|
|
|
|
def _BuildFileChecks(input_api, output_api):
|
|
"""Performs checks on SDK, EDK, and services' public buildfiles."""
|
|
results = []
|
|
for package in ["SDK", "EDK", "services"]:
|
|
results.extend(_CheckNoIllegalAbsolutePathsInBuildFiles(input_api,
|
|
output_api,
|
|
package))
|
|
results.extend(_CheckSourceSetsAreOfCorrectType(input_api,
|
|
output_api,
|
|
package))
|
|
return results
|
|
|
|
def _CommonChecks(input_api, output_api):
|
|
"""Checks common to both upload and commit."""
|
|
results = []
|
|
results.extend(_BuildFileChecks(input_api, output_api))
|
|
return results
|
|
|
|
def CheckChangeOnUpload(input_api, output_api):
|
|
results = []
|
|
results.extend(_CommonChecks(input_api, output_api))
|
|
results.extend(_CheckChangePylintsClean(input_api, output_api))
|
|
return results
|
|
|
|
def CheckChangeOnCommit(input_api, output_api):
|
|
results = []
|
|
results.extend(_CommonChecks(input_api, output_api))
|
|
return results
|