blob: e2e042336926e54a01f47dd33769c9a534c7c92c [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",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d1982009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4455 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4956 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4757 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4958 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0859 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4960 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4461)
[email protected]ca8d1982009-02-19 16:33:1262
wnwenbdc444e2016-05-25 13:44:1563
[email protected]eea609a2011-11-18 13:10:1264_TEST_ONLY_WARNING = (
65 'You might be calling functions intended only for testing from\n'
66 'production code. It is OK to ignore this warning if you know what\n'
67 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5868 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1269
70
[email protected]cf9b78f2012-11-14 11:40:2871_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4072 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2173 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
74 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2875
wnwenbdc444e2016-05-25 13:44:1576
[email protected]127f18ec2012-06-16 05:05:5977_BANNED_OBJC_FUNCTIONS = (
78 (
79 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2080 (
81 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5982 'prohibited. Please use CrTrackingArea instead.',
83 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
84 ),
85 False,
86 ),
87 (
[email protected]eaae1972014-04-16 04:17:2688 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2089 (
90 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5991 'instead.',
92 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
93 ),
94 False,
95 ),
96 (
97 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2098 (
99 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59100 'Please use |convertPoint:(point) fromView:nil| instead.',
101 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
102 ),
103 True,
104 ),
105 (
106 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20107 (
108 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59109 'Please use |convertPoint:(point) toView:nil| instead.',
110 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
111 ),
112 True,
113 ),
114 (
115 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20116 (
117 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59118 'Please use |convertRect:(point) fromView:nil| instead.',
119 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
120 ),
121 True,
122 ),
123 (
124 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20125 (
126 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59127 'Please use |convertRect:(point) toView:nil| instead.',
128 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
129 ),
130 True,
131 ),
132 (
133 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20134 (
135 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59136 'Please use |convertSize:(point) fromView:nil| instead.',
137 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
138 ),
139 True,
140 ),
141 (
142 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20143 (
144 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59145 'Please use |convertSize:(point) toView:nil| instead.',
146 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
147 ),
148 True,
149 ),
150)
151
152
153_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20154 # Make sure that gtest's FRIEND_TEST() macro is not used; the
155 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30156 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'FRIEND_TEST(',
159 (
[email protected]e3c945502012-06-26 20:01:49160 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20161 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
162 ),
163 False,
[email protected]7345da02012-11-27 14:31:49164 (),
[email protected]23e6cbc2012-06-16 18:51:20165 ),
166 (
167 'ScopedAllowIO',
168 (
[email protected]e3c945502012-06-26 20:01:49169 'New code should not use ScopedAllowIO. Post a task to the blocking',
170 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20171 ),
[email protected]e3c945502012-06-26 20:01:49172 True,
[email protected]7345da02012-11-27 14:31:49173 (
nyad2c548b2015-12-09 03:22:32174 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10175 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49176 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22177 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31178 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51179 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
180 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09181 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49182 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
183 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25184 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41185 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
186 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25187 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48188 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
189 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01190 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25191 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
192 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
193 r"embedded_test_server\.cc$",
194 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
195 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54196 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53197 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
198 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45199 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
200 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
201 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
202 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
203 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49204 ),
[email protected]23e6cbc2012-06-16 18:51:20205 ),
[email protected]52657f62013-05-20 05:30:31206 (
tomhudsone2c14d552016-05-26 17:07:46207 'setMatrixClip',
208 (
209 'Overriding setMatrixClip() is prohibited; ',
210 'the base function is deprecated. ',
211 ),
212 True,
213 (),
214 ),
215 (
[email protected]52657f62013-05-20 05:30:31216 'SkRefPtr',
217 (
218 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22219 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31220 ),
221 True,
222 (),
223 ),
224 (
225 'SkAutoRef',
226 (
227 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22228 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31229 ),
230 True,
231 (),
232 ),
233 (
234 'SkAutoTUnref',
235 (
236 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22237 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31238 ),
239 True,
240 (),
241 ),
242 (
243 'SkAutoUnref',
244 (
245 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
246 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22247 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31248 ),
249 True,
250 (),
251 ),
[email protected]d89eec82013-12-03 14:10:59252 (
253 r'/HANDLE_EINTR\(.*close',
254 (
255 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
256 'descriptor will be closed, and it is incorrect to retry the close.',
257 'Either call close directly and ignore its return value, or wrap close',
258 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
259 ),
260 True,
261 (),
262 ),
263 (
264 r'/IGNORE_EINTR\((?!.*close)',
265 (
266 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
267 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
268 ),
269 True,
270 (
271 # Files that #define IGNORE_EINTR.
272 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
273 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
274 ),
275 ),
[email protected]ec5b3f02014-04-04 18:43:43276 (
277 r'/v8::Extension\(',
278 (
279 'Do not introduce new v8::Extensions into the code base, use',
280 'gin::Wrappable instead. See http://crbug.com/334679',
281 ),
282 True,
[email protected]f55c90ee62014-04-12 00:50:03283 (
joaodasilva718f87672014-08-30 09:25:49284 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03285 ),
[email protected]ec5b3f02014-04-04 18:43:43286 ),
skyostilf9469f72015-04-20 10:38:52287 (
jame2d1a952016-04-02 00:27:10288 '#pragma comment(lib,',
289 (
290 'Specify libraries to link with in build files and not in the source.',
291 ),
292 True,
293 (),
294 ),
[email protected]127f18ec2012-06-16 05:05:59295)
296
wnwenbdc444e2016-05-25 13:44:15297
mlamouria82272622014-09-16 18:45:04298_IPC_ENUM_TRAITS_DEPRECATED = (
299 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
300 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
301
[email protected]127f18ec2012-06-16 05:05:59302
[email protected]b00342e7f2013-03-26 16:21:54303_VALID_OS_MACROS = (
304 # Please keep sorted.
305 'OS_ANDROID',
306 'OS_BSD',
307 'OS_CAT', # For testing.
308 'OS_CHROMEOS',
309 'OS_FREEBSD',
310 'OS_IOS',
311 'OS_LINUX',
312 'OS_MACOSX',
313 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21314 'OS_NACL_NONSFI',
315 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12316 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54317 'OS_OPENBSD',
318 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37319 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54320 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54321 'OS_WIN',
322)
323
324
agrievef32bcc72016-04-04 14:57:40325_ANDROID_SPECIFIC_PYDEPS_FILES = [
326 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19327 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40328]
329
wnwenbdc444e2016-05-25 13:44:15330
agrievef32bcc72016-04-04 14:57:40331_GENERIC_PYDEPS_FILES = [
332 'build/secondary/tools/swarming_client/isolate.pydeps',
333]
334
wnwenbdc444e2016-05-25 13:44:15335
agrievef32bcc72016-04-04 14:57:40336_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
337
338
[email protected]55459852011-08-10 15:17:19339def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
340 """Attempts to prevent use of functions intended only for testing in
341 non-testing code. For now this is just a best-effort implementation
342 that ignores header files and may have some false positives. A
343 better implementation would probably need a proper C++ parser.
344 """
345 # We only scan .cc files and the like, as the declaration of
346 # for-testing functions in header files are hard to distinguish from
347 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44348 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19349
jochenc0d4808c2015-07-27 09:25:42350 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19351 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09352 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19353 exclusion_pattern = input_api.re.compile(
354 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
355 base_function_pattern, base_function_pattern))
356
357 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44358 black_list = (_EXCLUDED_PATHS +
359 _TEST_CODE_EXCLUDED_PATHS +
360 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19361 return input_api.FilterSourceFile(
362 affected_file,
363 white_list=(file_inclusion_pattern, ),
364 black_list=black_list)
365
366 problems = []
367 for f in input_api.AffectedSourceFiles(FilterFile):
368 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24369 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03370 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46371 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03372 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19373 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03374 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19375
376 if problems:
[email protected]f7051d52013-04-02 18:31:42377 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03378 else:
379 return []
[email protected]55459852011-08-10 15:17:19380
381
[email protected]10689ca2011-09-02 02:31:54382def _CheckNoIOStreamInHeaders(input_api, output_api):
383 """Checks to make sure no .h files include <iostream>."""
384 files = []
385 pattern = input_api.re.compile(r'^#include\s*<iostream>',
386 input_api.re.MULTILINE)
387 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
388 if not f.LocalPath().endswith('.h'):
389 continue
390 contents = input_api.ReadFile(f)
391 if pattern.search(contents):
392 files.append(f)
393
394 if len(files):
yolandyandaabc6d2016-04-18 18:29:39395 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06396 'Do not #include <iostream> in header files, since it inserts static '
397 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54398 '#include <ostream>. See http://crbug.com/94794',
399 files) ]
400 return []
401
402
[email protected]72df4e782012-06-21 16:28:18403def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52404 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18405 problems = []
406 for f in input_api.AffectedFiles():
407 if (not f.LocalPath().endswith(('.cc', '.mm'))):
408 continue
409
410 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04411 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18412 problems.append(' %s:%d' % (f.LocalPath(), line_num))
413
414 if not problems:
415 return []
416 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
417 '\n'.join(problems))]
418
419
danakj61c1aa22015-10-26 19:55:52420def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
421 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
422 errors = []
423 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
424 input_api.re.MULTILINE)
425 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
426 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
427 continue
428 for lnum, line in f.ChangedContents():
429 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17430 errors.append(output_api.PresubmitError(
431 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
432 'DCHECK_IS_ON()", not forgetting the braces.')
433 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52434 return errors
435
436
mcasasb7440c282015-02-04 14:52:19437def _FindHistogramNameInLine(histogram_name, line):
438 """Tries to find a histogram name or prefix in a line."""
439 if not "affected-histogram" in line:
440 return histogram_name in line
441 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
442 # the histogram_name.
443 if not '"' in line:
444 return False
445 histogram_prefix = line.split('\"')[1]
446 return histogram_prefix in histogram_name
447
448
449def _CheckUmaHistogramChanges(input_api, output_api):
450 """Check that UMA histogram names in touched lines can still be found in other
451 lines of the patch or in histograms.xml. Note that this check would not catch
452 the reverse: changes in histograms.xml not matched in the code itself."""
453 touched_histograms = []
454 histograms_xml_modifications = []
455 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
456 for f in input_api.AffectedFiles():
457 # If histograms.xml itself is modified, keep the modified lines for later.
458 if f.LocalPath().endswith(('histograms.xml')):
459 histograms_xml_modifications = f.ChangedContents()
460 continue
461 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
462 continue
463 for line_num, line in f.ChangedContents():
464 found = pattern.search(line)
465 if found:
466 touched_histograms.append([found.group(1), f, line_num])
467
468 # Search for the touched histogram names in the local modifications to
469 # histograms.xml, and, if not found, on the base histograms.xml file.
470 unmatched_histograms = []
471 for histogram_info in touched_histograms:
472 histogram_name_found = False
473 for line_num, line in histograms_xml_modifications:
474 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
475 if histogram_name_found:
476 break
477 if not histogram_name_found:
478 unmatched_histograms.append(histogram_info)
479
eromanb90c82e7e32015-04-01 15:13:49480 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19481 problems = []
482 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49483 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19484 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45485 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19486 histogram_name_found = False
487 for line in histograms_xml:
488 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
489 if histogram_name_found:
490 break
491 if not histogram_name_found:
492 problems.append(' [%s:%d] %s' %
493 (f.LocalPath(), line_num, histogram_name))
494
495 if not problems:
496 return []
497 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
498 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49499 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19500
wnwenbdc444e2016-05-25 13:44:15501
yolandyandaabc6d2016-04-18 18:29:39502def _CheckFlakyTestUsage(input_api, output_api):
503 """Check that FlakyTest annotation is our own instead of the android one"""
504 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
505 files = []
506 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
507 if f.LocalPath().endswith('Test.java'):
508 if pattern.search(input_api.ReadFile(f)):
509 files.append(f)
510 if len(files):
511 return [output_api.PresubmitError(
512 'Use org.chromium.base.test.util.FlakyTest instead of '
513 'android.test.FlakyTest',
514 files)]
515 return []
mcasasb7440c282015-02-04 14:52:19516
wnwenbdc444e2016-05-25 13:44:15517
[email protected]8ea5d4b2011-09-13 21:49:22518def _CheckNoNewWStrings(input_api, output_api):
519 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27520 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22521 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20522 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57523 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34524 '/win/' in f.LocalPath() or
525 'chrome_elf' in f.LocalPath() or
526 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20527 continue
[email protected]8ea5d4b2011-09-13 21:49:22528
[email protected]a11dbe9b2012-08-07 01:32:58529 allowWString = False
[email protected]b5c24292011-11-28 14:38:20530 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58531 if 'presubmit: allow wstring' in line:
532 allowWString = True
533 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27534 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58535 allowWString = False
536 else:
537 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22538
[email protected]55463aa62011-10-12 00:48:27539 if not problems:
540 return []
541 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58542 ' If you are calling a cross-platform API that accepts a wstring, '
543 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27544 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22545
546
[email protected]2a8ac9c2011-10-19 17:20:44547def _CheckNoDEPSGIT(input_api, output_api):
548 """Make sure .DEPS.git is never modified manually."""
549 if any(f.LocalPath().endswith('.DEPS.git') for f in
550 input_api.AffectedFiles()):
551 return [output_api.PresubmitError(
552 'Never commit changes to .DEPS.git. This file is maintained by an\n'
553 'automated system based on what\'s in DEPS and your changes will be\n'
554 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34555 '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:44556 'for more information')]
557 return []
558
559
tandriief664692014-09-23 14:51:47560def _CheckValidHostsInDEPS(input_api, output_api):
561 """Checks that DEPS file deps are from allowed_hosts."""
562 # Run only if DEPS file has been modified to annoy fewer bystanders.
563 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
564 return []
565 # Outsource work to gclient verify
566 try:
567 input_api.subprocess.check_output(['gclient', 'verify'])
568 return []
569 except input_api.subprocess.CalledProcessError, error:
570 return [output_api.PresubmitError(
571 'DEPS file must have only git dependencies.',
572 long_text=error.output)]
573
574
[email protected]127f18ec2012-06-16 05:05:59575def _CheckNoBannedFunctions(input_api, output_api):
576 """Make sure that banned functions are not used."""
577 warnings = []
578 errors = []
579
wnwenbdc444e2016-05-25 13:44:15580 def IsBlacklisted(affected_file, blacklist):
581 local_path = affected_file.LocalPath()
582 for item in blacklist:
583 if input_api.re.match(item, local_path):
584 return True
585 return False
586
587 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
588 matched = False
589 if func_name[0:1] == '/':
590 regex = func_name[1:]
591 if input_api.re.search(regex, line):
592 matched = True
593 elif func_name in line:
dchenge07de812016-06-20 19:27:17594 matched = True
wnwenbdc444e2016-05-25 13:44:15595 if matched:
dchenge07de812016-06-20 19:27:17596 problems = warnings
wnwenbdc444e2016-05-25 13:44:15597 if error:
dchenge07de812016-06-20 19:27:17598 problems = errors
wnwenbdc444e2016-05-25 13:44:15599 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
600 for message_line in message:
601 problems.append(' %s' % message_line)
602
[email protected]127f18ec2012-06-16 05:05:59603 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
604 for f in input_api.AffectedFiles(file_filter=file_filter):
605 for line_num, line in f.ChangedContents():
606 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15607 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59608
609 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
610 for f in input_api.AffectedFiles(file_filter=file_filter):
611 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49612 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49613 if IsBlacklisted(f, excluded_paths):
614 continue
wnwenbdc444e2016-05-25 13:44:15615 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59616
617 result = []
618 if (warnings):
619 result.append(output_api.PresubmitPromptWarning(
620 'Banned functions were used.\n' + '\n'.join(warnings)))
621 if (errors):
622 result.append(output_api.PresubmitError(
623 'Banned functions were used.\n' + '\n'.join(errors)))
624 return result
625
626
[email protected]6c063c62012-07-11 19:11:06627def _CheckNoPragmaOnce(input_api, output_api):
628 """Make sure that banned functions are not used."""
629 files = []
630 pattern = input_api.re.compile(r'^#pragma\s+once',
631 input_api.re.MULTILINE)
632 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
633 if not f.LocalPath().endswith('.h'):
634 continue
635 contents = input_api.ReadFile(f)
636 if pattern.search(contents):
637 files.append(f)
638
639 if files:
640 return [output_api.PresubmitError(
641 'Do not use #pragma once in header files.\n'
642 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
643 files)]
644 return []
645
[email protected]127f18ec2012-06-16 05:05:59646
[email protected]e7479052012-09-19 00:26:12647def _CheckNoTrinaryTrueFalse(input_api, output_api):
648 """Checks to make sure we don't introduce use of foo ? true : false."""
649 problems = []
650 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
651 for f in input_api.AffectedFiles():
652 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
653 continue
654
655 for line_num, line in f.ChangedContents():
656 if pattern.match(line):
657 problems.append(' %s:%d' % (f.LocalPath(), line_num))
658
659 if not problems:
660 return []
661 return [output_api.PresubmitPromptWarning(
662 'Please consider avoiding the "? true : false" pattern if possible.\n' +
663 '\n'.join(problems))]
664
665
[email protected]55f9f382012-07-31 11:02:18666def _CheckUnwantedDependencies(input_api, output_api):
667 """Runs checkdeps on #include statements added in this
668 change. Breaking - rules is an error, breaking ! rules is a
669 warning.
670 """
mohan.reddyf21db962014-10-16 12:26:47671 import sys
[email protected]55f9f382012-07-31 11:02:18672 # We need to wait until we have an input_api object and use this
673 # roundabout construct to import checkdeps because this file is
674 # eval-ed and thus doesn't have __file__.
675 original_sys_path = sys.path
676 try:
677 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47678 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18679 import checkdeps
680 from cpp_checker import CppChecker
681 from rules import Rule
682 finally:
683 # Restore sys.path to what it was before.
684 sys.path = original_sys_path
685
686 added_includes = []
687 for f in input_api.AffectedFiles():
688 if not CppChecker.IsCppFile(f.LocalPath()):
689 continue
690
691 changed_lines = [line for line_num, line in f.ChangedContents()]
692 added_includes.append([f.LocalPath(), changed_lines])
693
[email protected]26385172013-05-09 23:11:35694 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18695
696 error_descriptions = []
697 warning_descriptions = []
698 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
699 added_includes):
700 description_with_path = '%s\n %s' % (path, rule_description)
701 if rule_type == Rule.DISALLOW:
702 error_descriptions.append(description_with_path)
703 else:
704 warning_descriptions.append(description_with_path)
705
706 results = []
707 if error_descriptions:
708 results.append(output_api.PresubmitError(
709 'You added one or more #includes that violate checkdeps rules.',
710 error_descriptions))
711 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42712 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18713 'You added one or more #includes of files that are temporarily\n'
714 'allowed but being removed. Can you avoid introducing the\n'
715 '#include? See relevant DEPS file(s) for details and contacts.',
716 warning_descriptions))
717 return results
718
719
[email protected]fbcafe5a2012-08-08 15:31:22720def _CheckFilePermissions(input_api, output_api):
721 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15722 if input_api.platform == 'win32':
723 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29724 checkperms_tool = input_api.os_path.join(
725 input_api.PresubmitLocalPath(),
726 'tools', 'checkperms', 'checkperms.py')
727 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47728 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22729 for f in input_api.AffectedFiles():
730 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11731 try:
732 input_api.subprocess.check_output(args)
733 return []
734 except input_api.subprocess.CalledProcessError as error:
735 return [output_api.PresubmitError(
736 'checkperms.py failed:',
737 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22738
739
[email protected]c8278b32012-10-30 20:35:49740def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
741 """Makes sure we don't include ui/aura/window_property.h
742 in header files.
743 """
744 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
745 errors = []
746 for f in input_api.AffectedFiles():
747 if not f.LocalPath().endswith('.h'):
748 continue
749 for line_num, line in f.ChangedContents():
750 if pattern.match(line):
751 errors.append(' %s:%d' % (f.LocalPath(), line_num))
752
753 results = []
754 if errors:
755 results.append(output_api.PresubmitError(
756 'Header files should not include ui/aura/window_property.h', errors))
757 return results
758
759
[email protected]cf9b78f2012-11-14 11:40:28760def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
761 """Checks that the lines in scope occur in the right order.
762
763 1. C system files in alphabetical order
764 2. C++ system files in alphabetical order
765 3. Project's .h files
766 """
767
768 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
769 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
770 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
771
772 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
773
774 state = C_SYSTEM_INCLUDES
775
776 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57777 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28778 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55779 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28780 for line_num, line in scope:
781 if c_system_include_pattern.match(line):
782 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55783 problem_linenums.append((line_num, previous_line_num,
784 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28785 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55786 problem_linenums.append((line_num, previous_line_num,
787 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28788 elif cpp_system_include_pattern.match(line):
789 if state == C_SYSTEM_INCLUDES:
790 state = CPP_SYSTEM_INCLUDES
791 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55792 problem_linenums.append((line_num, previous_line_num,
793 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28794 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55795 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28796 elif custom_include_pattern.match(line):
797 if state != CUSTOM_INCLUDES:
798 state = CUSTOM_INCLUDES
799 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55800 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28801 else:
brucedawson70fadb02015-06-30 17:47:55802 problem_linenums.append((line_num, previous_line_num,
803 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28804 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57805 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28806
807 warnings = []
brucedawson70fadb02015-06-30 17:47:55808 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57809 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55810 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28811 return warnings
812
813
[email protected]ac294a12012-12-06 16:38:43814def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28815 """Checks the #include order for the given file f."""
816
[email protected]2299dcf2012-11-15 19:56:24817 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30818 # Exclude the following includes from the check:
819 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
820 # specific order.
821 # 2) <atlbase.h>, "build/build_config.h"
822 excluded_include_pattern = input_api.re.compile(
823 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24824 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33825 # Match the final or penultimate token if it is xxxtest so we can ignore it
826 # when considering the special first include.
827 test_file_tag_pattern = input_api.re.compile(
828 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11829 if_pattern = input_api.re.compile(
830 r'\s*#\s*(if|elif|else|endif|define|undef).*')
831 # Some files need specialized order of includes; exclude such files from this
832 # check.
833 uncheckable_includes_pattern = input_api.re.compile(
834 r'\s*#include '
835 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28836
837 contents = f.NewContents()
838 warnings = []
839 line_num = 0
840
[email protected]ac294a12012-12-06 16:38:43841 # Handle the special first include. If the first include file is
842 # some/path/file.h, the corresponding including file can be some/path/file.cc,
843 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
844 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33845 # If the included file is some/path/file_platform.h the including file could
846 # also be some/path/file_xxxtest_platform.h.
847 including_file_base_name = test_file_tag_pattern.sub(
848 '', input_api.os_path.basename(f.LocalPath()))
849
[email protected]ac294a12012-12-06 16:38:43850 for line in contents:
851 line_num += 1
852 if system_include_pattern.match(line):
853 # No special first include -> process the line again along with normal
854 # includes.
855 line_num -= 1
856 break
857 match = custom_include_pattern.match(line)
858 if match:
859 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33860 header_basename = test_file_tag_pattern.sub(
861 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
862
863 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24864 # No special first include -> process the line again along with normal
865 # includes.
866 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43867 break
[email protected]cf9b78f2012-11-14 11:40:28868
869 # Split into scopes: Each region between #if and #endif is its own scope.
870 scopes = []
871 current_scope = []
872 for line in contents[line_num:]:
873 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11874 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54875 continue
[email protected]2309b0fa02012-11-16 12:18:27876 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28877 scopes.append(current_scope)
878 current_scope = []
[email protected]962f117e2012-11-22 18:11:56879 elif ((system_include_pattern.match(line) or
880 custom_include_pattern.match(line)) and
881 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28882 current_scope.append((line_num, line))
883 scopes.append(current_scope)
884
885 for scope in scopes:
886 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
887 changed_linenums))
888 return warnings
889
890
891def _CheckIncludeOrder(input_api, output_api):
892 """Checks that the #include order is correct.
893
894 1. The corresponding header for source files.
895 2. C system files in alphabetical order
896 3. C++ system files in alphabetical order
897 4. Project's .h files in alphabetical order
898
[email protected]ac294a12012-12-06 16:38:43899 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
900 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28901 """
[email protected]e120b012014-08-15 19:08:35902 def FileFilterIncludeOrder(affected_file):
903 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
904 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28905
906 warnings = []
[email protected]e120b012014-08-15 19:08:35907 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08908 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43909 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
910 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28911
912 results = []
913 if warnings:
[email protected]f7051d52013-04-02 18:31:42914 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53915 warnings))
[email protected]cf9b78f2012-11-14 11:40:28916 return results
917
918
[email protected]70ca77752012-11-20 03:45:03919def _CheckForVersionControlConflictsInFile(input_api, f):
920 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
921 errors = []
922 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23923 if f.LocalPath().endswith('.md'):
924 # First-level headers in markdown look a lot like version control
925 # conflict markers. http://daringfireball.net/projects/markdown/basics
926 continue
[email protected]70ca77752012-11-20 03:45:03927 if pattern.match(line):
928 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
929 return errors
930
931
932def _CheckForVersionControlConflicts(input_api, output_api):
933 """Usually this is not intentional and will cause a compile failure."""
934 errors = []
935 for f in input_api.AffectedFiles():
936 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
937
938 results = []
939 if errors:
940 results.append(output_api.PresubmitError(
941 'Version control conflict markers found, please resolve.', errors))
942 return results
943
944
[email protected]06e6d0ff2012-12-11 01:36:44945def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
946 def FilterFile(affected_file):
947 """Filter function for use with input_api.AffectedSourceFiles,
948 below. This filters out everything except non-test files from
949 top-level directories that generally speaking should not hard-code
950 service URLs (e.g. src/android_webview/, src/content/ and others).
951 """
952 return input_api.FilterSourceFile(
953 affected_file,
[email protected]78bb39d62012-12-11 15:11:56954 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44955 black_list=(_EXCLUDED_PATHS +
956 _TEST_CODE_EXCLUDED_PATHS +
957 input_api.DEFAULT_BLACK_LIST))
958
reillyi38965732015-11-16 18:27:33959 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
960 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46961 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
962 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44963 problems = [] # items are (filename, line_number, line)
964 for f in input_api.AffectedSourceFiles(FilterFile):
965 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46966 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44967 problems.append((f.LocalPath(), line_num, line))
968
969 if problems:
[email protected]f7051d52013-04-02 18:31:42970 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44971 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58972 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44973 [' %s:%d: %s' % (
974 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03975 else:
976 return []
[email protected]06e6d0ff2012-12-11 01:36:44977
978
[email protected]d2530012013-01-25 16:39:27979def _CheckNoAbbreviationInPngFileName(input_api, output_api):
980 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31981 The native_client_sdk directory is excluded because it has auto-generated PNG
982 files for documentation.
[email protected]d2530012013-01-25 16:39:27983 """
[email protected]d2530012013-01-25 16:39:27984 errors = []
binji0dcdf342014-12-12 18:32:31985 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
986 black_list = (r'^native_client_sdk[\\\/]',)
987 file_filter = lambda f: input_api.FilterSourceFile(
988 f, white_list=white_list, black_list=black_list)
989 for f in input_api.AffectedFiles(include_deletes=False,
990 file_filter=file_filter):
991 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27992
993 results = []
994 if errors:
995 results.append(output_api.PresubmitError(
996 'The name of PNG files should not have abbreviations. \n'
997 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
998 'Contact [email protected] if you have questions.', errors))
999 return results
1000
1001
[email protected]14a6131c2014-01-08 01:15:411002def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081003 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411004 a set of DEPS entries that we should look up.
1005
1006 For a directory (rather than a specific filename) we fake a path to
1007 a specific filename by adding /DEPS. This is chosen as a file that
1008 will seldom or never be subject to per-file include_rules.
1009 """
[email protected]2b438d62013-11-14 17:54:141010 # We ignore deps entries on auto-generated directories.
1011 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081012
1013 # This pattern grabs the path without basename in the first
1014 # parentheses, and the basename (if present) in the second. It
1015 # relies on the simple heuristic that if there is a basename it will
1016 # be a header file ending in ".h".
1017 pattern = re.compile(
1018 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141019 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081020 for changed_line in changed_lines:
1021 m = pattern.match(changed_line)
1022 if m:
1023 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141024 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411025 if m.group(2):
1026 results.add('%s%s' % (path, m.group(2)))
1027 else:
1028 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081029 return results
1030
1031
[email protected]e871964c2013-05-13 14:14:551032def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1033 """When a dependency prefixed with + is added to a DEPS file, we
1034 want to make sure that the change is reviewed by an OWNER of the
1035 target file or directory, to avoid layering violations from being
1036 introduced. This check verifies that this happens.
1037 """
1038 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241039
1040 file_filter = lambda f: not input_api.re.match(
1041 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1042 for f in input_api.AffectedFiles(include_deletes=False,
1043 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551044 filename = input_api.os_path.basename(f.LocalPath())
1045 if filename == 'DEPS':
1046 changed_lines |= set(line.strip()
1047 for line_num, line
1048 in f.ChangedContents())
1049 if not changed_lines:
1050 return []
1051
[email protected]14a6131c2014-01-08 01:15:411052 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1053 changed_lines)
[email protected]e871964c2013-05-13 14:14:551054 if not virtual_depended_on_files:
1055 return []
1056
1057 if input_api.is_committing:
1058 if input_api.tbr:
1059 return [output_api.PresubmitNotifyResult(
1060 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271061 if input_api.dry_run:
1062 return [output_api.PresubmitNotifyResult(
1063 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551064 if not input_api.change.issue:
1065 return [output_api.PresubmitError(
1066 "DEPS approval by OWNERS check failed: this change has "
1067 "no Rietveld issue number, so we can't check it for approvals.")]
1068 output = output_api.PresubmitError
1069 else:
1070 output = output_api.PresubmitNotifyResult
1071
1072 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501073 owner_email, reviewers = (
1074 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1075 input_api,
1076 owners_db.email_regexp,
1077 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551078
1079 owner_email = owner_email or input_api.change.author_email
1080
[email protected]de4f7d22013-05-23 14:27:461081 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511082 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461083 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551084 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1085 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411086
1087 # We strip the /DEPS part that was added by
1088 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1089 # directory.
1090 def StripDeps(path):
1091 start_deps = path.rfind('/DEPS')
1092 if start_deps != -1:
1093 return path[:start_deps]
1094 else:
1095 return path
1096 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551097 for path in missing_files]
1098
1099 if unapproved_dependencies:
1100 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151101 output('You need LGTM from owners of depends-on paths in DEPS that were '
1102 'modified in this CL:\n %s' %
1103 '\n '.join(sorted(unapproved_dependencies)))]
1104 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1105 output_list.append(output(
1106 'Suggested missing target path OWNERS:\n %s' %
1107 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551108 return output_list
1109
1110 return []
1111
1112
[email protected]85218562013-11-22 07:41:401113def _CheckSpamLogging(input_api, output_api):
1114 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1115 black_list = (_EXCLUDED_PATHS +
1116 _TEST_CODE_EXCLUDED_PATHS +
1117 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501118 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191119 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481120 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461121 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121122 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1123 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581124 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161125 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031126 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151127 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1128 r"^chromecast[\\\/]",
1129 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311130 r"^components[\\\/]html_viewer[\\\/]"
1131 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461132 # TODO(peter): Remove this exception. https://crbug.com/534537
1133 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1134 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251135 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1136 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241137 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111138 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151139 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111140 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521141 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501142 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361143 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311144 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131145 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441146 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451147 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021148 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441149 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401150 source_file_filter = lambda x: input_api.FilterSourceFile(
1151 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1152
1153 log_info = []
1154 printf = []
1155
1156 for f in input_api.AffectedSourceFiles(source_file_filter):
1157 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471158 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401159 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471160 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131161 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371162
mohan.reddyf21db962014-10-16 12:26:471163 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371164 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471165 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401166 printf.append(f.LocalPath())
1167
1168 if log_info:
1169 return [output_api.PresubmitError(
1170 'These files spam the console log with LOG(INFO):',
1171 items=log_info)]
1172 if printf:
1173 return [output_api.PresubmitError(
1174 'These files spam the console log with printf/fprintf:',
1175 items=printf)]
1176 return []
1177
1178
[email protected]49aa76a2013-12-04 06:59:161179def _CheckForAnonymousVariables(input_api, output_api):
1180 """These types are all expected to hold locks while in scope and
1181 so should never be anonymous (which causes them to be immediately
1182 destroyed)."""
1183 they_who_must_be_named = [
1184 'base::AutoLock',
1185 'base::AutoReset',
1186 'base::AutoUnlock',
1187 'SkAutoAlphaRestore',
1188 'SkAutoBitmapShaderInstall',
1189 'SkAutoBlitterChoose',
1190 'SkAutoBounderCommit',
1191 'SkAutoCallProc',
1192 'SkAutoCanvasRestore',
1193 'SkAutoCommentBlock',
1194 'SkAutoDescriptor',
1195 'SkAutoDisableDirectionCheck',
1196 'SkAutoDisableOvalCheck',
1197 'SkAutoFree',
1198 'SkAutoGlyphCache',
1199 'SkAutoHDC',
1200 'SkAutoLockColors',
1201 'SkAutoLockPixels',
1202 'SkAutoMalloc',
1203 'SkAutoMaskFreeImage',
1204 'SkAutoMutexAcquire',
1205 'SkAutoPathBoundsUpdate',
1206 'SkAutoPDFRelease',
1207 'SkAutoRasterClipValidate',
1208 'SkAutoRef',
1209 'SkAutoTime',
1210 'SkAutoTrace',
1211 'SkAutoUnref',
1212 ]
1213 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1214 # bad: base::AutoLock(lock.get());
1215 # not bad: base::AutoLock lock(lock.get());
1216 bad_pattern = input_api.re.compile(anonymous)
1217 # good: new base::AutoLock(lock.get())
1218 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1219 errors = []
1220
1221 for f in input_api.AffectedFiles():
1222 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1223 continue
1224 for linenum, line in f.ChangedContents():
1225 if bad_pattern.search(line) and not good_pattern.search(line):
1226 errors.append('%s:%d' % (f.LocalPath(), linenum))
1227
1228 if errors:
1229 return [output_api.PresubmitError(
1230 'These lines create anonymous variables that need to be named:',
1231 items=errors)]
1232 return []
1233
1234
[email protected]5fe0f8742013-11-29 01:04:591235def _CheckCygwinShell(input_api, output_api):
1236 source_file_filter = lambda x: input_api.FilterSourceFile(
1237 x, white_list=(r'.+\.(gyp|gypi)$',))
1238 cygwin_shell = []
1239
1240 for f in input_api.AffectedSourceFiles(source_file_filter):
1241 for linenum, line in f.ChangedContents():
1242 if 'msvs_cygwin_shell' in line:
1243 cygwin_shell.append(f.LocalPath())
1244 break
1245
1246 if cygwin_shell:
1247 return [output_api.PresubmitError(
1248 'These files should not use msvs_cygwin_shell (the default is 0):',
1249 items=cygwin_shell)]
1250 return []
1251
[email protected]85218562013-11-22 07:41:401252
[email protected]999261d2014-03-03 20:08:081253def _CheckUserActionUpdate(input_api, output_api):
1254 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521255 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081256 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521257 # If actions.xml is already included in the changelist, the PRESUBMIT
1258 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081259 return []
1260
[email protected]999261d2014-03-03 20:08:081261 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1262 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521263 current_actions = None
[email protected]999261d2014-03-03 20:08:081264 for f in input_api.AffectedFiles(file_filter=file_filter):
1265 for line_num, line in f.ChangedContents():
1266 match = input_api.re.search(action_re, line)
1267 if match:
[email protected]2f92dec2014-03-07 19:21:521268 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1269 # loaded only once.
1270 if not current_actions:
1271 with open('tools/metrics/actions/actions.xml') as actions_f:
1272 current_actions = actions_f.read()
1273 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081274 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521275 action = 'name="{0}"'.format(action_name)
1276 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081277 return [output_api.PresubmitPromptWarning(
1278 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521279 'tools/metrics/actions/actions.xml. Please run '
1280 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081281 % (f.LocalPath(), line_num, action_name))]
1282 return []
1283
1284
[email protected]99171a92014-06-03 08:44:471285def _GetJSONParseError(input_api, filename, eat_comments=True):
1286 try:
1287 contents = input_api.ReadFile(filename)
1288 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131289 import sys
1290 original_sys_path = sys.path
1291 try:
1292 sys.path = sys.path + [input_api.os_path.join(
1293 input_api.PresubmitLocalPath(),
1294 'tools', 'json_comment_eater')]
1295 import json_comment_eater
1296 finally:
1297 sys.path = original_sys_path
1298 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471299
1300 input_api.json.loads(contents)
1301 except ValueError as e:
1302 return e
1303 return None
1304
1305
1306def _GetIDLParseError(input_api, filename):
1307 try:
1308 contents = input_api.ReadFile(filename)
1309 idl_schema = input_api.os_path.join(
1310 input_api.PresubmitLocalPath(),
1311 'tools', 'json_schema_compiler', 'idl_schema.py')
1312 process = input_api.subprocess.Popen(
1313 [input_api.python_executable, idl_schema],
1314 stdin=input_api.subprocess.PIPE,
1315 stdout=input_api.subprocess.PIPE,
1316 stderr=input_api.subprocess.PIPE,
1317 universal_newlines=True)
1318 (_, error) = process.communicate(input=contents)
1319 return error or None
1320 except ValueError as e:
1321 return e
1322
1323
1324def _CheckParseErrors(input_api, output_api):
1325 """Check that IDL and JSON files do not contain syntax errors."""
1326 actions = {
1327 '.idl': _GetIDLParseError,
1328 '.json': _GetJSONParseError,
1329 }
1330 # These paths contain test data and other known invalid JSON files.
1331 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491332 r'test[\\\/]data[\\\/]',
1333 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471334 ]
1335 # Most JSON files are preprocessed and support comments, but these do not.
1336 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491337 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471338 ]
1339 # Only run IDL checker on files in these directories.
1340 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491341 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1342 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471343 ]
1344
1345 def get_action(affected_file):
1346 filename = affected_file.LocalPath()
1347 return actions.get(input_api.os_path.splitext(filename)[1])
1348
1349 def MatchesFile(patterns, path):
1350 for pattern in patterns:
1351 if input_api.re.search(pattern, path):
1352 return True
1353 return False
1354
1355 def FilterFile(affected_file):
1356 action = get_action(affected_file)
1357 if not action:
1358 return False
1359 path = affected_file.LocalPath()
1360
1361 if MatchesFile(excluded_patterns, path):
1362 return False
1363
1364 if (action == _GetIDLParseError and
1365 not MatchesFile(idl_included_patterns, path)):
1366 return False
1367 return True
1368
1369 results = []
1370 for affected_file in input_api.AffectedFiles(
1371 file_filter=FilterFile, include_deletes=False):
1372 action = get_action(affected_file)
1373 kwargs = {}
1374 if (action == _GetJSONParseError and
1375 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1376 kwargs['eat_comments'] = False
1377 parse_error = action(input_api,
1378 affected_file.AbsoluteLocalPath(),
1379 **kwargs)
1380 if parse_error:
1381 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1382 (affected_file.LocalPath(), parse_error)))
1383 return results
1384
1385
[email protected]760deea2013-12-10 19:33:491386def _CheckJavaStyle(input_api, output_api):
1387 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471388 import sys
[email protected]760deea2013-12-10 19:33:491389 original_sys_path = sys.path
1390 try:
1391 sys.path = sys.path + [input_api.os_path.join(
1392 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1393 import checkstyle
1394 finally:
1395 # Restore sys.path to what it was before.
1396 sys.path = original_sys_path
1397
1398 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091399 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511400 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491401
1402
dchenge07de812016-06-20 19:27:171403def _CheckIpcOwners(input_api, output_api):
1404 """Checks that affected files involving IPC have an IPC OWNERS rule.
1405
1406 Whether or not a file affects IPC is determined by a simple whitelist of
1407 filename patterns."""
1408 file_patterns = [
1409 '*_messages.cc',
1410 '*_messages*.h',
1411 '*_param_traits*.*',
1412 '*.mojom',
1413 '*_struct_traits*.*',
1414 '*_type_converter*.*',
1415 # Blink uses a different file naming convention
1416 '*StructTraits*.*',
1417 '*TypeConverter*.*',
1418 ]
1419
1420 # Dictionary mapping an OWNERS file path to Patterns.
1421 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1422 # rules ) to a PatternEntry.
1423 # PatternEntry is a dictionary with two keys:
1424 # - 'files': the files that are matched by this pattern
1425 # - 'rules': the per-file rules needed for this pattern
1426 # For example, if we expect OWNERS file to contain rules for *.mojom and
1427 # *_struct_traits*.*, Patterns might look like this:
1428 # {
1429 # '*.mojom': {
1430 # 'files': ...,
1431 # 'rules': [
1432 # 'per-file *.mojom=set noparent',
1433 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1434 # ],
1435 # },
1436 # '*_struct_traits*.*': {
1437 # 'files': ...,
1438 # 'rules': [
1439 # 'per-file *_struct_traits*.*=set noparent',
1440 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1441 # ],
1442 # },
1443 # }
1444 to_check = {}
1445
1446 # Iterate through the affected files to see what we actually need to check
1447 # for. We should only nag patch authors about per-file rules if a file in that
1448 # directory would match that pattern. If a directory only contains *.mojom
1449 # files and no *_messages*.h files, we should only nag about rules for
1450 # *.mojom files.
rockot51249332016-06-23 16:32:251451 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171452 for pattern in file_patterns:
1453 if input_api.fnmatch.fnmatch(
1454 input_api.os_path.basename(f.LocalPath()), pattern):
1455 owners_file = input_api.os_path.join(
1456 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1457 if owners_file not in to_check:
1458 to_check[owners_file] = {}
1459 if pattern not in to_check[owners_file]:
1460 to_check[owners_file][pattern] = {
1461 'files': [],
1462 'rules': [
1463 'per-file %s=set noparent' % pattern,
1464 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1465 ]
1466 }
1467 to_check[owners_file][pattern]['files'].append(f)
1468 break
1469
1470 # Now go through the OWNERS files we collected, filtering out rules that are
1471 # already present in that OWNERS file.
1472 for owners_file, patterns in to_check.iteritems():
1473 try:
1474 with file(owners_file) as f:
1475 lines = set(f.read().splitlines())
1476 for entry in patterns.itervalues():
1477 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1478 ]
1479 except IOError:
1480 # No OWNERS file, so all the rules are definitely missing.
1481 continue
1482
1483 # All the remaining lines weren't found in OWNERS files, so emit an error.
1484 errors = []
1485 for owners_file, patterns in to_check.iteritems():
1486 missing_lines = []
1487 files = []
1488 for pattern, entry in patterns.iteritems():
1489 missing_lines.extend(entry['rules'])
1490 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1491 if missing_lines:
1492 errors.append(
1493 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1494 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1495
1496 results = []
1497 if errors:
vabrf5ce3bf92016-07-11 14:52:411498 if input_api.is_committing:
1499 output = output_api.PresubmitError
1500 else:
1501 output = output_api.PresubmitPromptWarning
1502 results.append(output(
dchenge07de812016-06-20 19:27:171503 'Found changes to IPC files without a security OWNER!',
1504 long_text='\n\n'.join(errors)))
1505
1506 return results
1507
1508
yzshend99f726a2016-07-25 21:44:231509def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1510 """Checks to make sure that all newly added mojom targets map array/map/string
1511 to STL (for chromium) or WTF (for blink) types.
1512 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1513 """
1514 files = []
1515 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1516 input_api.re.MULTILINE)
1517
1518 for f in input_api.AffectedFiles():
1519 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1520 continue
1521
1522 for _, line in f.ChangedContents():
1523 if pattern.search(line):
1524 files.append(f)
1525 break
1526
1527 if len(files):
1528 return [output_api.PresubmitError(
1529 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1530 'false. The mode is deprecated and will be removed soon.',
1531 files)]
1532 return []
1533
1534
dskiba88634f4e2015-08-14 23:03:291535def _CheckAndroidToastUsage(input_api, output_api):
1536 """Checks that code uses org.chromium.ui.widget.Toast instead of
1537 android.widget.Toast (Chromium Toast doesn't force hardware
1538 acceleration on low-end devices, saving memory).
1539 """
1540 toast_import_pattern = input_api.re.compile(
1541 r'^import android\.widget\.Toast;$')
1542
1543 errors = []
1544
1545 sources = lambda affected_file: input_api.FilterSourceFile(
1546 affected_file,
1547 black_list=(_EXCLUDED_PATHS +
1548 _TEST_CODE_EXCLUDED_PATHS +
1549 input_api.DEFAULT_BLACK_LIST +
1550 (r'^chromecast[\\\/].*',
1551 r'^remoting[\\\/].*')),
1552 white_list=(r'.*\.java$',))
1553
1554 for f in input_api.AffectedSourceFiles(sources):
1555 for line_num, line in f.ChangedContents():
1556 if toast_import_pattern.search(line):
1557 errors.append("%s:%d" % (f.LocalPath(), line_num))
1558
1559 results = []
1560
1561 if errors:
1562 results.append(output_api.PresubmitError(
1563 'android.widget.Toast usage is detected. Android toasts use hardware'
1564 ' acceleration, and can be\ncostly on low-end devices. Please use'
1565 ' org.chromium.ui.widget.Toast instead.\n'
1566 'Contact [email protected] if you have any questions.',
1567 errors))
1568
1569 return results
1570
1571
dgnaa68d5e2015-06-10 10:08:221572def _CheckAndroidCrLogUsage(input_api, output_api):
1573 """Checks that new logs using org.chromium.base.Log:
1574 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511575 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221576 """
pkotwicza1dd0b002016-05-16 14:41:041577
1578 # Do not check format of logs in //chrome/android/webapk because
1579 # //chrome/android/webapk cannot depend on //base
1580 cr_log_check_excluded_paths = [
1581 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1582 ]
1583
dgnaa68d5e2015-06-10 10:08:221584 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121585 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1586 class_in_base_pattern = input_api.re.compile(
1587 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1588 has_some_log_import_pattern = input_api.re.compile(
1589 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221590 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121591 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221592 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511593 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221594 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221595
Vincent Scheib16d7b272015-09-15 18:09:071596 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221597 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041598 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1599 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121600
dgnaa68d5e2015-06-10 10:08:221601 tag_decl_errors = []
1602 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121603 tag_errors = []
dgn38736db2015-09-18 19:20:511604 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121605 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221606
1607 for f in input_api.AffectedSourceFiles(sources):
1608 file_content = input_api.ReadFile(f)
1609 has_modified_logs = False
1610
1611 # Per line checks
dgn87d9fb62015-06-12 09:15:121612 if (cr_log_import_pattern.search(file_content) or
1613 (class_in_base_pattern.search(file_content) and
1614 not has_some_log_import_pattern.search(file_content))):
1615 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221616 for line_num, line in f.ChangedContents():
1617
1618 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121619 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221620 if match:
1621 has_modified_logs = True
1622
1623 # Make sure it uses "TAG"
1624 if not match.group('tag') == 'TAG':
1625 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121626 else:
1627 # Report non cr Log function calls in changed lines
1628 for line_num, line in f.ChangedContents():
1629 if log_call_pattern.search(line):
1630 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221631
1632 # Per file checks
1633 if has_modified_logs:
1634 # Make sure the tag is using the "cr" prefix and is not too long
1635 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511636 tag_name = match.group('name') if match else None
1637 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221638 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511639 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221640 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511641 elif '.' in tag_name:
1642 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221643
1644 results = []
1645 if tag_decl_errors:
1646 results.append(output_api.PresubmitPromptWarning(
1647 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511648 '"private static final String TAG = "<package tag>".\n'
1649 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221650 tag_decl_errors))
1651
1652 if tag_length_errors:
1653 results.append(output_api.PresubmitError(
1654 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511655 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221656 tag_length_errors))
1657
1658 if tag_errors:
1659 results.append(output_api.PresubmitPromptWarning(
1660 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1661 tag_errors))
1662
dgn87d9fb62015-06-12 09:15:121663 if util_log_errors:
dgn4401aa52015-04-29 16:26:171664 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121665 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1666 util_log_errors))
1667
dgn38736db2015-09-18 19:20:511668 if tag_with_dot_errors:
1669 results.append(output_api.PresubmitPromptWarning(
1670 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1671 tag_with_dot_errors))
1672
dgn4401aa52015-04-29 16:26:171673 return results
1674
1675
agrieve7b6479d82015-10-07 14:24:221676def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1677 """Checks if MDPI assets are placed in a correct directory."""
1678 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1679 ('/res/drawable/' in f.LocalPath() or
1680 '/res/drawable-ldrtl/' in f.LocalPath()))
1681 errors = []
1682 for f in input_api.AffectedFiles(include_deletes=False,
1683 file_filter=file_filter):
1684 errors.append(' %s' % f.LocalPath())
1685
1686 results = []
1687 if errors:
1688 results.append(output_api.PresubmitError(
1689 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1690 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1691 '/res/drawable-ldrtl/.\n'
1692 'Contact [email protected] if you have questions.', errors))
1693 return results
1694
1695
agrievef32bcc72016-04-04 14:57:401696class PydepsChecker(object):
1697 def __init__(self, input_api, pydeps_files):
1698 self._file_cache = {}
1699 self._input_api = input_api
1700 self._pydeps_files = pydeps_files
1701
1702 def _LoadFile(self, path):
1703 """Returns the list of paths within a .pydeps file relative to //."""
1704 if path not in self._file_cache:
1705 with open(path) as f:
1706 self._file_cache[path] = f.read()
1707 return self._file_cache[path]
1708
1709 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1710 """Returns an interable of paths within the .pydep, relativized to //."""
1711 os_path = self._input_api.os_path
1712 pydeps_dir = os_path.dirname(pydeps_path)
1713 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1714 if not l.startswith('*'))
1715 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1716
1717 def _CreateFilesToPydepsMap(self):
1718 """Returns a map of local_path -> list_of_pydeps."""
1719 ret = {}
1720 for pydep_local_path in self._pydeps_files:
1721 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1722 ret.setdefault(path, []).append(pydep_local_path)
1723 return ret
1724
1725 def ComputeAffectedPydeps(self):
1726 """Returns an iterable of .pydeps files that might need regenerating."""
1727 affected_pydeps = set()
1728 file_to_pydeps_map = None
1729 for f in self._input_api.AffectedFiles(include_deletes=True):
1730 local_path = f.LocalPath()
1731 if local_path == 'DEPS':
1732 return self._pydeps_files
1733 elif local_path.endswith('.pydeps'):
1734 if local_path in self._pydeps_files:
1735 affected_pydeps.add(local_path)
1736 elif local_path.endswith('.py'):
1737 if file_to_pydeps_map is None:
1738 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1739 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1740 return affected_pydeps
1741
1742 def DetermineIfStale(self, pydeps_path):
1743 """Runs print_python_deps.py to see if the files is stale."""
1744 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1745 cmd = old_pydeps_data[1][1:].strip()
1746 new_pydeps_data = self._input_api.subprocess.check_output(
1747 cmd + ' --output ""', shell=True)
1748 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1749 return cmd
1750
1751
1752def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1753 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001754 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281755 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1756 # Mac, so skip it on other platforms.
1757 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001758 return []
agrievef32bcc72016-04-04 14:57:401759 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1760 is_android = input_api.os_path.exists('third_party/android_tools')
1761 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1762 results = []
1763 # First, check for new / deleted .pydeps.
1764 for f in input_api.AffectedFiles(include_deletes=True):
1765 if f.LocalPath().endswith('.pydeps'):
1766 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1767 results.append(output_api.PresubmitError(
1768 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1769 'remove %s' % f.LocalPath()))
1770 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1771 results.append(output_api.PresubmitError(
1772 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1773 'include %s' % f.LocalPath()))
1774
1775 if results:
1776 return results
1777
1778 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1779
1780 for pydep_path in checker.ComputeAffectedPydeps():
1781 try:
1782 cmd = checker.DetermineIfStale(pydep_path)
1783 if cmd:
1784 results.append(output_api.PresubmitError(
1785 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1786 (pydep_path, cmd)))
1787 except input_api.subprocess.CalledProcessError as error:
1788 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1789 long_text=error.output)]
1790
1791 return results
1792
1793
mnaganov9b9b1fe82014-12-11 16:30:361794def _CheckForCopyrightedCode(input_api, output_api):
1795 """Verifies that newly added code doesn't contain copyrighted material
1796 and is properly licensed under the standard Chromium license.
1797
1798 As there can be false positives, we maintain a whitelist file. This check
1799 also verifies that the whitelist file is up to date.
1800 """
1801 import sys
1802 original_sys_path = sys.path
1803 try:
1804 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221805 input_api.PresubmitLocalPath(), 'tools')]
1806 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361807 finally:
1808 # Restore sys.path to what it was before.
1809 sys.path = original_sys_path
1810
1811 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1812
1813
glidere61efad2015-02-18 17:39:431814def _CheckSingletonInHeaders(input_api, output_api):
1815 """Checks to make sure no header files have |Singleton<|."""
1816 def FileFilter(affected_file):
1817 # It's ok for base/memory/singleton.h to have |Singleton<|.
1818 black_list = (_EXCLUDED_PATHS +
1819 input_api.DEFAULT_BLACK_LIST +
1820 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1821 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1822
sergeyu34d21222015-09-16 00:11:441823 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431824 files = []
1825 for f in input_api.AffectedSourceFiles(FileFilter):
1826 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1827 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1828 contents = input_api.ReadFile(f)
1829 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241830 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431831 pattern.search(line)):
1832 files.append(f)
1833 break
1834
1835 if files:
yolandyandaabc6d2016-04-18 18:29:391836 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441837 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431838 'Please move them to an appropriate source file so that the ' +
1839 'template gets instantiated in a single compilation unit.',
1840 files) ]
1841 return []
1842
1843
dbeam37e8e7402016-02-10 22:58:201844def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1845 """Checks for old style compiled_resources.gyp files."""
1846 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1847
1848 added_compiled_resources = filter(is_compiled_resource, [
1849 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1850 ])
1851
1852 if not added_compiled_resources:
1853 return []
1854
1855 return [output_api.PresubmitError(
1856 "Found new compiled_resources.gyp files:\n%s\n\n"
1857 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551858 "please use compiled_resources2.gyp instead:\n"
1859 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1860 %
dbeam37e8e7402016-02-10 22:58:201861 "\n".join(added_compiled_resources))]
1862
1863
[email protected]fd20b902014-05-09 02:14:531864_DEPRECATED_CSS = [
1865 # Values
1866 ( "-webkit-box", "flex" ),
1867 ( "-webkit-inline-box", "inline-flex" ),
1868 ( "-webkit-flex", "flex" ),
1869 ( "-webkit-inline-flex", "inline-flex" ),
1870 ( "-webkit-min-content", "min-content" ),
1871 ( "-webkit-max-content", "max-content" ),
1872
1873 # Properties
1874 ( "-webkit-background-clip", "background-clip" ),
1875 ( "-webkit-background-origin", "background-origin" ),
1876 ( "-webkit-background-size", "background-size" ),
1877 ( "-webkit-box-shadow", "box-shadow" ),
1878
1879 # Functions
1880 ( "-webkit-gradient", "gradient" ),
1881 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1882 ( "-webkit-linear-gradient", "linear-gradient" ),
1883 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1884 ( "-webkit-radial-gradient", "radial-gradient" ),
1885 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1886]
1887
1888def _CheckNoDeprecatedCSS(input_api, output_api):
1889 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251890 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341891 documentation and iOS CSS for dom distiller
1892 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251893 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531894 results = []
dbeam070cfe62014-10-22 06:44:021895 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251896 black_list = (_EXCLUDED_PATHS +
1897 _TEST_CODE_EXCLUDED_PATHS +
1898 input_api.DEFAULT_BLACK_LIST +
1899 (r"^chrome/common/extensions/docs",
1900 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341901 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051902 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441903 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251904 r"^native_client_sdk"))
1905 file_filter = lambda f: input_api.FilterSourceFile(
1906 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531907 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1908 for line_num, line in fpath.ChangedContents():
1909 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021910 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531911 results.append(output_api.PresubmitError(
1912 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1913 (fpath.LocalPath(), line_num, deprecated_value, value)))
1914 return results
1915
mohan.reddyf21db962014-10-16 12:26:471916
dbeam070cfe62014-10-22 06:44:021917_DEPRECATED_JS = [
1918 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1919 ( "__defineGetter__", "Object.defineProperty" ),
1920 ( "__defineSetter__", "Object.defineProperty" ),
1921]
1922
1923def _CheckNoDeprecatedJS(input_api, output_api):
1924 """Make sure that we don't use deprecated JS in Chrome code."""
1925 results = []
1926 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1927 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1928 input_api.DEFAULT_BLACK_LIST)
1929 file_filter = lambda f: input_api.FilterSourceFile(
1930 f, white_list=file_inclusion_pattern, black_list=black_list)
1931 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1932 for lnum, line in fpath.ChangedContents():
1933 for (deprecated, replacement) in _DEPRECATED_JS:
1934 if deprecated in line:
1935 results.append(output_api.PresubmitError(
1936 "%s:%d: Use of deprecated JS %s, use %s instead" %
1937 (fpath.LocalPath(), lnum, deprecated, replacement)))
1938 return results
1939
1940
dgnaa68d5e2015-06-10 10:08:221941def _AndroidSpecificOnUploadChecks(input_api, output_api):
1942 """Groups checks that target android code."""
1943 results = []
dgnaa68d5e2015-06-10 10:08:221944 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221945 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291946 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221947 return results
1948
1949
[email protected]22c9bd72011-03-27 16:47:391950def _CommonChecks(input_api, output_api):
1951 """Checks common to both upload and commit."""
1952 results = []
1953 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381954 input_api, output_api,
1955 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461956 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191957 results.extend(
[email protected]760deea2013-12-10 19:33:491958 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541959 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181960 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521961 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221962 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441963 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591964 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061965 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121966 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181967 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221968 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491969 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271970 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031971 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491972 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441973 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271974 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541975 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441976 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391977 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551978 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041979 results.extend(
1980 input_api.canned_checks.CheckChangeHasNoTabs(
1981 input_api,
1982 output_api,
1983 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401984 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161985 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591986 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081987 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531988 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021989 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471990 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041991 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361992 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231993 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431994 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201995 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401996 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:151997 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:171998 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:231999 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242000
2001 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2002 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2003 input_api, output_api,
2004 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382005 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392006 return results
[email protected]1f7b4172010-01-28 01:17:342007
[email protected]b337cb5b2011-01-23 21:24:052008
[email protected]66daa702011-05-28 14:41:462009def _CheckAuthorizedAuthor(input_api, output_api):
2010 """For non-googler/chromites committers, verify the author's email address is
2011 in AUTHORS.
2012 """
2013 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012014 if not author:
2015 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462016 return []
[email protected]c99663292011-05-31 19:46:082017 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462018 input_api.PresubmitLocalPath(), 'AUTHORS')
2019 valid_authors = (
2020 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2021 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182022 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172023 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2024 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232025 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462026 return [output_api.PresubmitPromptWarning(
2027 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2028 '\n'
2029 'http://www.chromium.org/developers/contributing-code and read the '
2030 '"Legal" section\n'
2031 'If you are a chromite, verify the contributor signed the CLA.') %
2032 author)]
2033 return []
2034
2035
[email protected]b8079ae4a2012-12-05 19:56:492036def _CheckPatchFiles(input_api, output_api):
2037 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2038 if f.LocalPath().endswith(('.orig', '.rej'))]
2039 if problems:
2040 return [output_api.PresubmitError(
2041 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032042 else:
2043 return []
[email protected]b8079ae4a2012-12-05 19:56:492044
2045
[email protected]b00342e7f2013-03-26 16:21:542046def _DidYouMeanOSMacro(bad_macro):
2047 try:
2048 return {'A': 'OS_ANDROID',
2049 'B': 'OS_BSD',
2050 'C': 'OS_CHROMEOS',
2051 'F': 'OS_FREEBSD',
2052 'L': 'OS_LINUX',
2053 'M': 'OS_MACOSX',
2054 'N': 'OS_NACL',
2055 'O': 'OS_OPENBSD',
2056 'P': 'OS_POSIX',
2057 'S': 'OS_SOLARIS',
2058 'W': 'OS_WIN'}[bad_macro[3].upper()]
2059 except KeyError:
2060 return ''
2061
2062
2063def _CheckForInvalidOSMacrosInFile(input_api, f):
2064 """Check for sensible looking, totally invalid OS macros."""
2065 preprocessor_statement = input_api.re.compile(r'^\s*#')
2066 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2067 results = []
2068 for lnum, line in f.ChangedContents():
2069 if preprocessor_statement.search(line):
2070 for match in os_macro.finditer(line):
2071 if not match.group(1) in _VALID_OS_MACROS:
2072 good = _DidYouMeanOSMacro(match.group(1))
2073 did_you_mean = ' (did you mean %s?)' % good if good else ''
2074 results.append(' %s:%d %s%s' % (f.LocalPath(),
2075 lnum,
2076 match.group(1),
2077 did_you_mean))
2078 return results
2079
2080
2081def _CheckForInvalidOSMacros(input_api, output_api):
2082 """Check all affected files for invalid OS macros."""
2083 bad_macros = []
2084 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472085 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542086 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2087
2088 if not bad_macros:
2089 return []
2090
2091 return [output_api.PresubmitError(
2092 'Possibly invalid OS macro[s] found. Please fix your code\n'
2093 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2094
lliabraa35bab3932014-10-01 12:16:442095
2096def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2097 """Check all affected files for invalid "if defined" macros."""
2098 ALWAYS_DEFINED_MACROS = (
2099 "TARGET_CPU_PPC",
2100 "TARGET_CPU_PPC64",
2101 "TARGET_CPU_68K",
2102 "TARGET_CPU_X86",
2103 "TARGET_CPU_ARM",
2104 "TARGET_CPU_MIPS",
2105 "TARGET_CPU_SPARC",
2106 "TARGET_CPU_ALPHA",
2107 "TARGET_IPHONE_SIMULATOR",
2108 "TARGET_OS_EMBEDDED",
2109 "TARGET_OS_IPHONE",
2110 "TARGET_OS_MAC",
2111 "TARGET_OS_UNIX",
2112 "TARGET_OS_WIN32",
2113 )
2114 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2115 results = []
2116 for lnum, line in f.ChangedContents():
2117 for match in ifdef_macro.finditer(line):
2118 if match.group(1) in ALWAYS_DEFINED_MACROS:
2119 always_defined = ' %s is always defined. ' % match.group(1)
2120 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2121 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2122 lnum,
2123 always_defined,
2124 did_you_mean))
2125 return results
2126
2127
2128def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2129 """Check all affected files for invalid "if defined" macros."""
2130 bad_macros = []
2131 for f in input_api.AffectedFiles():
2132 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2133 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2134
2135 if not bad_macros:
2136 return []
2137
2138 return [output_api.PresubmitError(
2139 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2140 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2141 bad_macros)]
2142
2143
mlamouria82272622014-09-16 18:45:042144def _CheckForIPCRules(input_api, output_api):
2145 """Check for same IPC rules described in
2146 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2147 """
2148 base_pattern = r'IPC_ENUM_TRAITS\('
2149 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2150 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2151
2152 problems = []
2153 for f in input_api.AffectedSourceFiles(None):
2154 local_path = f.LocalPath()
2155 if not local_path.endswith('.h'):
2156 continue
2157 for line_number, line in f.ChangedContents():
2158 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2159 problems.append(
2160 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2161
2162 if problems:
2163 return [output_api.PresubmitPromptWarning(
2164 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2165 else:
2166 return []
2167
[email protected]b00342e7f2013-03-26 16:21:542168
mostynbb639aca52015-01-07 20:31:232169def _CheckForWindowsLineEndings(input_api, output_api):
2170 """Check source code and known ascii text files for Windows style line
2171 endings.
2172 """
earthdok1b5e0ee2015-03-10 15:19:102173 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232174
2175 file_inclusion_pattern = (
2176 known_text_files,
2177 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2178 )
2179
2180 filter = lambda f: input_api.FilterSourceFile(
2181 f, white_list=file_inclusion_pattern, black_list=None)
2182 files = [f.LocalPath() for f in
2183 input_api.AffectedSourceFiles(filter)]
2184
2185 problems = []
2186
2187 for file in files:
2188 fp = open(file, 'r')
2189 for line in fp:
2190 if line.endswith('\r\n'):
2191 problems.append(file)
2192 break
2193 fp.close()
2194
2195 if problems:
2196 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2197 'these files to contain Windows style line endings?\n' +
2198 '\n'.join(problems))]
2199
2200 return []
2201
2202
[email protected]1f7b4172010-01-28 01:17:342203def CheckChangeOnUpload(input_api, output_api):
2204 results = []
2205 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472206 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282207 results.extend(
2208 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192209 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222210 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542211 return results
[email protected]ca8d1982009-02-19 16:33:122212
2213
[email protected]1bfb8322014-04-23 01:02:412214def GetTryServerMasterForBot(bot):
2215 """Returns the Try Server master for the given bot.
2216
[email protected]0bb112362014-07-26 04:38:322217 It tries to guess the master from the bot name, but may still fail
2218 and return None. There is no longer a default master.
2219 """
2220 # Potentially ambiguous bot names are listed explicitly.
2221 master_map = {
tandriie5587792016-07-14 00:34:502222 'chromium_presubmit': 'master.tryserver.chromium.linux',
2223 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412224 }
[email protected]0bb112362014-07-26 04:38:322225 master = master_map.get(bot)
2226 if not master:
wnwen4fbaab82016-05-25 12:54:362227 if 'android' in bot:
tandriie5587792016-07-14 00:34:502228 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362229 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502230 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322231 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502232 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322233 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502234 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322235 return master
[email protected]1bfb8322014-04-23 01:02:412236
2237
Paweł Hajdan, Jr55083782014-12-19 20:32:562238def GetDefaultTryConfigs(bots):
2239 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012240 """
2241
Paweł Hajdan, Jr55083782014-12-19 20:32:562242 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412243
2244 # Build up the mapping from tryserver master to bot/test.
2245 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562246 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412247 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2248 return out
[email protected]38c6a512013-12-18 23:48:012249
2250
[email protected]ca8d1982009-02-19 16:33:122251def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542252 results = []
[email protected]1f7b4172010-01-28 01:17:342253 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542254 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272255 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342256 input_api,
2257 output_api,
[email protected]2fdd1f362013-01-16 03:56:032258 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272259
[email protected]3e4eb112011-01-18 03:29:542260 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2261 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412262 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2263 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542264 return results