blob: 819f54b5a069cc0027857c2a88d781c724b45fc9 [file] [log] [blame]
Anush Elangovan44fc81e2010-12-10 10:42:16 -08001# 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
7See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8for more details about the presubmit API built into gcl and git cl.
9"""
10
11import 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
45def 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
63def 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
78def 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
85def 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
92def 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
101def 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,
bradnelsone512a3b2010-12-15 15:25:39 -0800106 'http://build.chromium.org/p/chromiumos/json/builders?filter=1',
Anush Elangovan44fc81e2010-12-10 10:42:16 -0800107 6,
108 [])
109
110
111def 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
143def 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
175def 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
185def MakeUploadChecklist(input_api):
186 return [(CheckChangeHasBugField, _EXCLUDED_PATHS)]
187
188
189def MakeCommitChecklist(input_api):
190 return [(CheckChangeHasMandatoryBugField, _EXCLUDED_PATHS + _NEXT_PATHS),
191 (CheckTreeIsOpen, _EXCLUDED_PATHS),
192 (CheckBuildbotPendingBuilds, _EXCLUDED_PATHS)]
193
194
195def 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
203def 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
211def GetPreferredTrySlaves():
212 return ['ChromiumOS x86']