OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """Top-level presubmit script for Chromium OS. |
| 6 |
| 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
| 8 for more details about the presubmit API built into gcl and git cl. |
| 9 """ |
| 10 |
| 11 import re |
| 12 |
| 13 _EXCLUDED_PATHS = ( |
| 14 r"^inherit-review-settings-ok$", |
| 15 r".*[\\\/]debian[\\\/]rules$", |
| 16 ) |
| 17 |
| 18 # These match files that should contain tabs as indentation. |
| 19 _TAB_OK_PATHS = ( |
| 20 r"/src/third_party/kernel/", |
| 21 r"/src/third_party/kernel-next/", |
| 22 r"/src/third_party/u-boot/", |
| 23 r"/src/third_party/u-boot-next/", |
| 24 r".*\.ebuild$", |
| 25 r".*\.eclass$", |
| 26 ) |
| 27 |
| 28 # These match files that are part of out "next" developemnt flow and as such |
| 29 # do not require a valid BUG= field to commit, but it's still a good idea. |
| 30 _NEXT_PATHS = ( |
| 31 r"/src/third_party/kernel-next", |
| 32 r"/src/third_party/u-boot-next", |
| 33 ) |
| 34 |
| 35 _LICENSE_HEADER = ( |
| 36 r".*? Copyright \(c\) 20[-0-9]{2,7} The Chromium OS Authors\. All rights " |
| 37 r"reserved\." "\n" |
| 38 r".*? Use of this source code is governed by a BSD-style license that can " |
| 39 "be\n" |
| 40 r".*? found in the LICENSE file\." |
| 41 "\n" |
| 42 ) |
| 43 |
| 44 |
| 45 def CheckAndShowLicense(input_api, output_api, source_file_filter=None): |
| 46 """Check that the source files have a valid License header. |
| 47 |
| 48 The license header must matches our template. If not also show the |
| 49 header that should have been used. |
| 50 |
| 51 """ |
| 52 results = [] |
| 53 license_check = input_api.canned_checks.CheckLicense( |
| 54 input_api, output_api, _LICENSE_HEADER, source_file_filter) |
| 55 results.extend(license_check) |
| 56 if license_check: |
| 57 results.extend([output_api.PresubmitNotifyResult( |
| 58 "License header should match the following:", |
| 59 long_text=_LICENSE_HEADER)]) |
| 60 return results |
| 61 |
| 62 |
| 63 def CheckChangeHasMandatoryBugField(input_api, |
| 64 output_api, |
| 65 source_file_filter=None): |
| 66 """Check that the commit contains a valid BUG= field.""" |
| 67 msg = ('Changelist must reference a bug number using BUG=\n' |
| 68 'For example, BUG=chromium-os:8205\n' |
| 69 'BUG=none is not allowed.') |
| 70 |
| 71 if (not input_api.AffectedSourceFiles(source_file_filter) or |
| 72 (input_api.change.BUG and re.search(r"\d", input_api.change.BUG))): |
| 73 return [] |
| 74 else: |
| 75 return [output_api.PresubmitError(msg)] |
| 76 |
| 77 |
| 78 def CheckChangeHasBugField(input_api, output_api, source_file_filter=None): |
| 79 # This function is required because the canned BugField check doesn't |
| 80 # take a source filter. |
| 81 return input_api.canned_checks.CheckChangeHasBugField(input_api, |
| 82 output_api) |
| 83 |
| 84 |
| 85 def CheckChangeHasTestField(input_api, output_api, source_file_filter=None): |
| 86 # This function is required because the canned TestField check doesn't |
| 87 # take a source filter. |
| 88 return input_api.canned_checks.CheckChangeHasTestField(input_api, |
| 89 output_api) |
| 90 |
| 91 |
| 92 def CheckTreeIsOpen(input_api, output_api, source_file_filter=None): |
| 93 """Make sure the tree is 'open'. If not, don't submit.""" |
| 94 return input_api.canned_checks.CheckTreeIsOpen( |
| 95 input_api, |
| 96 output_api, |
| 97 'http://chromiumos-status.appspot.com/current?format=raw', |
| 98 '.*closed.*') |
| 99 |
| 100 |
| 101 def CheckBuildbotPendingBuilds(input_api, output_api, source_file_filter=None): |
| 102 """Check to see if there's a backlog on the pending CL queue""" |
| 103 return input_api.canned_checks.CheckBuildbotPendingBuilds( |
| 104 input_api, |
| 105 output_api, |
| 106 'http://build.chromium.org/buildbot/chromiumos/json/builders?filter=1', |
| 107 6, |
| 108 []) |
| 109 |
| 110 |
| 111 def FilterAbsoluteSourceFile(input_api, affected_file, white_list, black_list): |
| 112 """Filters out files that aren't considered "source file". |
| 113 |
| 114 The lists will be compiled as regular expression and |
| 115 AffectedFile.AbsoluteLocalPath() needs to pass both list. |
| 116 |
| 117 Note: This function was coppied from presubmit_support.py and modified to |
| 118 check against (AbsoluteLocalPath - PresubmitLocalPath) instead of LocalPath |
| 119 because LocalPath doesn't contain enough information to disambiguate kernel, |
| 120 u-boot and -next files from the rest of ChromiumOS. |
| 121 |
| 122 """ |
| 123 presubmit_local_path = input_api.PresubmitLocalPath() |
| 124 |
| 125 def RelativePath(affected_file): |
| 126 absolute_local_path = affected_file.AbsoluteLocalPath() |
| 127 |
| 128 assert absolute_local_path.startswith(presubmit_local_path) |
| 129 return absolute_local_path[len(presubmit_local_path):] |
| 130 |
| 131 def Find(relative_path, items): |
| 132 for item in items: |
| 133 if re.match(item, relative_path): |
| 134 return True |
| 135 |
| 136 return False |
| 137 |
| 138 relative_path = RelativePath(affected_file) |
| 139 |
| 140 return (Find(relative_path, white_list) and |
| 141 not Find(relative_path, black_list)) |
| 142 |
| 143 def RunChecklist(input_api, output_api, checklist): |
| 144 """Run through a set of checks provided in a checklist. |
| 145 |
| 146 The checklist is a list of tuples, each of which contains the check to run |
| 147 and a list of regular expressions of paths to ignore for this check |
| 148 |
| 149 """ |
| 150 results = [] |
| 151 |
| 152 for check, paths in checklist: |
| 153 white_list = input_api.DEFAULT_WHITE_LIST |
| 154 |
| 155 # Construct a black list from the DEFAULT_BLACK_LIST supplied by |
| 156 # depot_tools and the paths that this check should not be applied to. |
| 157 # |
| 158 # We also remove the third_party rule here because our paterns are |
| 159 # matching against the entire path from the root of the ChromiumOS |
| 160 # project. We use the rooted paths because we want to be able to apply |
| 161 # some of the presubmit checks to things like the kernel and u-boot that |
| 162 # live in the third_party directory. |
| 163 black_list = list(input_api.DEFAULT_BLACK_LIST) |
| 164 black_list.remove(r".*\bthird_party[\\\/].*") |
| 165 black_list.extend(paths) |
| 166 sources = lambda path: FilterAbsoluteSourceFile(input_api, |
| 167 path, |
| 168 white_list, |
| 169 black_list) |
| 170 results.extend(check(input_api, output_api, source_file_filter=sources)) |
| 171 |
| 172 return results |
| 173 |
| 174 |
| 175 def MakeCommonChecklist(input_api): |
| 176 return [(input_api.canned_checks.CheckLongLines, _EXCLUDED_PATHS), |
| 177 (input_api.canned_checks.CheckChangeHasNoStrayWhitespace, |
| 178 _EXCLUDED_PATHS), |
| 179 (CheckChangeHasTestField, _EXCLUDED_PATHS), |
| 180 (CheckAndShowLicense, _EXCLUDED_PATHS), |
| 181 (input_api.canned_checks.CheckChangeHasNoTabs, |
| 182 _EXCLUDED_PATHS + _TAB_OK_PATHS)] |
| 183 |
| 184 |
| 185 def MakeUploadChecklist(input_api): |
| 186 return [(CheckChangeHasBugField, _EXCLUDED_PATHS)] |
| 187 |
| 188 |
| 189 def MakeCommitChecklist(input_api): |
| 190 return [(CheckChangeHasMandatoryBugField, _EXCLUDED_PATHS + _NEXT_PATHS), |
| 191 (CheckTreeIsOpen, _EXCLUDED_PATHS), |
| 192 (CheckBuildbotPendingBuilds, _EXCLUDED_PATHS)] |
| 193 |
| 194 |
| 195 def CheckChangeOnUpload(input_api, output_api): |
| 196 """On upload we check against the common and upload lists.""" |
| 197 return RunChecklist(input_api, |
| 198 output_api, |
| 199 MakeCommonChecklist(input_api) + |
| 200 MakeUploadChecklist(input_api)) |
| 201 |
| 202 |
| 203 def CheckChangeOnCommit(input_api, output_api): |
| 204 """On commit we check against the common and commit lists.""" |
| 205 return RunChecklist(input_api, |
| 206 output_api, |
| 207 MakeCommonChecklist(input_api) + |
| 208 MakeCommitChecklist(input_api)) |
| 209 |
| 210 |
| 211 def GetPreferredTrySlaves(): |
| 212 return ['ChromiumOS x86'] |
OLD | NEW |