blob: a45c497d0f744058dde03c08bd47e6ff11b29730 [file] [log] [blame]
# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Top-level presubmit script for Chromium OS.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into gcl and git cl.
"""
import re
_EXCLUDED_PATHS = (
r"^inherit-review-settings-ok$",
r".*[\\\/]debian[\\\/]rules$",
)
# These match files that should contain tabs as indentation.
_TAB_OK_PATHS = (
r"/src/third_party/kernel/",
r"/src/third_party/kernel-next/",
r"/src/third_party/u-boot/",
r"/src/third_party/u-boot-next/",
r".*\.ebuild$",
r".*\.eclass$",
)
# These match files that are part of out "next" developemnt flow and as such
# do not require a valid BUG= field to commit, but it's still a good idea.
_NEXT_PATHS = (
r"/src/third_party/kernel-next",
r"/src/third_party/u-boot-next",
)
_LICENSE_HEADER = (
r".*? Copyright \(c\) 20[-0-9]{2,7} The Chromium OS Authors\. All rights "
r"reserved\." "\n"
r".*? Use of this source code is governed by a BSD-style license that can "
"be\n"
r".*? found in the LICENSE file\."
"\n"
)
def CheckAndShowLicense(input_api, output_api, source_file_filter=None):
"""Check that the source files have a valid License header.
The license header must matches our template. If not also show the
header that should have been used.
"""
results = []
license_check = input_api.canned_checks.CheckLicense(
input_api, output_api, _LICENSE_HEADER, source_file_filter)
results.extend(license_check)
if license_check:
results.extend([output_api.PresubmitNotifyResult(
"License header should match the following:",
long_text=_LICENSE_HEADER)])
return results
def CheckChangeHasMandatoryBugField(input_api,
output_api,
source_file_filter=None):
"""Check that the commit contains a valid BUG= field."""
msg = ('Changelist must reference a bug number using BUG=\n'
'For example, BUG=chromium-os:8205\n'
'BUG=none is allowed.')
if (not input_api.AffectedSourceFiles(source_file_filter) or
input_api.change.BUG):
return []
else:
return [output_api.PresubmitError(msg)]
def CheckChangeHasBugField(input_api, output_api, source_file_filter=None):
# This function is required because the canned BugField check doesn't
# take a source filter.
return input_api.canned_checks.CheckChangeHasBugField(input_api,
output_api)
def CheckChangeHasTestField(input_api, output_api, source_file_filter=None):
# This function is required because the canned TestField check doesn't
# take a source filter.
return input_api.canned_checks.CheckChangeHasTestField(input_api,
output_api)
def CheckTreeIsOpen(input_api, output_api, source_file_filter=None):
"""Make sure the tree is 'open'. If not, don't submit."""
return input_api.canned_checks.CheckTreeIsOpen(
input_api,
output_api,
json_url='http://chromiumos-status.appspot.com/current?format=json')
def CheckBuildbotPendingBuilds(input_api, output_api, source_file_filter=None):
"""Check to see if there's a backlog on the pending CL queue"""
return input_api.canned_checks.CheckBuildbotPendingBuilds(
input_api,
output_api,
'http://build.chromium.org/p/chromiumos/json/builders?filter=1',
6,
[])
def FilterAbsoluteSourceFile(input_api, affected_file, white_list, black_list):
"""Filters out files that aren't considered "source file".
The lists will be compiled as regular expression and
AffectedFile.AbsoluteLocalPath() needs to pass both list.
Note: This function was coppied from presubmit_support.py and modified to
check against (AbsoluteLocalPath - PresubmitLocalPath) instead of LocalPath
because LocalPath doesn't contain enough information to disambiguate kernel,
u-boot and -next files from the rest of ChromiumOS.
"""
presubmit_local_path = input_api.PresubmitLocalPath()
def RelativePath(affected_file):
absolute_local_path = affected_file.AbsoluteLocalPath()
assert absolute_local_path.startswith(presubmit_local_path)
return absolute_local_path[len(presubmit_local_path):]
def Find(relative_path, items):
for item in items:
if re.match(item, relative_path):
return True
return False
relative_path = RelativePath(affected_file)
return (Find(relative_path, white_list) and
not Find(relative_path, black_list))
def RunChecklist(input_api, output_api, checklist):
"""Run through a set of checks provided in a checklist.
The checklist is a list of tuples, each of which contains the check to run
and a list of regular expressions of paths to ignore for this check
"""
results = []
for check, paths in checklist:
white_list = input_api.DEFAULT_WHITE_LIST
# Construct a black list from the DEFAULT_BLACK_LIST supplied by
# depot_tools and the paths that this check should not be applied to.
#
# We also remove the third_party rule here because our paterns are
# matching against the entire path from the root of the ChromiumOS
# project. We use the rooted paths because we want to be able to apply
# some of the presubmit checks to things like the kernel and u-boot that
# live in the third_party directory.
black_list = list(input_api.DEFAULT_BLACK_LIST)
black_list.remove(r".*\bthird_party[\\\/].*")
black_list.extend(paths)
sources = lambda path: FilterAbsoluteSourceFile(input_api,
path,
white_list,
black_list)
results.extend(check(input_api, output_api, source_file_filter=sources))
return results
def MakeCommonChecklist(input_api):
return [(input_api.canned_checks.CheckLongLines, _EXCLUDED_PATHS),
(input_api.canned_checks.CheckChangeHasNoStrayWhitespace,
_EXCLUDED_PATHS),
(CheckChangeHasTestField, _EXCLUDED_PATHS),
(CheckAndShowLicense, _EXCLUDED_PATHS),
(input_api.canned_checks.CheckChangeHasNoTabs,
_EXCLUDED_PATHS + _TAB_OK_PATHS)]
def MakeUploadChecklist(input_api):
return [(CheckChangeHasBugField, _EXCLUDED_PATHS)]
def MakeCommitChecklist(input_api):
return [(CheckChangeHasMandatoryBugField, _EXCLUDED_PATHS),
(CheckTreeIsOpen, _EXCLUDED_PATHS),
(CheckBuildbotPendingBuilds, _EXCLUDED_PATHS)]
def CheckChangeOnUpload(input_api, output_api):
"""On upload we check against the common and upload lists."""
return RunChecklist(input_api,
output_api,
MakeCommonChecklist(input_api) +
MakeUploadChecklist(input_api))
def CheckChangeOnCommit(input_api, output_api):
"""On commit we check against the common and commit lists."""
return RunChecklist(input_api,
output_api,
MakeCommonChecklist(input_api) +
MakeCommitChecklist(input_api))
def GetPreferredTrySlaves():
return ['ChromiumOS x86']