blob: fde5a12f590ee156633047c944e71ceb546280b9 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# 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.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
[email protected]4306417642009-06-11 00:33:4026)
[email protected]ca8d1982009-02-19 16:33:1227
wnwenbdc444e2016-05-25 13:44:1528
jochen9ea8fdbc2014-09-25 13:21:3529# The NetscapePlugIn library is excluded from pan-project as it will soon
30# be deleted together with the rest of the NPAPI and it's not worthwhile to
31# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3832_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3233 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3834)
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Fragment of a regular expression that matches C++ and Objective-C++
38# implementation files.
39_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
40
wnwenbdc444e2016-05-25 13:44:1541
[email protected]06e6d0ff2012-12-11 01:36:4442# Regular expression that matches code only used for test binaries
43# (best effort).
44_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3247 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1248 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4449 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4950 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0551 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4952 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4453 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4954 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d1982009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
148)
149
150
151_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20152 # Make sure that gtest's FRIEND_TEST() macro is not used; the
153 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30154 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'FRIEND_TEST(',
157 (
[email protected]e3c945502012-06-26 20:01:49158 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20159 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
160 ),
161 False,
[email protected]7345da02012-11-27 14:31:49162 (),
[email protected]23e6cbc2012-06-16 18:51:20163 ),
164 (
165 'ScopedAllowIO',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'New code should not use ScopedAllowIO. Post a task to the blocking',
168 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20169 ),
[email protected]e3c945502012-06-26 20:01:49170 True,
[email protected]7345da02012-11-27 14:31:49171 (
nyad2c548b2015-12-09 03:22:32172 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10173 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49174 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22175 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31176 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51177 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
178 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09179 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49180 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
181 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25182 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41183 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
184 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25185 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48186 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
187 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01188 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25189 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
190 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
191 r"embedded_test_server\.cc$",
192 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
193 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54194 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53195 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
196 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45197 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
198 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
199 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
200 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
201 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49202 ),
[email protected]23e6cbc2012-06-16 18:51:20203 ),
[email protected]52657f62013-05-20 05:30:31204 (
tomhudsone2c14d552016-05-26 17:07:46205 'setMatrixClip',
206 (
207 'Overriding setMatrixClip() is prohibited; ',
208 'the base function is deprecated. ',
209 ),
210 True,
211 (),
212 ),
213 (
[email protected]52657f62013-05-20 05:30:31214 'SkRefPtr',
215 (
216 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22217 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31218 ),
219 True,
220 (),
221 ),
222 (
223 'SkAutoRef',
224 (
225 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22226 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31227 ),
228 True,
229 (),
230 ),
231 (
232 'SkAutoTUnref',
233 (
234 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22235 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31236 ),
237 True,
238 (),
239 ),
240 (
241 'SkAutoUnref',
242 (
243 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
244 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22245 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31246 ),
247 True,
248 (),
249 ),
[email protected]d89eec82013-12-03 14:10:59250 (
251 r'/HANDLE_EINTR\(.*close',
252 (
253 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
254 'descriptor will be closed, and it is incorrect to retry the close.',
255 'Either call close directly and ignore its return value, or wrap close',
256 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
257 ),
258 True,
259 (),
260 ),
261 (
262 r'/IGNORE_EINTR\((?!.*close)',
263 (
264 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
265 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
266 ),
267 True,
268 (
269 # Files that #define IGNORE_EINTR.
270 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
271 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
272 ),
273 ),
[email protected]ec5b3f02014-04-04 18:43:43274 (
275 r'/v8::Extension\(',
276 (
277 'Do not introduce new v8::Extensions into the code base, use',
278 'gin::Wrappable instead. See http://crbug.com/334679',
279 ),
280 True,
[email protected]f55c90ee62014-04-12 00:50:03281 (
joaodasilva718f87672014-08-30 09:25:49282 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03283 ),
[email protected]ec5b3f02014-04-04 18:43:43284 ),
skyostilf9469f72015-04-20 10:38:52285 (
jame2d1a952016-04-02 00:27:10286 '#pragma comment(lib,',
287 (
288 'Specify libraries to link with in build files and not in the source.',
289 ),
290 True,
291 (),
292 ),
[email protected]127f18ec2012-06-16 05:05:59293)
294
wnwenbdc444e2016-05-25 13:44:15295
mlamouria82272622014-09-16 18:45:04296_IPC_ENUM_TRAITS_DEPRECATED = (
297 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
298 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
299
[email protected]127f18ec2012-06-16 05:05:59300
[email protected]b00342e7f2013-03-26 16:21:54301_VALID_OS_MACROS = (
302 # Please keep sorted.
303 'OS_ANDROID',
304 'OS_BSD',
305 'OS_CAT', # For testing.
306 'OS_CHROMEOS',
307 'OS_FREEBSD',
308 'OS_IOS',
309 'OS_LINUX',
310 'OS_MACOSX',
311 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21312 'OS_NACL_NONSFI',
313 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12314 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54315 'OS_OPENBSD',
316 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37317 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54318 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54319 'OS_WIN',
320)
321
322
agrievef32bcc72016-04-04 14:57:40323_ANDROID_SPECIFIC_PYDEPS_FILES = [
324 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19325 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40326]
327
wnwenbdc444e2016-05-25 13:44:15328
agrievef32bcc72016-04-04 14:57:40329_GENERIC_PYDEPS_FILES = [
330 'build/secondary/tools/swarming_client/isolate.pydeps',
331]
332
wnwenbdc444e2016-05-25 13:44:15333
agrievef32bcc72016-04-04 14:57:40334_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
335
336
[email protected]55459852011-08-10 15:17:19337def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
338 """Attempts to prevent use of functions intended only for testing in
339 non-testing code. For now this is just a best-effort implementation
340 that ignores header files and may have some false positives. A
341 better implementation would probably need a proper C++ parser.
342 """
343 # We only scan .cc files and the like, as the declaration of
344 # for-testing functions in header files are hard to distinguish from
345 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44346 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19347
jochenc0d4808c2015-07-27 09:25:42348 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19349 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09350 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19351 exclusion_pattern = input_api.re.compile(
352 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
353 base_function_pattern, base_function_pattern))
354
355 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44356 black_list = (_EXCLUDED_PATHS +
357 _TEST_CODE_EXCLUDED_PATHS +
358 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19359 return input_api.FilterSourceFile(
360 affected_file,
361 white_list=(file_inclusion_pattern, ),
362 black_list=black_list)
363
364 problems = []
365 for f in input_api.AffectedSourceFiles(FilterFile):
366 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24367 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03368 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46369 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03370 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19371 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03372 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19373
374 if problems:
[email protected]f7051d52013-04-02 18:31:42375 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03376 else:
377 return []
[email protected]55459852011-08-10 15:17:19378
379
[email protected]10689ca2011-09-02 02:31:54380def _CheckNoIOStreamInHeaders(input_api, output_api):
381 """Checks to make sure no .h files include <iostream>."""
382 files = []
383 pattern = input_api.re.compile(r'^#include\s*<iostream>',
384 input_api.re.MULTILINE)
385 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
386 if not f.LocalPath().endswith('.h'):
387 continue
388 contents = input_api.ReadFile(f)
389 if pattern.search(contents):
390 files.append(f)
391
392 if len(files):
yolandyandaabc6d2016-04-18 18:29:39393 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06394 'Do not #include <iostream> in header files, since it inserts static '
395 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54396 '#include <ostream>. See http://crbug.com/94794',
397 files) ]
398 return []
399
400
[email protected]72df4e782012-06-21 16:28:18401def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52402 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18403 problems = []
404 for f in input_api.AffectedFiles():
405 if (not f.LocalPath().endswith(('.cc', '.mm'))):
406 continue
407
408 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04409 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18410 problems.append(' %s:%d' % (f.LocalPath(), line_num))
411
412 if not problems:
413 return []
414 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
415 '\n'.join(problems))]
416
417
danakj61c1aa22015-10-26 19:55:52418def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
419 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
420 errors = []
421 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
422 input_api.re.MULTILINE)
423 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
424 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
425 continue
426 for lnum, line in f.ChangedContents():
427 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17428 errors.append(output_api.PresubmitError(
429 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
430 'DCHECK_IS_ON()", not forgetting the braces.')
431 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52432 return errors
433
434
mcasasb7440c282015-02-04 14:52:19435def _FindHistogramNameInLine(histogram_name, line):
436 """Tries to find a histogram name or prefix in a line."""
437 if not "affected-histogram" in line:
438 return histogram_name in line
439 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
440 # the histogram_name.
441 if not '"' in line:
442 return False
443 histogram_prefix = line.split('\"')[1]
444 return histogram_prefix in histogram_name
445
446
447def _CheckUmaHistogramChanges(input_api, output_api):
448 """Check that UMA histogram names in touched lines can still be found in other
449 lines of the patch or in histograms.xml. Note that this check would not catch
450 the reverse: changes in histograms.xml not matched in the code itself."""
451 touched_histograms = []
452 histograms_xml_modifications = []
453 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
454 for f in input_api.AffectedFiles():
455 # If histograms.xml itself is modified, keep the modified lines for later.
456 if f.LocalPath().endswith(('histograms.xml')):
457 histograms_xml_modifications = f.ChangedContents()
458 continue
459 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
460 continue
461 for line_num, line in f.ChangedContents():
462 found = pattern.search(line)
463 if found:
464 touched_histograms.append([found.group(1), f, line_num])
465
466 # Search for the touched histogram names in the local modifications to
467 # histograms.xml, and, if not found, on the base histograms.xml file.
468 unmatched_histograms = []
469 for histogram_info in touched_histograms:
470 histogram_name_found = False
471 for line_num, line in histograms_xml_modifications:
472 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
473 if histogram_name_found:
474 break
475 if not histogram_name_found:
476 unmatched_histograms.append(histogram_info)
477
eromanb90c82e7e32015-04-01 15:13:49478 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19479 problems = []
480 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49481 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19482 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45483 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19484 histogram_name_found = False
485 for line in histograms_xml:
486 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
487 if histogram_name_found:
488 break
489 if not histogram_name_found:
490 problems.append(' [%s:%d] %s' %
491 (f.LocalPath(), line_num, histogram_name))
492
493 if not problems:
494 return []
495 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
496 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49497 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19498
wnwenbdc444e2016-05-25 13:44:15499
yolandyandaabc6d2016-04-18 18:29:39500def _CheckFlakyTestUsage(input_api, output_api):
501 """Check that FlakyTest annotation is our own instead of the android one"""
502 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
503 files = []
504 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
505 if f.LocalPath().endswith('Test.java'):
506 if pattern.search(input_api.ReadFile(f)):
507 files.append(f)
508 if len(files):
509 return [output_api.PresubmitError(
510 'Use org.chromium.base.test.util.FlakyTest instead of '
511 'android.test.FlakyTest',
512 files)]
513 return []
mcasasb7440c282015-02-04 14:52:19514
wnwenbdc444e2016-05-25 13:44:15515
[email protected]8ea5d4b2011-09-13 21:49:22516def _CheckNoNewWStrings(input_api, output_api):
517 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27518 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22519 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20520 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57521 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34522 '/win/' in f.LocalPath() or
523 'chrome_elf' in f.LocalPath() or
524 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20525 continue
[email protected]8ea5d4b2011-09-13 21:49:22526
[email protected]a11dbe9b2012-08-07 01:32:58527 allowWString = False
[email protected]b5c24292011-11-28 14:38:20528 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58529 if 'presubmit: allow wstring' in line:
530 allowWString = True
531 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27532 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58533 allowWString = False
534 else:
535 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22536
[email protected]55463aa62011-10-12 00:48:27537 if not problems:
538 return []
539 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58540 ' If you are calling a cross-platform API that accepts a wstring, '
541 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27542 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22543
544
[email protected]2a8ac9c2011-10-19 17:20:44545def _CheckNoDEPSGIT(input_api, output_api):
546 """Make sure .DEPS.git is never modified manually."""
547 if any(f.LocalPath().endswith('.DEPS.git') for f in
548 input_api.AffectedFiles()):
549 return [output_api.PresubmitError(
550 'Never commit changes to .DEPS.git. This file is maintained by an\n'
551 'automated system based on what\'s in DEPS and your changes will be\n'
552 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34553 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code#Rolling_DEPS\n'
[email protected]2a8ac9c2011-10-19 17:20:44554 'for more information')]
555 return []
556
557
tandriief664692014-09-23 14:51:47558def _CheckValidHostsInDEPS(input_api, output_api):
559 """Checks that DEPS file deps are from allowed_hosts."""
560 # Run only if DEPS file has been modified to annoy fewer bystanders.
561 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
562 return []
563 # Outsource work to gclient verify
564 try:
565 input_api.subprocess.check_output(['gclient', 'verify'])
566 return []
567 except input_api.subprocess.CalledProcessError, error:
568 return [output_api.PresubmitError(
569 'DEPS file must have only git dependencies.',
570 long_text=error.output)]
571
572
[email protected]127f18ec2012-06-16 05:05:59573def _CheckNoBannedFunctions(input_api, output_api):
574 """Make sure that banned functions are not used."""
575 warnings = []
576 errors = []
577
wnwenbdc444e2016-05-25 13:44:15578 def IsBlacklisted(affected_file, blacklist):
579 local_path = affected_file.LocalPath()
580 for item in blacklist:
581 if input_api.re.match(item, local_path):
582 return True
583 return False
584
585 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
586 matched = False
587 if func_name[0:1] == '/':
588 regex = func_name[1:]
589 if input_api.re.search(regex, line):
590 matched = True
591 elif func_name in line:
dchenge07de812016-06-20 19:27:17592 matched = True
wnwenbdc444e2016-05-25 13:44:15593 if matched:
dchenge07de812016-06-20 19:27:17594 problems = warnings
wnwenbdc444e2016-05-25 13:44:15595 if error:
dchenge07de812016-06-20 19:27:17596 problems = errors
wnwenbdc444e2016-05-25 13:44:15597 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
598 for message_line in message:
599 problems.append(' %s' % message_line)
600
[email protected]127f18ec2012-06-16 05:05:59601 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
602 for f in input_api.AffectedFiles(file_filter=file_filter):
603 for line_num, line in f.ChangedContents():
604 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15605 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59606
607 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
608 for f in input_api.AffectedFiles(file_filter=file_filter):
609 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49610 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49611 if IsBlacklisted(f, excluded_paths):
612 continue
wnwenbdc444e2016-05-25 13:44:15613 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59614
615 result = []
616 if (warnings):
617 result.append(output_api.PresubmitPromptWarning(
618 'Banned functions were used.\n' + '\n'.join(warnings)))
619 if (errors):
620 result.append(output_api.PresubmitError(
621 'Banned functions were used.\n' + '\n'.join(errors)))
622 return result
623
624
[email protected]6c063c62012-07-11 19:11:06625def _CheckNoPragmaOnce(input_api, output_api):
626 """Make sure that banned functions are not used."""
627 files = []
628 pattern = input_api.re.compile(r'^#pragma\s+once',
629 input_api.re.MULTILINE)
630 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
631 if not f.LocalPath().endswith('.h'):
632 continue
633 contents = input_api.ReadFile(f)
634 if pattern.search(contents):
635 files.append(f)
636
637 if files:
638 return [output_api.PresubmitError(
639 'Do not use #pragma once in header files.\n'
640 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
641 files)]
642 return []
643
[email protected]127f18ec2012-06-16 05:05:59644
[email protected]e7479052012-09-19 00:26:12645def _CheckNoTrinaryTrueFalse(input_api, output_api):
646 """Checks to make sure we don't introduce use of foo ? true : false."""
647 problems = []
648 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
649 for f in input_api.AffectedFiles():
650 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
651 continue
652
653 for line_num, line in f.ChangedContents():
654 if pattern.match(line):
655 problems.append(' %s:%d' % (f.LocalPath(), line_num))
656
657 if not problems:
658 return []
659 return [output_api.PresubmitPromptWarning(
660 'Please consider avoiding the "? true : false" pattern if possible.\n' +
661 '\n'.join(problems))]
662
663
[email protected]55f9f382012-07-31 11:02:18664def _CheckUnwantedDependencies(input_api, output_api):
665 """Runs checkdeps on #include statements added in this
666 change. Breaking - rules is an error, breaking ! rules is a
667 warning.
668 """
mohan.reddyf21db962014-10-16 12:26:47669 import sys
[email protected]55f9f382012-07-31 11:02:18670 # We need to wait until we have an input_api object and use this
671 # roundabout construct to import checkdeps because this file is
672 # eval-ed and thus doesn't have __file__.
673 original_sys_path = sys.path
674 try:
675 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47676 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18677 import checkdeps
678 from cpp_checker import CppChecker
679 from rules import Rule
680 finally:
681 # Restore sys.path to what it was before.
682 sys.path = original_sys_path
683
684 added_includes = []
685 for f in input_api.AffectedFiles():
686 if not CppChecker.IsCppFile(f.LocalPath()):
687 continue
688
689 changed_lines = [line for line_num, line in f.ChangedContents()]
690 added_includes.append([f.LocalPath(), changed_lines])
691
[email protected]26385172013-05-09 23:11:35692 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18693
694 error_descriptions = []
695 warning_descriptions = []
696 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
697 added_includes):
698 description_with_path = '%s\n %s' % (path, rule_description)
699 if rule_type == Rule.DISALLOW:
700 error_descriptions.append(description_with_path)
701 else:
702 warning_descriptions.append(description_with_path)
703
704 results = []
705 if error_descriptions:
706 results.append(output_api.PresubmitError(
707 'You added one or more #includes that violate checkdeps rules.',
708 error_descriptions))
709 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42710 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18711 'You added one or more #includes of files that are temporarily\n'
712 'allowed but being removed. Can you avoid introducing the\n'
713 '#include? See relevant DEPS file(s) for details and contacts.',
714 warning_descriptions))
715 return results
716
717
[email protected]fbcafe5a2012-08-08 15:31:22718def _CheckFilePermissions(input_api, output_api):
719 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15720 if input_api.platform == 'win32':
721 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29722 checkperms_tool = input_api.os_path.join(
723 input_api.PresubmitLocalPath(),
724 'tools', 'checkperms', 'checkperms.py')
725 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47726 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22727 for f in input_api.AffectedFiles():
728 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11729 try:
730 input_api.subprocess.check_output(args)
731 return []
732 except input_api.subprocess.CalledProcessError as error:
733 return [output_api.PresubmitError(
734 'checkperms.py failed:',
735 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22736
737
[email protected]c8278b32012-10-30 20:35:49738def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
739 """Makes sure we don't include ui/aura/window_property.h
740 in header files.
741 """
742 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
743 errors = []
744 for f in input_api.AffectedFiles():
745 if not f.LocalPath().endswith('.h'):
746 continue
747 for line_num, line in f.ChangedContents():
748 if pattern.match(line):
749 errors.append(' %s:%d' % (f.LocalPath(), line_num))
750
751 results = []
752 if errors:
753 results.append(output_api.PresubmitError(
754 'Header files should not include ui/aura/window_property.h', errors))
755 return results
756
757
[email protected]cf9b78f2012-11-14 11:40:28758def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
759 """Checks that the lines in scope occur in the right order.
760
761 1. C system files in alphabetical order
762 2. C++ system files in alphabetical order
763 3. Project's .h files
764 """
765
766 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
767 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
768 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
769
770 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
771
772 state = C_SYSTEM_INCLUDES
773
774 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57775 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28776 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55777 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28778 for line_num, line in scope:
779 if c_system_include_pattern.match(line):
780 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55781 problem_linenums.append((line_num, previous_line_num,
782 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28783 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55784 problem_linenums.append((line_num, previous_line_num,
785 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28786 elif cpp_system_include_pattern.match(line):
787 if state == C_SYSTEM_INCLUDES:
788 state = CPP_SYSTEM_INCLUDES
789 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55790 problem_linenums.append((line_num, previous_line_num,
791 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28792 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55793 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28794 elif custom_include_pattern.match(line):
795 if state != CUSTOM_INCLUDES:
796 state = CUSTOM_INCLUDES
797 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55798 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28799 else:
brucedawson70fadb02015-06-30 17:47:55800 problem_linenums.append((line_num, previous_line_num,
801 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28802 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57803 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28804
805 warnings = []
brucedawson70fadb02015-06-30 17:47:55806 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57807 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55808 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28809 return warnings
810
811
[email protected]ac294a12012-12-06 16:38:43812def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28813 """Checks the #include order for the given file f."""
814
[email protected]2299dcf2012-11-15 19:56:24815 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30816 # Exclude the following includes from the check:
817 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
818 # specific order.
819 # 2) <atlbase.h>, "build/build_config.h"
820 excluded_include_pattern = input_api.re.compile(
821 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24822 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33823 # Match the final or penultimate token if it is xxxtest so we can ignore it
824 # when considering the special first include.
825 test_file_tag_pattern = input_api.re.compile(
826 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11827 if_pattern = input_api.re.compile(
828 r'\s*#\s*(if|elif|else|endif|define|undef).*')
829 # Some files need specialized order of includes; exclude such files from this
830 # check.
831 uncheckable_includes_pattern = input_api.re.compile(
832 r'\s*#include '
833 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28834
835 contents = f.NewContents()
836 warnings = []
837 line_num = 0
838
[email protected]ac294a12012-12-06 16:38:43839 # Handle the special first include. If the first include file is
840 # some/path/file.h, the corresponding including file can be some/path/file.cc,
841 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
842 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33843 # If the included file is some/path/file_platform.h the including file could
844 # also be some/path/file_xxxtest_platform.h.
845 including_file_base_name = test_file_tag_pattern.sub(
846 '', input_api.os_path.basename(f.LocalPath()))
847
[email protected]ac294a12012-12-06 16:38:43848 for line in contents:
849 line_num += 1
850 if system_include_pattern.match(line):
851 # No special first include -> process the line again along with normal
852 # includes.
853 line_num -= 1
854 break
855 match = custom_include_pattern.match(line)
856 if match:
857 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33858 header_basename = test_file_tag_pattern.sub(
859 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
860
861 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24862 # No special first include -> process the line again along with normal
863 # includes.
864 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43865 break
[email protected]cf9b78f2012-11-14 11:40:28866
867 # Split into scopes: Each region between #if and #endif is its own scope.
868 scopes = []
869 current_scope = []
870 for line in contents[line_num:]:
871 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11872 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54873 continue
[email protected]2309b0fa02012-11-16 12:18:27874 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28875 scopes.append(current_scope)
876 current_scope = []
[email protected]962f117e2012-11-22 18:11:56877 elif ((system_include_pattern.match(line) or
878 custom_include_pattern.match(line)) and
879 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28880 current_scope.append((line_num, line))
881 scopes.append(current_scope)
882
883 for scope in scopes:
884 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
885 changed_linenums))
886 return warnings
887
888
889def _CheckIncludeOrder(input_api, output_api):
890 """Checks that the #include order is correct.
891
892 1. The corresponding header for source files.
893 2. C system files in alphabetical order
894 3. C++ system files in alphabetical order
895 4. Project's .h files in alphabetical order
896
[email protected]ac294a12012-12-06 16:38:43897 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
898 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28899 """
[email protected]e120b012014-08-15 19:08:35900 def FileFilterIncludeOrder(affected_file):
901 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
902 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28903
904 warnings = []
[email protected]e120b012014-08-15 19:08:35905 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08906 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43907 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
908 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28909
910 results = []
911 if warnings:
[email protected]f7051d52013-04-02 18:31:42912 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53913 warnings))
[email protected]cf9b78f2012-11-14 11:40:28914 return results
915
916
[email protected]70ca77752012-11-20 03:45:03917def _CheckForVersionControlConflictsInFile(input_api, f):
918 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
919 errors = []
920 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23921 if f.LocalPath().endswith('.md'):
922 # First-level headers in markdown look a lot like version control
923 # conflict markers. http://daringfireball.net/projects/markdown/basics
924 continue
[email protected]70ca77752012-11-20 03:45:03925 if pattern.match(line):
926 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
927 return errors
928
929
930def _CheckForVersionControlConflicts(input_api, output_api):
931 """Usually this is not intentional and will cause a compile failure."""
932 errors = []
933 for f in input_api.AffectedFiles():
934 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
935
936 results = []
937 if errors:
938 results.append(output_api.PresubmitError(
939 'Version control conflict markers found, please resolve.', errors))
940 return results
941
942
[email protected]06e6d0ff2012-12-11 01:36:44943def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
944 def FilterFile(affected_file):
945 """Filter function for use with input_api.AffectedSourceFiles,
946 below. This filters out everything except non-test files from
947 top-level directories that generally speaking should not hard-code
948 service URLs (e.g. src/android_webview/, src/content/ and others).
949 """
950 return input_api.FilterSourceFile(
951 affected_file,
[email protected]78bb39d62012-12-11 15:11:56952 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44953 black_list=(_EXCLUDED_PATHS +
954 _TEST_CODE_EXCLUDED_PATHS +
955 input_api.DEFAULT_BLACK_LIST))
956
reillyi38965732015-11-16 18:27:33957 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
958 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46959 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
960 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44961 problems = [] # items are (filename, line_number, line)
962 for f in input_api.AffectedSourceFiles(FilterFile):
963 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46964 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44965 problems.append((f.LocalPath(), line_num, line))
966
967 if problems:
[email protected]f7051d52013-04-02 18:31:42968 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44969 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58970 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44971 [' %s:%d: %s' % (
972 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03973 else:
974 return []
[email protected]06e6d0ff2012-12-11 01:36:44975
976
[email protected]d2530012013-01-25 16:39:27977def _CheckNoAbbreviationInPngFileName(input_api, output_api):
978 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31979 The native_client_sdk directory is excluded because it has auto-generated PNG
980 files for documentation.
[email protected]d2530012013-01-25 16:39:27981 """
[email protected]d2530012013-01-25 16:39:27982 errors = []
binji0dcdf342014-12-12 18:32:31983 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
984 black_list = (r'^native_client_sdk[\\\/]',)
985 file_filter = lambda f: input_api.FilterSourceFile(
986 f, white_list=white_list, black_list=black_list)
987 for f in input_api.AffectedFiles(include_deletes=False,
988 file_filter=file_filter):
989 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27990
991 results = []
992 if errors:
993 results.append(output_api.PresubmitError(
994 'The name of PNG files should not have abbreviations. \n'
995 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
996 'Contact [email protected] if you have questions.', errors))
997 return results
998
999
[email protected]14a6131c2014-01-08 01:15:411000def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081001 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411002 a set of DEPS entries that we should look up.
1003
1004 For a directory (rather than a specific filename) we fake a path to
1005 a specific filename by adding /DEPS. This is chosen as a file that
1006 will seldom or never be subject to per-file include_rules.
1007 """
[email protected]2b438d62013-11-14 17:54:141008 # We ignore deps entries on auto-generated directories.
1009 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081010
1011 # This pattern grabs the path without basename in the first
1012 # parentheses, and the basename (if present) in the second. It
1013 # relies on the simple heuristic that if there is a basename it will
1014 # be a header file ending in ".h".
1015 pattern = re.compile(
1016 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141017 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081018 for changed_line in changed_lines:
1019 m = pattern.match(changed_line)
1020 if m:
1021 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141022 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411023 if m.group(2):
1024 results.add('%s%s' % (path, m.group(2)))
1025 else:
1026 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081027 return results
1028
1029
[email protected]e871964c2013-05-13 14:14:551030def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1031 """When a dependency prefixed with + is added to a DEPS file, we
1032 want to make sure that the change is reviewed by an OWNER of the
1033 target file or directory, to avoid layering violations from being
1034 introduced. This check verifies that this happens.
1035 """
1036 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241037
1038 file_filter = lambda f: not input_api.re.match(
1039 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1040 for f in input_api.AffectedFiles(include_deletes=False,
1041 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551042 filename = input_api.os_path.basename(f.LocalPath())
1043 if filename == 'DEPS':
1044 changed_lines |= set(line.strip()
1045 for line_num, line
1046 in f.ChangedContents())
1047 if not changed_lines:
1048 return []
1049
[email protected]14a6131c2014-01-08 01:15:411050 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1051 changed_lines)
[email protected]e871964c2013-05-13 14:14:551052 if not virtual_depended_on_files:
1053 return []
1054
1055 if input_api.is_committing:
1056 if input_api.tbr:
1057 return [output_api.PresubmitNotifyResult(
1058 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271059 if input_api.dry_run:
1060 return [output_api.PresubmitNotifyResult(
1061 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551062 if not input_api.change.issue:
1063 return [output_api.PresubmitError(
1064 "DEPS approval by OWNERS check failed: this change has "
1065 "no Rietveld issue number, so we can't check it for approvals.")]
1066 output = output_api.PresubmitError
1067 else:
1068 output = output_api.PresubmitNotifyResult
1069
1070 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501071 owner_email, reviewers = (
1072 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1073 input_api,
1074 owners_db.email_regexp,
1075 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551076
1077 owner_email = owner_email or input_api.change.author_email
1078
[email protected]de4f7d22013-05-23 14:27:461079 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511080 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461081 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551082 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1083 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411084
1085 # We strip the /DEPS part that was added by
1086 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1087 # directory.
1088 def StripDeps(path):
1089 start_deps = path.rfind('/DEPS')
1090 if start_deps != -1:
1091 return path[:start_deps]
1092 else:
1093 return path
1094 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551095 for path in missing_files]
1096
1097 if unapproved_dependencies:
1098 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151099 output('You need LGTM from owners of depends-on paths in DEPS that were '
1100 'modified in this CL:\n %s' %
1101 '\n '.join(sorted(unapproved_dependencies)))]
1102 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1103 output_list.append(output(
1104 'Suggested missing target path OWNERS:\n %s' %
1105 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551106 return output_list
1107
1108 return []
1109
1110
[email protected]85218562013-11-22 07:41:401111def _CheckSpamLogging(input_api, output_api):
1112 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1113 black_list = (_EXCLUDED_PATHS +
1114 _TEST_CODE_EXCLUDED_PATHS +
1115 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501116 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191117 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481118 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461119 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121120 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1121 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581122 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161123 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031124 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151125 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1126 r"^chromecast[\\\/]",
1127 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311128 r"^components[\\\/]html_viewer[\\\/]"
1129 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461130 # TODO(peter): Remove this exception. https://crbug.com/534537
1131 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1132 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251133 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1134 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241135 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111136 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151137 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111138 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521139 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501140 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361141 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311142 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131143 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441144 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451145 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021146 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441147 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401148 source_file_filter = lambda x: input_api.FilterSourceFile(
1149 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1150
1151 log_info = []
1152 printf = []
1153
1154 for f in input_api.AffectedSourceFiles(source_file_filter):
1155 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471156 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401157 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471158 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131159 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371160
mohan.reddyf21db962014-10-16 12:26:471161 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371162 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471163 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401164 printf.append(f.LocalPath())
1165
1166 if log_info:
1167 return [output_api.PresubmitError(
1168 'These files spam the console log with LOG(INFO):',
1169 items=log_info)]
1170 if printf:
1171 return [output_api.PresubmitError(
1172 'These files spam the console log with printf/fprintf:',
1173 items=printf)]
1174 return []
1175
1176
[email protected]49aa76a2013-12-04 06:59:161177def _CheckForAnonymousVariables(input_api, output_api):
1178 """These types are all expected to hold locks while in scope and
1179 so should never be anonymous (which causes them to be immediately
1180 destroyed)."""
1181 they_who_must_be_named = [
1182 'base::AutoLock',
1183 'base::AutoReset',
1184 'base::AutoUnlock',
1185 'SkAutoAlphaRestore',
1186 'SkAutoBitmapShaderInstall',
1187 'SkAutoBlitterChoose',
1188 'SkAutoBounderCommit',
1189 'SkAutoCallProc',
1190 'SkAutoCanvasRestore',
1191 'SkAutoCommentBlock',
1192 'SkAutoDescriptor',
1193 'SkAutoDisableDirectionCheck',
1194 'SkAutoDisableOvalCheck',
1195 'SkAutoFree',
1196 'SkAutoGlyphCache',
1197 'SkAutoHDC',
1198 'SkAutoLockColors',
1199 'SkAutoLockPixels',
1200 'SkAutoMalloc',
1201 'SkAutoMaskFreeImage',
1202 'SkAutoMutexAcquire',
1203 'SkAutoPathBoundsUpdate',
1204 'SkAutoPDFRelease',
1205 'SkAutoRasterClipValidate',
1206 'SkAutoRef',
1207 'SkAutoTime',
1208 'SkAutoTrace',
1209 'SkAutoUnref',
1210 ]
1211 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1212 # bad: base::AutoLock(lock.get());
1213 # not bad: base::AutoLock lock(lock.get());
1214 bad_pattern = input_api.re.compile(anonymous)
1215 # good: new base::AutoLock(lock.get())
1216 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1217 errors = []
1218
1219 for f in input_api.AffectedFiles():
1220 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1221 continue
1222 for linenum, line in f.ChangedContents():
1223 if bad_pattern.search(line) and not good_pattern.search(line):
1224 errors.append('%s:%d' % (f.LocalPath(), linenum))
1225
1226 if errors:
1227 return [output_api.PresubmitError(
1228 'These lines create anonymous variables that need to be named:',
1229 items=errors)]
1230 return []
1231
1232
[email protected]5fe0f8742013-11-29 01:04:591233def _CheckCygwinShell(input_api, output_api):
1234 source_file_filter = lambda x: input_api.FilterSourceFile(
1235 x, white_list=(r'.+\.(gyp|gypi)$',))
1236 cygwin_shell = []
1237
1238 for f in input_api.AffectedSourceFiles(source_file_filter):
1239 for linenum, line in f.ChangedContents():
1240 if 'msvs_cygwin_shell' in line:
1241 cygwin_shell.append(f.LocalPath())
1242 break
1243
1244 if cygwin_shell:
1245 return [output_api.PresubmitError(
1246 'These files should not use msvs_cygwin_shell (the default is 0):',
1247 items=cygwin_shell)]
1248 return []
1249
[email protected]85218562013-11-22 07:41:401250
[email protected]999261d2014-03-03 20:08:081251def _CheckUserActionUpdate(input_api, output_api):
1252 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521253 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081254 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521255 # If actions.xml is already included in the changelist, the PRESUBMIT
1256 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081257 return []
1258
[email protected]999261d2014-03-03 20:08:081259 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1260 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521261 current_actions = None
[email protected]999261d2014-03-03 20:08:081262 for f in input_api.AffectedFiles(file_filter=file_filter):
1263 for line_num, line in f.ChangedContents():
1264 match = input_api.re.search(action_re, line)
1265 if match:
[email protected]2f92dec2014-03-07 19:21:521266 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1267 # loaded only once.
1268 if not current_actions:
1269 with open('tools/metrics/actions/actions.xml') as actions_f:
1270 current_actions = actions_f.read()
1271 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081272 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521273 action = 'name="{0}"'.format(action_name)
1274 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081275 return [output_api.PresubmitPromptWarning(
1276 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521277 'tools/metrics/actions/actions.xml. Please run '
1278 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081279 % (f.LocalPath(), line_num, action_name))]
1280 return []
1281
1282
[email protected]99171a92014-06-03 08:44:471283def _GetJSONParseError(input_api, filename, eat_comments=True):
1284 try:
1285 contents = input_api.ReadFile(filename)
1286 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131287 import sys
1288 original_sys_path = sys.path
1289 try:
1290 sys.path = sys.path + [input_api.os_path.join(
1291 input_api.PresubmitLocalPath(),
1292 'tools', 'json_comment_eater')]
1293 import json_comment_eater
1294 finally:
1295 sys.path = original_sys_path
1296 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471297
1298 input_api.json.loads(contents)
1299 except ValueError as e:
1300 return e
1301 return None
1302
1303
1304def _GetIDLParseError(input_api, filename):
1305 try:
1306 contents = input_api.ReadFile(filename)
1307 idl_schema = input_api.os_path.join(
1308 input_api.PresubmitLocalPath(),
1309 'tools', 'json_schema_compiler', 'idl_schema.py')
1310 process = input_api.subprocess.Popen(
1311 [input_api.python_executable, idl_schema],
1312 stdin=input_api.subprocess.PIPE,
1313 stdout=input_api.subprocess.PIPE,
1314 stderr=input_api.subprocess.PIPE,
1315 universal_newlines=True)
1316 (_, error) = process.communicate(input=contents)
1317 return error or None
1318 except ValueError as e:
1319 return e
1320
1321
1322def _CheckParseErrors(input_api, output_api):
1323 """Check that IDL and JSON files do not contain syntax errors."""
1324 actions = {
1325 '.idl': _GetIDLParseError,
1326 '.json': _GetJSONParseError,
1327 }
1328 # These paths contain test data and other known invalid JSON files.
1329 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491330 r'test[\\\/]data[\\\/]',
1331 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471332 ]
1333 # Most JSON files are preprocessed and support comments, but these do not.
1334 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491335 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471336 ]
1337 # Only run IDL checker on files in these directories.
1338 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491339 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1340 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471341 ]
1342
1343 def get_action(affected_file):
1344 filename = affected_file.LocalPath()
1345 return actions.get(input_api.os_path.splitext(filename)[1])
1346
1347 def MatchesFile(patterns, path):
1348 for pattern in patterns:
1349 if input_api.re.search(pattern, path):
1350 return True
1351 return False
1352
1353 def FilterFile(affected_file):
1354 action = get_action(affected_file)
1355 if not action:
1356 return False
1357 path = affected_file.LocalPath()
1358
1359 if MatchesFile(excluded_patterns, path):
1360 return False
1361
1362 if (action == _GetIDLParseError and
1363 not MatchesFile(idl_included_patterns, path)):
1364 return False
1365 return True
1366
1367 results = []
1368 for affected_file in input_api.AffectedFiles(
1369 file_filter=FilterFile, include_deletes=False):
1370 action = get_action(affected_file)
1371 kwargs = {}
1372 if (action == _GetJSONParseError and
1373 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1374 kwargs['eat_comments'] = False
1375 parse_error = action(input_api,
1376 affected_file.AbsoluteLocalPath(),
1377 **kwargs)
1378 if parse_error:
1379 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1380 (affected_file.LocalPath(), parse_error)))
1381 return results
1382
1383
[email protected]760deea2013-12-10 19:33:491384def _CheckJavaStyle(input_api, output_api):
1385 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471386 import sys
[email protected]760deea2013-12-10 19:33:491387 original_sys_path = sys.path
1388 try:
1389 sys.path = sys.path + [input_api.os_path.join(
1390 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1391 import checkstyle
1392 finally:
1393 # Restore sys.path to what it was before.
1394 sys.path = original_sys_path
1395
1396 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091397 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511398 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491399
1400
dchenge07de812016-06-20 19:27:171401def _CheckIpcOwners(input_api, output_api):
1402 """Checks that affected files involving IPC have an IPC OWNERS rule.
1403
1404 Whether or not a file affects IPC is determined by a simple whitelist of
1405 filename patterns."""
1406 file_patterns = [
1407 '*_messages.cc',
1408 '*_messages*.h',
1409 '*_param_traits*.*',
1410 '*.mojom',
1411 '*_struct_traits*.*',
1412 '*_type_converter*.*',
1413 # Blink uses a different file naming convention
1414 '*StructTraits*.*',
1415 '*TypeConverter*.*',
1416 ]
1417
1418 # Dictionary mapping an OWNERS file path to Patterns.
1419 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1420 # rules ) to a PatternEntry.
1421 # PatternEntry is a dictionary with two keys:
1422 # - 'files': the files that are matched by this pattern
1423 # - 'rules': the per-file rules needed for this pattern
1424 # For example, if we expect OWNERS file to contain rules for *.mojom and
1425 # *_struct_traits*.*, Patterns might look like this:
1426 # {
1427 # '*.mojom': {
1428 # 'files': ...,
1429 # 'rules': [
1430 # 'per-file *.mojom=set noparent',
1431 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1432 # ],
1433 # },
1434 # '*_struct_traits*.*': {
1435 # 'files': ...,
1436 # 'rules': [
1437 # 'per-file *_struct_traits*.*=set noparent',
1438 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1439 # ],
1440 # },
1441 # }
1442 to_check = {}
1443
1444 # Iterate through the affected files to see what we actually need to check
1445 # for. We should only nag patch authors about per-file rules if a file in that
1446 # directory would match that pattern. If a directory only contains *.mojom
1447 # files and no *_messages*.h files, we should only nag about rules for
1448 # *.mojom files.
rockot51249332016-06-23 16:32:251449 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171450 for pattern in file_patterns:
1451 if input_api.fnmatch.fnmatch(
1452 input_api.os_path.basename(f.LocalPath()), pattern):
1453 owners_file = input_api.os_path.join(
1454 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1455 if owners_file not in to_check:
1456 to_check[owners_file] = {}
1457 if pattern not in to_check[owners_file]:
1458 to_check[owners_file][pattern] = {
1459 'files': [],
1460 'rules': [
1461 'per-file %s=set noparent' % pattern,
1462 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1463 ]
1464 }
1465 to_check[owners_file][pattern]['files'].append(f)
1466 break
1467
1468 # Now go through the OWNERS files we collected, filtering out rules that are
1469 # already present in that OWNERS file.
1470 for owners_file, patterns in to_check.iteritems():
1471 try:
1472 with file(owners_file) as f:
1473 lines = set(f.read().splitlines())
1474 for entry in patterns.itervalues():
1475 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1476 ]
1477 except IOError:
1478 # No OWNERS file, so all the rules are definitely missing.
1479 continue
1480
1481 # All the remaining lines weren't found in OWNERS files, so emit an error.
1482 errors = []
1483 for owners_file, patterns in to_check.iteritems():
1484 missing_lines = []
1485 files = []
1486 for pattern, entry in patterns.iteritems():
1487 missing_lines.extend(entry['rules'])
1488 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1489 if missing_lines:
1490 errors.append(
1491 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1492 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1493
1494 results = []
1495 if errors:
vabrf5ce3bf92016-07-11 14:52:411496 if input_api.is_committing:
1497 output = output_api.PresubmitError
1498 else:
1499 output = output_api.PresubmitPromptWarning
1500 results.append(output(
dchenge07de812016-06-20 19:27:171501 'Found changes to IPC files without a security OWNER!',
1502 long_text='\n\n'.join(errors)))
1503
1504 return results
1505
1506
yzshend99f726a2016-07-25 21:44:231507def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1508 """Checks to make sure that all newly added mojom targets map array/map/string
1509 to STL (for chromium) or WTF (for blink) types.
1510 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1511 """
1512 files = []
1513 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1514 input_api.re.MULTILINE)
1515
1516 for f in input_api.AffectedFiles():
1517 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1518 continue
1519
1520 for _, line in f.ChangedContents():
1521 if pattern.search(line):
1522 files.append(f)
1523 break
1524
1525 if len(files):
1526 return [output_api.PresubmitError(
1527 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1528 'false. The mode is deprecated and will be removed soon.',
1529 files)]
1530 return []
1531
1532
dskiba88634f4e2015-08-14 23:03:291533def _CheckAndroidToastUsage(input_api, output_api):
1534 """Checks that code uses org.chromium.ui.widget.Toast instead of
1535 android.widget.Toast (Chromium Toast doesn't force hardware
1536 acceleration on low-end devices, saving memory).
1537 """
1538 toast_import_pattern = input_api.re.compile(
1539 r'^import android\.widget\.Toast;$')
1540
1541 errors = []
1542
1543 sources = lambda affected_file: input_api.FilterSourceFile(
1544 affected_file,
1545 black_list=(_EXCLUDED_PATHS +
1546 _TEST_CODE_EXCLUDED_PATHS +
1547 input_api.DEFAULT_BLACK_LIST +
1548 (r'^chromecast[\\\/].*',
1549 r'^remoting[\\\/].*')),
1550 white_list=(r'.*\.java$',))
1551
1552 for f in input_api.AffectedSourceFiles(sources):
1553 for line_num, line in f.ChangedContents():
1554 if toast_import_pattern.search(line):
1555 errors.append("%s:%d" % (f.LocalPath(), line_num))
1556
1557 results = []
1558
1559 if errors:
1560 results.append(output_api.PresubmitError(
1561 'android.widget.Toast usage is detected. Android toasts use hardware'
1562 ' acceleration, and can be\ncostly on low-end devices. Please use'
1563 ' org.chromium.ui.widget.Toast instead.\n'
1564 'Contact [email protected] if you have any questions.',
1565 errors))
1566
1567 return results
1568
1569
dgnaa68d5e2015-06-10 10:08:221570def _CheckAndroidCrLogUsage(input_api, output_api):
1571 """Checks that new logs using org.chromium.base.Log:
1572 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511573 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221574 """
pkotwicza1dd0b002016-05-16 14:41:041575
1576 # Do not check format of logs in //chrome/android/webapk because
1577 # //chrome/android/webapk cannot depend on //base
1578 cr_log_check_excluded_paths = [
1579 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1580 ]
1581
dgnaa68d5e2015-06-10 10:08:221582 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121583 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1584 class_in_base_pattern = input_api.re.compile(
1585 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1586 has_some_log_import_pattern = input_api.re.compile(
1587 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221588 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121589 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221590 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511591 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221592 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221593
Vincent Scheib16d7b272015-09-15 18:09:071594 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221595 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041596 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1597 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121598
dgnaa68d5e2015-06-10 10:08:221599 tag_decl_errors = []
1600 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121601 tag_errors = []
dgn38736db2015-09-18 19:20:511602 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121603 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221604
1605 for f in input_api.AffectedSourceFiles(sources):
1606 file_content = input_api.ReadFile(f)
1607 has_modified_logs = False
1608
1609 # Per line checks
dgn87d9fb62015-06-12 09:15:121610 if (cr_log_import_pattern.search(file_content) or
1611 (class_in_base_pattern.search(file_content) and
1612 not has_some_log_import_pattern.search(file_content))):
1613 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221614 for line_num, line in f.ChangedContents():
1615
1616 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121617 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221618 if match:
1619 has_modified_logs = True
1620
1621 # Make sure it uses "TAG"
1622 if not match.group('tag') == 'TAG':
1623 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121624 else:
1625 # Report non cr Log function calls in changed lines
1626 for line_num, line in f.ChangedContents():
1627 if log_call_pattern.search(line):
1628 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221629
1630 # Per file checks
1631 if has_modified_logs:
1632 # Make sure the tag is using the "cr" prefix and is not too long
1633 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511634 tag_name = match.group('name') if match else None
1635 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221636 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511637 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221638 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511639 elif '.' in tag_name:
1640 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221641
1642 results = []
1643 if tag_decl_errors:
1644 results.append(output_api.PresubmitPromptWarning(
1645 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511646 '"private static final String TAG = "<package tag>".\n'
1647 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221648 tag_decl_errors))
1649
1650 if tag_length_errors:
1651 results.append(output_api.PresubmitError(
1652 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511653 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221654 tag_length_errors))
1655
1656 if tag_errors:
1657 results.append(output_api.PresubmitPromptWarning(
1658 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1659 tag_errors))
1660
dgn87d9fb62015-06-12 09:15:121661 if util_log_errors:
dgn4401aa52015-04-29 16:26:171662 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121663 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1664 util_log_errors))
1665
dgn38736db2015-09-18 19:20:511666 if tag_with_dot_errors:
1667 results.append(output_api.PresubmitPromptWarning(
1668 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1669 tag_with_dot_errors))
1670
dgn4401aa52015-04-29 16:26:171671 return results
1672
1673
agrieve7b6479d82015-10-07 14:24:221674def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1675 """Checks if MDPI assets are placed in a correct directory."""
1676 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1677 ('/res/drawable/' in f.LocalPath() or
1678 '/res/drawable-ldrtl/' in f.LocalPath()))
1679 errors = []
1680 for f in input_api.AffectedFiles(include_deletes=False,
1681 file_filter=file_filter):
1682 errors.append(' %s' % f.LocalPath())
1683
1684 results = []
1685 if errors:
1686 results.append(output_api.PresubmitError(
1687 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1688 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1689 '/res/drawable-ldrtl/.\n'
1690 'Contact [email protected] if you have questions.', errors))
1691 return results
1692
1693
agrievef32bcc72016-04-04 14:57:401694class PydepsChecker(object):
1695 def __init__(self, input_api, pydeps_files):
1696 self._file_cache = {}
1697 self._input_api = input_api
1698 self._pydeps_files = pydeps_files
1699
1700 def _LoadFile(self, path):
1701 """Returns the list of paths within a .pydeps file relative to //."""
1702 if path not in self._file_cache:
1703 with open(path) as f:
1704 self._file_cache[path] = f.read()
1705 return self._file_cache[path]
1706
1707 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1708 """Returns an interable of paths within the .pydep, relativized to //."""
1709 os_path = self._input_api.os_path
1710 pydeps_dir = os_path.dirname(pydeps_path)
1711 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1712 if not l.startswith('*'))
1713 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1714
1715 def _CreateFilesToPydepsMap(self):
1716 """Returns a map of local_path -> list_of_pydeps."""
1717 ret = {}
1718 for pydep_local_path in self._pydeps_files:
1719 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1720 ret.setdefault(path, []).append(pydep_local_path)
1721 return ret
1722
1723 def ComputeAffectedPydeps(self):
1724 """Returns an iterable of .pydeps files that might need regenerating."""
1725 affected_pydeps = set()
1726 file_to_pydeps_map = None
1727 for f in self._input_api.AffectedFiles(include_deletes=True):
1728 local_path = f.LocalPath()
1729 if local_path == 'DEPS':
1730 return self._pydeps_files
1731 elif local_path.endswith('.pydeps'):
1732 if local_path in self._pydeps_files:
1733 affected_pydeps.add(local_path)
1734 elif local_path.endswith('.py'):
1735 if file_to_pydeps_map is None:
1736 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1737 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1738 return affected_pydeps
1739
1740 def DetermineIfStale(self, pydeps_path):
1741 """Runs print_python_deps.py to see if the files is stale."""
1742 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1743 cmd = old_pydeps_data[1][1:].strip()
1744 new_pydeps_data = self._input_api.subprocess.check_output(
1745 cmd + ' --output ""', shell=True)
1746 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1747 return cmd
1748
1749
1750def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1751 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001752 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281753 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1754 # Mac, so skip it on other platforms.
1755 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001756 return []
agrievef32bcc72016-04-04 14:57:401757 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1758 is_android = input_api.os_path.exists('third_party/android_tools')
1759 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1760 results = []
1761 # First, check for new / deleted .pydeps.
1762 for f in input_api.AffectedFiles(include_deletes=True):
1763 if f.LocalPath().endswith('.pydeps'):
1764 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1765 results.append(output_api.PresubmitError(
1766 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1767 'remove %s' % f.LocalPath()))
1768 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1769 results.append(output_api.PresubmitError(
1770 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1771 'include %s' % f.LocalPath()))
1772
1773 if results:
1774 return results
1775
1776 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1777
1778 for pydep_path in checker.ComputeAffectedPydeps():
1779 try:
1780 cmd = checker.DetermineIfStale(pydep_path)
1781 if cmd:
1782 results.append(output_api.PresubmitError(
1783 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1784 (pydep_path, cmd)))
1785 except input_api.subprocess.CalledProcessError as error:
1786 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1787 long_text=error.output)]
1788
1789 return results
1790
1791
mnaganov9b9b1fe82014-12-11 16:30:361792def _CheckForCopyrightedCode(input_api, output_api):
1793 """Verifies that newly added code doesn't contain copyrighted material
1794 and is properly licensed under the standard Chromium license.
1795
1796 As there can be false positives, we maintain a whitelist file. This check
1797 also verifies that the whitelist file is up to date.
1798 """
1799 import sys
1800 original_sys_path = sys.path
1801 try:
1802 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221803 input_api.PresubmitLocalPath(), 'tools')]
1804 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361805 finally:
1806 # Restore sys.path to what it was before.
1807 sys.path = original_sys_path
1808
1809 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1810
1811
glidere61efad2015-02-18 17:39:431812def _CheckSingletonInHeaders(input_api, output_api):
1813 """Checks to make sure no header files have |Singleton<|."""
1814 def FileFilter(affected_file):
1815 # It's ok for base/memory/singleton.h to have |Singleton<|.
1816 black_list = (_EXCLUDED_PATHS +
1817 input_api.DEFAULT_BLACK_LIST +
1818 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1819 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1820
sergeyu34d21222015-09-16 00:11:441821 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431822 files = []
1823 for f in input_api.AffectedSourceFiles(FileFilter):
1824 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1825 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1826 contents = input_api.ReadFile(f)
1827 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241828 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431829 pattern.search(line)):
1830 files.append(f)
1831 break
1832
1833 if files:
yolandyandaabc6d2016-04-18 18:29:391834 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441835 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431836 'Please move them to an appropriate source file so that the ' +
1837 'template gets instantiated in a single compilation unit.',
1838 files) ]
1839 return []
1840
1841
dbeam37e8e7402016-02-10 22:58:201842def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1843 """Checks for old style compiled_resources.gyp files."""
1844 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1845
1846 added_compiled_resources = filter(is_compiled_resource, [
1847 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1848 ])
1849
1850 if not added_compiled_resources:
1851 return []
1852
1853 return [output_api.PresubmitError(
1854 "Found new compiled_resources.gyp files:\n%s\n\n"
1855 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551856 "please use compiled_resources2.gyp instead:\n"
1857 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1858 %
dbeam37e8e7402016-02-10 22:58:201859 "\n".join(added_compiled_resources))]
1860
1861
[email protected]fd20b902014-05-09 02:14:531862_DEPRECATED_CSS = [
1863 # Values
1864 ( "-webkit-box", "flex" ),
1865 ( "-webkit-inline-box", "inline-flex" ),
1866 ( "-webkit-flex", "flex" ),
1867 ( "-webkit-inline-flex", "inline-flex" ),
1868 ( "-webkit-min-content", "min-content" ),
1869 ( "-webkit-max-content", "max-content" ),
1870
1871 # Properties
1872 ( "-webkit-background-clip", "background-clip" ),
1873 ( "-webkit-background-origin", "background-origin" ),
1874 ( "-webkit-background-size", "background-size" ),
1875 ( "-webkit-box-shadow", "box-shadow" ),
1876
1877 # Functions
1878 ( "-webkit-gradient", "gradient" ),
1879 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1880 ( "-webkit-linear-gradient", "linear-gradient" ),
1881 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1882 ( "-webkit-radial-gradient", "radial-gradient" ),
1883 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1884]
1885
1886def _CheckNoDeprecatedCSS(input_api, output_api):
1887 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251888 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341889 documentation and iOS CSS for dom distiller
1890 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251891 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531892 results = []
dbeam070cfe62014-10-22 06:44:021893 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251894 black_list = (_EXCLUDED_PATHS +
1895 _TEST_CODE_EXCLUDED_PATHS +
1896 input_api.DEFAULT_BLACK_LIST +
1897 (r"^chrome/common/extensions/docs",
1898 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341899 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051900 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441901 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251902 r"^native_client_sdk"))
1903 file_filter = lambda f: input_api.FilterSourceFile(
1904 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531905 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1906 for line_num, line in fpath.ChangedContents():
1907 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021908 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531909 results.append(output_api.PresubmitError(
1910 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1911 (fpath.LocalPath(), line_num, deprecated_value, value)))
1912 return results
1913
mohan.reddyf21db962014-10-16 12:26:471914
dbeam070cfe62014-10-22 06:44:021915_DEPRECATED_JS = [
1916 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1917 ( "__defineGetter__", "Object.defineProperty" ),
1918 ( "__defineSetter__", "Object.defineProperty" ),
1919]
1920
1921def _CheckNoDeprecatedJS(input_api, output_api):
1922 """Make sure that we don't use deprecated JS in Chrome code."""
1923 results = []
1924 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1925 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1926 input_api.DEFAULT_BLACK_LIST)
1927 file_filter = lambda f: input_api.FilterSourceFile(
1928 f, white_list=file_inclusion_pattern, black_list=black_list)
1929 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1930 for lnum, line in fpath.ChangedContents():
1931 for (deprecated, replacement) in _DEPRECATED_JS:
1932 if deprecated in line:
1933 results.append(output_api.PresubmitError(
1934 "%s:%d: Use of deprecated JS %s, use %s instead" %
1935 (fpath.LocalPath(), lnum, deprecated, replacement)))
1936 return results
1937
1938
dgnaa68d5e2015-06-10 10:08:221939def _AndroidSpecificOnUploadChecks(input_api, output_api):
1940 """Groups checks that target android code."""
1941 results = []
dgnaa68d5e2015-06-10 10:08:221942 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221943 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291944 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221945 return results
1946
1947
[email protected]22c9bd72011-03-27 16:47:391948def _CommonChecks(input_api, output_api):
1949 """Checks common to both upload and commit."""
1950 results = []
1951 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381952 input_api, output_api,
1953 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461954 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191955 results.extend(
[email protected]760deea2013-12-10 19:33:491956 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541957 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181958 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521959 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221960 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441961 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591962 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061963 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121964 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181965 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221966 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491967 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271968 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031969 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491970 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441971 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271972 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541973 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441974 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391975 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551976 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041977 results.extend(
1978 input_api.canned_checks.CheckChangeHasNoTabs(
1979 input_api,
1980 output_api,
1981 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401982 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161983 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591984 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081985 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531986 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021987 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471988 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041989 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361990 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231991 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431992 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201993 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401994 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:151995 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:171996 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:231997 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241998
1999 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2000 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2001 input_api, output_api,
2002 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382003 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392004 return results
[email protected]1f7b4172010-01-28 01:17:342005
[email protected]b337cb5b2011-01-23 21:24:052006
[email protected]66daa702011-05-28 14:41:462007def _CheckAuthorizedAuthor(input_api, output_api):
2008 """For non-googler/chromites committers, verify the author's email address is
2009 in AUTHORS.
2010 """
2011 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012012 if not author:
2013 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462014 return []
[email protected]c99663292011-05-31 19:46:082015 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462016 input_api.PresubmitLocalPath(), 'AUTHORS')
2017 valid_authors = (
2018 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2019 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182020 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172021 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2022 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232023 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462024 return [output_api.PresubmitPromptWarning(
2025 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2026 '\n'
2027 'http://www.chromium.org/developers/contributing-code and read the '
2028 '"Legal" section\n'
2029 'If you are a chromite, verify the contributor signed the CLA.') %
2030 author)]
2031 return []
2032
2033
[email protected]b8079ae4a2012-12-05 19:56:492034def _CheckPatchFiles(input_api, output_api):
2035 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2036 if f.LocalPath().endswith(('.orig', '.rej'))]
2037 if problems:
2038 return [output_api.PresubmitError(
2039 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032040 else:
2041 return []
[email protected]b8079ae4a2012-12-05 19:56:492042
2043
[email protected]b00342e7f2013-03-26 16:21:542044def _DidYouMeanOSMacro(bad_macro):
2045 try:
2046 return {'A': 'OS_ANDROID',
2047 'B': 'OS_BSD',
2048 'C': 'OS_CHROMEOS',
2049 'F': 'OS_FREEBSD',
2050 'L': 'OS_LINUX',
2051 'M': 'OS_MACOSX',
2052 'N': 'OS_NACL',
2053 'O': 'OS_OPENBSD',
2054 'P': 'OS_POSIX',
2055 'S': 'OS_SOLARIS',
2056 'W': 'OS_WIN'}[bad_macro[3].upper()]
2057 except KeyError:
2058 return ''
2059
2060
2061def _CheckForInvalidOSMacrosInFile(input_api, f):
2062 """Check for sensible looking, totally invalid OS macros."""
2063 preprocessor_statement = input_api.re.compile(r'^\s*#')
2064 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2065 results = []
2066 for lnum, line in f.ChangedContents():
2067 if preprocessor_statement.search(line):
2068 for match in os_macro.finditer(line):
2069 if not match.group(1) in _VALID_OS_MACROS:
2070 good = _DidYouMeanOSMacro(match.group(1))
2071 did_you_mean = ' (did you mean %s?)' % good if good else ''
2072 results.append(' %s:%d %s%s' % (f.LocalPath(),
2073 lnum,
2074 match.group(1),
2075 did_you_mean))
2076 return results
2077
2078
2079def _CheckForInvalidOSMacros(input_api, output_api):
2080 """Check all affected files for invalid OS macros."""
2081 bad_macros = []
2082 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472083 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542084 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2085
2086 if not bad_macros:
2087 return []
2088
2089 return [output_api.PresubmitError(
2090 'Possibly invalid OS macro[s] found. Please fix your code\n'
2091 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2092
lliabraa35bab3932014-10-01 12:16:442093
2094def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2095 """Check all affected files for invalid "if defined" macros."""
2096 ALWAYS_DEFINED_MACROS = (
2097 "TARGET_CPU_PPC",
2098 "TARGET_CPU_PPC64",
2099 "TARGET_CPU_68K",
2100 "TARGET_CPU_X86",
2101 "TARGET_CPU_ARM",
2102 "TARGET_CPU_MIPS",
2103 "TARGET_CPU_SPARC",
2104 "TARGET_CPU_ALPHA",
2105 "TARGET_IPHONE_SIMULATOR",
2106 "TARGET_OS_EMBEDDED",
2107 "TARGET_OS_IPHONE",
2108 "TARGET_OS_MAC",
2109 "TARGET_OS_UNIX",
2110 "TARGET_OS_WIN32",
2111 )
2112 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2113 results = []
2114 for lnum, line in f.ChangedContents():
2115 for match in ifdef_macro.finditer(line):
2116 if match.group(1) in ALWAYS_DEFINED_MACROS:
2117 always_defined = ' %s is always defined. ' % match.group(1)
2118 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2119 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2120 lnum,
2121 always_defined,
2122 did_you_mean))
2123 return results
2124
2125
2126def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2127 """Check all affected files for invalid "if defined" macros."""
2128 bad_macros = []
2129 for f in input_api.AffectedFiles():
2130 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2131 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2132
2133 if not bad_macros:
2134 return []
2135
2136 return [output_api.PresubmitError(
2137 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2138 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2139 bad_macros)]
2140
2141
mlamouria82272622014-09-16 18:45:042142def _CheckForIPCRules(input_api, output_api):
2143 """Check for same IPC rules described in
2144 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2145 """
2146 base_pattern = r'IPC_ENUM_TRAITS\('
2147 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2148 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2149
2150 problems = []
2151 for f in input_api.AffectedSourceFiles(None):
2152 local_path = f.LocalPath()
2153 if not local_path.endswith('.h'):
2154 continue
2155 for line_number, line in f.ChangedContents():
2156 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2157 problems.append(
2158 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2159
2160 if problems:
2161 return [output_api.PresubmitPromptWarning(
2162 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2163 else:
2164 return []
2165
[email protected]b00342e7f2013-03-26 16:21:542166
mostynbb639aca52015-01-07 20:31:232167def _CheckForWindowsLineEndings(input_api, output_api):
2168 """Check source code and known ascii text files for Windows style line
2169 endings.
2170 """
earthdok1b5e0ee2015-03-10 15:19:102171 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232172
2173 file_inclusion_pattern = (
2174 known_text_files,
2175 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2176 )
2177
2178 filter = lambda f: input_api.FilterSourceFile(
2179 f, white_list=file_inclusion_pattern, black_list=None)
2180 files = [f.LocalPath() for f in
2181 input_api.AffectedSourceFiles(filter)]
2182
2183 problems = []
2184
2185 for file in files:
2186 fp = open(file, 'r')
2187 for line in fp:
2188 if line.endswith('\r\n'):
2189 problems.append(file)
2190 break
2191 fp.close()
2192
2193 if problems:
2194 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2195 'these files to contain Windows style line endings?\n' +
2196 '\n'.join(problems))]
2197
2198 return []
2199
2200
[email protected]1f7b4172010-01-28 01:17:342201def CheckChangeOnUpload(input_api, output_api):
2202 results = []
2203 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472204 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282205 results.extend(
2206 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192207 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222208 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542209 return results
[email protected]ca8d1982009-02-19 16:33:122210
2211
[email protected]1bfb8322014-04-23 01:02:412212def GetTryServerMasterForBot(bot):
2213 """Returns the Try Server master for the given bot.
2214
[email protected]0bb112362014-07-26 04:38:322215 It tries to guess the master from the bot name, but may still fail
2216 and return None. There is no longer a default master.
2217 """
2218 # Potentially ambiguous bot names are listed explicitly.
2219 master_map = {
tandriie5587792016-07-14 00:34:502220 'chromium_presubmit': 'master.tryserver.chromium.linux',
2221 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412222 }
[email protected]0bb112362014-07-26 04:38:322223 master = master_map.get(bot)
2224 if not master:
wnwen4fbaab82016-05-25 12:54:362225 if 'android' in bot:
tandriie5587792016-07-14 00:34:502226 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362227 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502228 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322229 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502230 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322231 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502232 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322233 return master
[email protected]1bfb8322014-04-23 01:02:412234
2235
Paweł Hajdan, Jr55083782014-12-19 20:32:562236def GetDefaultTryConfigs(bots):
2237 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012238 """
2239
Paweł Hajdan, Jr55083782014-12-19 20:32:562240 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412241
2242 # Build up the mapping from tryserver master to bot/test.
2243 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562244 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412245 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2246 return out
[email protected]38c6a512013-12-18 23:48:012247
2248
[email protected]ca8d1982009-02-19 16:33:122249def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542250 results = []
[email protected]1f7b4172010-01-28 01:17:342251 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542252 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272253 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342254 input_api,
2255 output_api,
[email protected]2fdd1f362013-01-16 03:56:032256 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272257
[email protected]3e4eb112011-01-18 03:29:542258 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2259 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412260 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2261 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542262 return results