blob: 83aca99c3978ba02e59da34b117337ae7a422ceb [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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]ca8d19842009-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 ),
jif65398702016-10-27 10:19:48150 (
151 r"/\s+UTF8String\s*]",
152 (
153 'The use of -[NSString UTF8String] is dangerous as it can return null',
154 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
155 'Please use |SysNSStringToUTF8| instead.',
156 ),
157 True,
158 ),
[email protected]127f18ec2012-06-16 05:05:59159)
160
161
162_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20163 # Make sure that gtest's FRIEND_TEST() macro is not used; the
164 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30165 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20166 (
167 'FRIEND_TEST(',
168 (
[email protected]e3c945502012-06-26 20:01:49169 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20170 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
171 ),
172 False,
[email protected]7345da02012-11-27 14:31:49173 (),
[email protected]23e6cbc2012-06-16 18:51:20174 ),
175 (
thomasanderson4b569052016-09-14 20:15:53176 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
177 (
178 'Chrome clients wishing to select events on X windows should use',
179 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
180 'you are selecting events from the GPU process, or if you are using',
181 'an XDisplay other than gfx::GetXDisplay().',
182 ),
183 True,
184 (
185 r"^ui[\\\/]gl[\\\/].*\.cc$",
186 r"^media[\\\/]gpu[\\\/].*\.cc$",
187 r"^gpu[\\\/].*\.cc$",
188 ),
189 ),
190 (
[email protected]23e6cbc2012-06-16 18:51:20191 'ScopedAllowIO',
192 (
[email protected]e3c945502012-06-26 20:01:49193 'New code should not use ScopedAllowIO. Post a task to the blocking',
194 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20195 ),
[email protected]e3c945502012-06-26 20:01:49196 True,
[email protected]7345da02012-11-27 14:31:49197 (
nyad2c548b2015-12-09 03:22:32198 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10199 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49200 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22201 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31202 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51203 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
204 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09205 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49206 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
207 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25208 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41209 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
210 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25211 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48212 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
213 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01214 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25215 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
216 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
217 r"embedded_test_server\.cc$",
218 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
219 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54220 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53221 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
222 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45223 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
224 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
225 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
226 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
227 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49228 ),
[email protected]23e6cbc2012-06-16 18:51:20229 ),
[email protected]52657f62013-05-20 05:30:31230 (
tomhudsone2c14d552016-05-26 17:07:46231 'setMatrixClip',
232 (
233 'Overriding setMatrixClip() is prohibited; ',
234 'the base function is deprecated. ',
235 ),
236 True,
237 (),
238 ),
239 (
[email protected]52657f62013-05-20 05:30:31240 'SkRefPtr',
241 (
242 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22243 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31244 ),
245 True,
246 (),
247 ),
248 (
249 'SkAutoRef',
250 (
251 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22252 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31253 ),
254 True,
255 (),
256 ),
257 (
258 'SkAutoTUnref',
259 (
260 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22261 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31262 ),
263 True,
264 (),
265 ),
266 (
267 'SkAutoUnref',
268 (
269 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
270 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22271 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31272 ),
273 True,
274 (),
275 ),
[email protected]d89eec82013-12-03 14:10:59276 (
277 r'/HANDLE_EINTR\(.*close',
278 (
279 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
280 'descriptor will be closed, and it is incorrect to retry the close.',
281 'Either call close directly and ignore its return value, or wrap close',
282 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
283 ),
284 True,
285 (),
286 ),
287 (
288 r'/IGNORE_EINTR\((?!.*close)',
289 (
290 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
291 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
292 ),
293 True,
294 (
295 # Files that #define IGNORE_EINTR.
296 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
297 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
298 ),
299 ),
[email protected]ec5b3f02014-04-04 18:43:43300 (
301 r'/v8::Extension\(',
302 (
303 'Do not introduce new v8::Extensions into the code base, use',
304 'gin::Wrappable instead. See http://crbug.com/334679',
305 ),
306 True,
[email protected]f55c90ee62014-04-12 00:50:03307 (
joaodasilva718f87672014-08-30 09:25:49308 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03309 ),
[email protected]ec5b3f02014-04-04 18:43:43310 ),
skyostilf9469f72015-04-20 10:38:52311 (
jame2d1a952016-04-02 00:27:10312 '#pragma comment(lib,',
313 (
314 'Specify libraries to link with in build files and not in the source.',
315 ),
316 True,
317 (),
318 ),
dcheng8f0694bae2016-10-12 15:58:15319 (
avid5a337982016-10-19 23:07:15320 r'STLDeleteContainerPointers', # http://crbug.com/555865
321 (
322 'This call is obsolete with C++ 11; create a container with owning',
323 'pointers instead (e.g. std::vector<std::unique_ptr<x>> ).',
324 ),
325 True,
326 (),
327 ),
328 (
329 r'STLDeleteElements', # http://crbug.com/555865
330 (
331 'This call is obsolete with C++ 11; create a container with owning',
332 'pointers instead (e.g. std::vector<std::unique_ptr<x>> ).',
333 ),
334 True,
335 (),
336 ),
337 (
338 r'STLDeleteValues', # http://crbug.com/555865
339 (
340 'This call is obsolete with C++ 11; create a map with owning',
341 'pointers instead (e.g. std::map<std::string, std::unique_ptr<x>> ).',
342 ),
343 True,
344 (),
345 ),
[email protected]127f18ec2012-06-16 05:05:59346)
347
wnwenbdc444e2016-05-25 13:44:15348
mlamouria82272622014-09-16 18:45:04349_IPC_ENUM_TRAITS_DEPRECATED = (
350 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
351 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
352
[email protected]127f18ec2012-06-16 05:05:59353
[email protected]b00342e7f2013-03-26 16:21:54354_VALID_OS_MACROS = (
355 # Please keep sorted.
356 'OS_ANDROID',
357 'OS_BSD',
358 'OS_CAT', # For testing.
359 'OS_CHROMEOS',
360 'OS_FREEBSD',
361 'OS_IOS',
362 'OS_LINUX',
363 'OS_MACOSX',
364 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21365 'OS_NACL_NONSFI',
366 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12367 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54368 'OS_OPENBSD',
369 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37370 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54371 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54372 'OS_WIN',
373)
374
375
agrievef32bcc72016-04-04 14:57:40376_ANDROID_SPECIFIC_PYDEPS_FILES = [
377 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19378 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40379]
380
wnwenbdc444e2016-05-25 13:44:15381
agrievef32bcc72016-04-04 14:57:40382_GENERIC_PYDEPS_FILES = [
383 'build/secondary/tools/swarming_client/isolate.pydeps',
384]
385
wnwenbdc444e2016-05-25 13:44:15386
agrievef32bcc72016-04-04 14:57:40387_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
388
389
[email protected]55459852011-08-10 15:17:19390def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
391 """Attempts to prevent use of functions intended only for testing in
392 non-testing code. For now this is just a best-effort implementation
393 that ignores header files and may have some false positives. A
394 better implementation would probably need a proper C++ parser.
395 """
396 # We only scan .cc files and the like, as the declaration of
397 # for-testing functions in header files are hard to distinguish from
398 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44399 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19400
jochenc0d4808c2015-07-27 09:25:42401 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19402 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09403 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19404 exclusion_pattern = input_api.re.compile(
405 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
406 base_function_pattern, base_function_pattern))
407
408 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44409 black_list = (_EXCLUDED_PATHS +
410 _TEST_CODE_EXCLUDED_PATHS +
411 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19412 return input_api.FilterSourceFile(
413 affected_file,
414 white_list=(file_inclusion_pattern, ),
415 black_list=black_list)
416
417 problems = []
418 for f in input_api.AffectedSourceFiles(FilterFile):
419 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24420 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03421 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46422 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03423 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19424 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03425 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19426
427 if problems:
[email protected]f7051d52013-04-02 18:31:42428 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03429 else:
430 return []
[email protected]55459852011-08-10 15:17:19431
432
[email protected]10689ca2011-09-02 02:31:54433def _CheckNoIOStreamInHeaders(input_api, output_api):
434 """Checks to make sure no .h files include <iostream>."""
435 files = []
436 pattern = input_api.re.compile(r'^#include\s*<iostream>',
437 input_api.re.MULTILINE)
438 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
439 if not f.LocalPath().endswith('.h'):
440 continue
441 contents = input_api.ReadFile(f)
442 if pattern.search(contents):
443 files.append(f)
444
445 if len(files):
yolandyandaabc6d2016-04-18 18:29:39446 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06447 'Do not #include <iostream> in header files, since it inserts static '
448 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54449 '#include <ostream>. See http://crbug.com/94794',
450 files) ]
451 return []
452
453
[email protected]72df4e782012-06-21 16:28:18454def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52455 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18456 problems = []
457 for f in input_api.AffectedFiles():
458 if (not f.LocalPath().endswith(('.cc', '.mm'))):
459 continue
460
461 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04462 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18463 problems.append(' %s:%d' % (f.LocalPath(), line_num))
464
465 if not problems:
466 return []
467 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
468 '\n'.join(problems))]
469
470
danakj61c1aa22015-10-26 19:55:52471def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
472 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
473 errors = []
474 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
475 input_api.re.MULTILINE)
476 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
477 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
478 continue
479 for lnum, line in f.ChangedContents():
480 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17481 errors.append(output_api.PresubmitError(
482 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
483 'DCHECK_IS_ON()", not forgetting the braces.')
484 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52485 return errors
486
487
mcasasb7440c282015-02-04 14:52:19488def _FindHistogramNameInLine(histogram_name, line):
489 """Tries to find a histogram name or prefix in a line."""
490 if not "affected-histogram" in line:
491 return histogram_name in line
492 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
493 # the histogram_name.
494 if not '"' in line:
495 return False
496 histogram_prefix = line.split('\"')[1]
497 return histogram_prefix in histogram_name
498
499
500def _CheckUmaHistogramChanges(input_api, output_api):
501 """Check that UMA histogram names in touched lines can still be found in other
502 lines of the patch or in histograms.xml. Note that this check would not catch
503 the reverse: changes in histograms.xml not matched in the code itself."""
504 touched_histograms = []
505 histograms_xml_modifications = []
506 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
507 for f in input_api.AffectedFiles():
508 # If histograms.xml itself is modified, keep the modified lines for later.
509 if f.LocalPath().endswith(('histograms.xml')):
510 histograms_xml_modifications = f.ChangedContents()
511 continue
512 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
513 continue
514 for line_num, line in f.ChangedContents():
515 found = pattern.search(line)
516 if found:
517 touched_histograms.append([found.group(1), f, line_num])
518
519 # Search for the touched histogram names in the local modifications to
520 # histograms.xml, and, if not found, on the base histograms.xml file.
521 unmatched_histograms = []
522 for histogram_info in touched_histograms:
523 histogram_name_found = False
524 for line_num, line in histograms_xml_modifications:
525 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
526 if histogram_name_found:
527 break
528 if not histogram_name_found:
529 unmatched_histograms.append(histogram_info)
530
eromanb90c82e7e32015-04-01 15:13:49531 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19532 problems = []
533 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49534 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19535 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45536 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19537 histogram_name_found = False
538 for line in histograms_xml:
539 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
540 if histogram_name_found:
541 break
542 if not histogram_name_found:
543 problems.append(' [%s:%d] %s' %
544 (f.LocalPath(), line_num, histogram_name))
545
546 if not problems:
547 return []
548 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
549 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49550 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19551
wnwenbdc444e2016-05-25 13:44:15552
yolandyandaabc6d2016-04-18 18:29:39553def _CheckFlakyTestUsage(input_api, output_api):
554 """Check that FlakyTest annotation is our own instead of the android one"""
555 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
556 files = []
557 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
558 if f.LocalPath().endswith('Test.java'):
559 if pattern.search(input_api.ReadFile(f)):
560 files.append(f)
561 if len(files):
562 return [output_api.PresubmitError(
563 'Use org.chromium.base.test.util.FlakyTest instead of '
564 'android.test.FlakyTest',
565 files)]
566 return []
mcasasb7440c282015-02-04 14:52:19567
wnwenbdc444e2016-05-25 13:44:15568
[email protected]8ea5d4b2011-09-13 21:49:22569def _CheckNoNewWStrings(input_api, output_api):
570 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27571 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22572 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20573 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57574 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34575 '/win/' in f.LocalPath() or
576 'chrome_elf' in f.LocalPath() or
577 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20578 continue
[email protected]8ea5d4b2011-09-13 21:49:22579
[email protected]a11dbe9b2012-08-07 01:32:58580 allowWString = False
[email protected]b5c24292011-11-28 14:38:20581 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58582 if 'presubmit: allow wstring' in line:
583 allowWString = True
584 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27585 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58586 allowWString = False
587 else:
588 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22589
[email protected]55463aa62011-10-12 00:48:27590 if not problems:
591 return []
592 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58593 ' If you are calling a cross-platform API that accepts a wstring, '
594 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27595 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22596
597
[email protected]2a8ac9c2011-10-19 17:20:44598def _CheckNoDEPSGIT(input_api, output_api):
599 """Make sure .DEPS.git is never modified manually."""
600 if any(f.LocalPath().endswith('.DEPS.git') for f in
601 input_api.AffectedFiles()):
602 return [output_api.PresubmitError(
603 'Never commit changes to .DEPS.git. This file is maintained by an\n'
604 'automated system based on what\'s in DEPS and your changes will be\n'
605 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34606 '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:44607 'for more information')]
608 return []
609
610
tandriief664692014-09-23 14:51:47611def _CheckValidHostsInDEPS(input_api, output_api):
612 """Checks that DEPS file deps are from allowed_hosts."""
613 # Run only if DEPS file has been modified to annoy fewer bystanders.
614 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
615 return []
616 # Outsource work to gclient verify
617 try:
618 input_api.subprocess.check_output(['gclient', 'verify'])
619 return []
620 except input_api.subprocess.CalledProcessError, error:
621 return [output_api.PresubmitError(
622 'DEPS file must have only git dependencies.',
623 long_text=error.output)]
624
625
[email protected]127f18ec2012-06-16 05:05:59626def _CheckNoBannedFunctions(input_api, output_api):
627 """Make sure that banned functions are not used."""
628 warnings = []
629 errors = []
630
wnwenbdc444e2016-05-25 13:44:15631 def IsBlacklisted(affected_file, blacklist):
632 local_path = affected_file.LocalPath()
633 for item in blacklist:
634 if input_api.re.match(item, local_path):
635 return True
636 return False
637
638 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
639 matched = False
640 if func_name[0:1] == '/':
641 regex = func_name[1:]
642 if input_api.re.search(regex, line):
643 matched = True
644 elif func_name in line:
dchenge07de812016-06-20 19:27:17645 matched = True
wnwenbdc444e2016-05-25 13:44:15646 if matched:
dchenge07de812016-06-20 19:27:17647 problems = warnings
wnwenbdc444e2016-05-25 13:44:15648 if error:
dchenge07de812016-06-20 19:27:17649 problems = errors
wnwenbdc444e2016-05-25 13:44:15650 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
651 for message_line in message:
652 problems.append(' %s' % message_line)
653
[email protected]127f18ec2012-06-16 05:05:59654 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
655 for f in input_api.AffectedFiles(file_filter=file_filter):
656 for line_num, line in f.ChangedContents():
657 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15658 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59659
660 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
661 for f in input_api.AffectedFiles(file_filter=file_filter):
662 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49663 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49664 if IsBlacklisted(f, excluded_paths):
665 continue
wnwenbdc444e2016-05-25 13:44:15666 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59667
668 result = []
669 if (warnings):
670 result.append(output_api.PresubmitPromptWarning(
671 'Banned functions were used.\n' + '\n'.join(warnings)))
672 if (errors):
673 result.append(output_api.PresubmitError(
674 'Banned functions were used.\n' + '\n'.join(errors)))
675 return result
676
677
[email protected]6c063c62012-07-11 19:11:06678def _CheckNoPragmaOnce(input_api, output_api):
679 """Make sure that banned functions are not used."""
680 files = []
681 pattern = input_api.re.compile(r'^#pragma\s+once',
682 input_api.re.MULTILINE)
683 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
684 if not f.LocalPath().endswith('.h'):
685 continue
686 contents = input_api.ReadFile(f)
687 if pattern.search(contents):
688 files.append(f)
689
690 if files:
691 return [output_api.PresubmitError(
692 'Do not use #pragma once in header files.\n'
693 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
694 files)]
695 return []
696
[email protected]127f18ec2012-06-16 05:05:59697
[email protected]e7479052012-09-19 00:26:12698def _CheckNoTrinaryTrueFalse(input_api, output_api):
699 """Checks to make sure we don't introduce use of foo ? true : false."""
700 problems = []
701 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
702 for f in input_api.AffectedFiles():
703 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
704 continue
705
706 for line_num, line in f.ChangedContents():
707 if pattern.match(line):
708 problems.append(' %s:%d' % (f.LocalPath(), line_num))
709
710 if not problems:
711 return []
712 return [output_api.PresubmitPromptWarning(
713 'Please consider avoiding the "? true : false" pattern if possible.\n' +
714 '\n'.join(problems))]
715
716
[email protected]55f9f382012-07-31 11:02:18717def _CheckUnwantedDependencies(input_api, output_api):
718 """Runs checkdeps on #include statements added in this
719 change. Breaking - rules is an error, breaking ! rules is a
720 warning.
721 """
mohan.reddyf21db962014-10-16 12:26:47722 import sys
[email protected]55f9f382012-07-31 11:02:18723 # We need to wait until we have an input_api object and use this
724 # roundabout construct to import checkdeps because this file is
725 # eval-ed and thus doesn't have __file__.
726 original_sys_path = sys.path
727 try:
728 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47729 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18730 import checkdeps
731 from cpp_checker import CppChecker
732 from rules import Rule
733 finally:
734 # Restore sys.path to what it was before.
735 sys.path = original_sys_path
736
737 added_includes = []
738 for f in input_api.AffectedFiles():
739 if not CppChecker.IsCppFile(f.LocalPath()):
740 continue
741
742 changed_lines = [line for line_num, line in f.ChangedContents()]
743 added_includes.append([f.LocalPath(), changed_lines])
744
[email protected]26385172013-05-09 23:11:35745 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18746
747 error_descriptions = []
748 warning_descriptions = []
749 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
750 added_includes):
751 description_with_path = '%s\n %s' % (path, rule_description)
752 if rule_type == Rule.DISALLOW:
753 error_descriptions.append(description_with_path)
754 else:
755 warning_descriptions.append(description_with_path)
756
757 results = []
758 if error_descriptions:
759 results.append(output_api.PresubmitError(
760 'You added one or more #includes that violate checkdeps rules.',
761 error_descriptions))
762 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42763 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18764 'You added one or more #includes of files that are temporarily\n'
765 'allowed but being removed. Can you avoid introducing the\n'
766 '#include? See relevant DEPS file(s) for details and contacts.',
767 warning_descriptions))
768 return results
769
770
[email protected]fbcafe5a2012-08-08 15:31:22771def _CheckFilePermissions(input_api, output_api):
772 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15773 if input_api.platform == 'win32':
774 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29775 checkperms_tool = input_api.os_path.join(
776 input_api.PresubmitLocalPath(),
777 'tools', 'checkperms', 'checkperms.py')
778 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47779 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22780 for f in input_api.AffectedFiles():
781 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11782 try:
783 input_api.subprocess.check_output(args)
784 return []
785 except input_api.subprocess.CalledProcessError as error:
786 return [output_api.PresubmitError(
787 'checkperms.py failed:',
788 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22789
790
[email protected]c8278b32012-10-30 20:35:49791def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
792 """Makes sure we don't include ui/aura/window_property.h
793 in header files.
794 """
795 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
796 errors = []
797 for f in input_api.AffectedFiles():
798 if not f.LocalPath().endswith('.h'):
799 continue
800 for line_num, line in f.ChangedContents():
801 if pattern.match(line):
802 errors.append(' %s:%d' % (f.LocalPath(), line_num))
803
804 results = []
805 if errors:
806 results.append(output_api.PresubmitError(
807 'Header files should not include ui/aura/window_property.h', errors))
808 return results
809
810
[email protected]cf9b78f2012-11-14 11:40:28811def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
812 """Checks that the lines in scope occur in the right order.
813
814 1. C system files in alphabetical order
815 2. C++ system files in alphabetical order
816 3. Project's .h files
817 """
818
819 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
820 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
821 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
822
823 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
824
825 state = C_SYSTEM_INCLUDES
826
827 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57828 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28829 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55830 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28831 for line_num, line in scope:
832 if c_system_include_pattern.match(line):
833 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55834 problem_linenums.append((line_num, previous_line_num,
835 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28836 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55837 problem_linenums.append((line_num, previous_line_num,
838 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28839 elif cpp_system_include_pattern.match(line):
840 if state == C_SYSTEM_INCLUDES:
841 state = CPP_SYSTEM_INCLUDES
842 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55843 problem_linenums.append((line_num, previous_line_num,
844 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28845 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55846 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28847 elif custom_include_pattern.match(line):
848 if state != CUSTOM_INCLUDES:
849 state = CUSTOM_INCLUDES
850 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55851 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28852 else:
brucedawson70fadb02015-06-30 17:47:55853 problem_linenums.append((line_num, previous_line_num,
854 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28855 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57856 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28857
858 warnings = []
brucedawson70fadb02015-06-30 17:47:55859 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57860 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55861 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28862 return warnings
863
864
[email protected]ac294a12012-12-06 16:38:43865def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28866 """Checks the #include order for the given file f."""
867
[email protected]2299dcf2012-11-15 19:56:24868 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30869 # Exclude the following includes from the check:
870 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
871 # specific order.
872 # 2) <atlbase.h>, "build/build_config.h"
873 excluded_include_pattern = input_api.re.compile(
874 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24875 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33876 # Match the final or penultimate token if it is xxxtest so we can ignore it
877 # when considering the special first include.
878 test_file_tag_pattern = input_api.re.compile(
879 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11880 if_pattern = input_api.re.compile(
881 r'\s*#\s*(if|elif|else|endif|define|undef).*')
882 # Some files need specialized order of includes; exclude such files from this
883 # check.
884 uncheckable_includes_pattern = input_api.re.compile(
885 r'\s*#include '
886 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28887
888 contents = f.NewContents()
889 warnings = []
890 line_num = 0
891
[email protected]ac294a12012-12-06 16:38:43892 # Handle the special first include. If the first include file is
893 # some/path/file.h, the corresponding including file can be some/path/file.cc,
894 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
895 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33896 # If the included file is some/path/file_platform.h the including file could
897 # also be some/path/file_xxxtest_platform.h.
898 including_file_base_name = test_file_tag_pattern.sub(
899 '', input_api.os_path.basename(f.LocalPath()))
900
[email protected]ac294a12012-12-06 16:38:43901 for line in contents:
902 line_num += 1
903 if system_include_pattern.match(line):
904 # No special first include -> process the line again along with normal
905 # includes.
906 line_num -= 1
907 break
908 match = custom_include_pattern.match(line)
909 if match:
910 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33911 header_basename = test_file_tag_pattern.sub(
912 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
913
914 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24915 # No special first include -> process the line again along with normal
916 # includes.
917 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43918 break
[email protected]cf9b78f2012-11-14 11:40:28919
920 # Split into scopes: Each region between #if and #endif is its own scope.
921 scopes = []
922 current_scope = []
923 for line in contents[line_num:]:
924 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11925 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54926 continue
[email protected]2309b0fa02012-11-16 12:18:27927 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28928 scopes.append(current_scope)
929 current_scope = []
[email protected]962f117e2012-11-22 18:11:56930 elif ((system_include_pattern.match(line) or
931 custom_include_pattern.match(line)) and
932 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28933 current_scope.append((line_num, line))
934 scopes.append(current_scope)
935
936 for scope in scopes:
937 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
938 changed_linenums))
939 return warnings
940
941
942def _CheckIncludeOrder(input_api, output_api):
943 """Checks that the #include order is correct.
944
945 1. The corresponding header for source files.
946 2. C system files in alphabetical order
947 3. C++ system files in alphabetical order
948 4. Project's .h files in alphabetical order
949
[email protected]ac294a12012-12-06 16:38:43950 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
951 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28952 """
[email protected]e120b012014-08-15 19:08:35953 def FileFilterIncludeOrder(affected_file):
954 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
955 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28956
957 warnings = []
[email protected]e120b012014-08-15 19:08:35958 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08959 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43960 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
961 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28962
963 results = []
964 if warnings:
[email protected]f7051d52013-04-02 18:31:42965 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53966 warnings))
[email protected]cf9b78f2012-11-14 11:40:28967 return results
968
969
[email protected]70ca77752012-11-20 03:45:03970def _CheckForVersionControlConflictsInFile(input_api, f):
971 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
972 errors = []
973 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23974 if f.LocalPath().endswith('.md'):
975 # First-level headers in markdown look a lot like version control
976 # conflict markers. http://daringfireball.net/projects/markdown/basics
977 continue
[email protected]70ca77752012-11-20 03:45:03978 if pattern.match(line):
979 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
980 return errors
981
982
983def _CheckForVersionControlConflicts(input_api, output_api):
984 """Usually this is not intentional and will cause a compile failure."""
985 errors = []
986 for f in input_api.AffectedFiles():
987 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
988
989 results = []
990 if errors:
991 results.append(output_api.PresubmitError(
992 'Version control conflict markers found, please resolve.', errors))
993 return results
994
995
[email protected]06e6d0ff2012-12-11 01:36:44996def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
997 def FilterFile(affected_file):
998 """Filter function for use with input_api.AffectedSourceFiles,
999 below. This filters out everything except non-test files from
1000 top-level directories that generally speaking should not hard-code
1001 service URLs (e.g. src/android_webview/, src/content/ and others).
1002 """
1003 return input_api.FilterSourceFile(
1004 affected_file,
[email protected]78bb39d62012-12-11 15:11:561005 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:441006 black_list=(_EXCLUDED_PATHS +
1007 _TEST_CODE_EXCLUDED_PATHS +
1008 input_api.DEFAULT_BLACK_LIST))
1009
reillyi38965732015-11-16 18:27:331010 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1011 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461012 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1013 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441014 problems = [] # items are (filename, line_number, line)
1015 for f in input_api.AffectedSourceFiles(FilterFile):
1016 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461017 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441018 problems.append((f.LocalPath(), line_num, line))
1019
1020 if problems:
[email protected]f7051d52013-04-02 18:31:421021 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441022 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581023 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441024 [' %s:%d: %s' % (
1025 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031026 else:
1027 return []
[email protected]06e6d0ff2012-12-11 01:36:441028
1029
[email protected]d2530012013-01-25 16:39:271030def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1031 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311032 The native_client_sdk directory is excluded because it has auto-generated PNG
1033 files for documentation.
[email protected]d2530012013-01-25 16:39:271034 """
[email protected]d2530012013-01-25 16:39:271035 errors = []
binji0dcdf342014-12-12 18:32:311036 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1037 black_list = (r'^native_client_sdk[\\\/]',)
1038 file_filter = lambda f: input_api.FilterSourceFile(
1039 f, white_list=white_list, black_list=black_list)
1040 for f in input_api.AffectedFiles(include_deletes=False,
1041 file_filter=file_filter):
1042 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271043
1044 results = []
1045 if errors:
1046 results.append(output_api.PresubmitError(
1047 'The name of PNG files should not have abbreviations. \n'
1048 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1049 'Contact [email protected] if you have questions.', errors))
1050 return results
1051
1052
[email protected]14a6131c2014-01-08 01:15:411053def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081054 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411055 a set of DEPS entries that we should look up.
1056
1057 For a directory (rather than a specific filename) we fake a path to
1058 a specific filename by adding /DEPS. This is chosen as a file that
1059 will seldom or never be subject to per-file include_rules.
1060 """
[email protected]2b438d62013-11-14 17:54:141061 # We ignore deps entries on auto-generated directories.
1062 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081063
1064 # This pattern grabs the path without basename in the first
1065 # parentheses, and the basename (if present) in the second. It
1066 # relies on the simple heuristic that if there is a basename it will
1067 # be a header file ending in ".h".
1068 pattern = re.compile(
1069 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141070 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081071 for changed_line in changed_lines:
1072 m = pattern.match(changed_line)
1073 if m:
1074 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141075 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411076 if m.group(2):
1077 results.add('%s%s' % (path, m.group(2)))
1078 else:
1079 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081080 return results
1081
1082
[email protected]e871964c2013-05-13 14:14:551083def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1084 """When a dependency prefixed with + is added to a DEPS file, we
1085 want to make sure that the change is reviewed by an OWNER of the
1086 target file or directory, to avoid layering violations from being
1087 introduced. This check verifies that this happens.
1088 """
1089 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241090
1091 file_filter = lambda f: not input_api.re.match(
1092 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1093 for f in input_api.AffectedFiles(include_deletes=False,
1094 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551095 filename = input_api.os_path.basename(f.LocalPath())
1096 if filename == 'DEPS':
1097 changed_lines |= set(line.strip()
1098 for line_num, line
1099 in f.ChangedContents())
1100 if not changed_lines:
1101 return []
1102
[email protected]14a6131c2014-01-08 01:15:411103 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1104 changed_lines)
[email protected]e871964c2013-05-13 14:14:551105 if not virtual_depended_on_files:
1106 return []
1107
1108 if input_api.is_committing:
1109 if input_api.tbr:
1110 return [output_api.PresubmitNotifyResult(
1111 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271112 if input_api.dry_run:
1113 return [output_api.PresubmitNotifyResult(
1114 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551115 if not input_api.change.issue:
1116 return [output_api.PresubmitError(
1117 "DEPS approval by OWNERS check failed: this change has "
1118 "no Rietveld issue number, so we can't check it for approvals.")]
1119 output = output_api.PresubmitError
1120 else:
1121 output = output_api.PresubmitNotifyResult
1122
1123 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501124 owner_email, reviewers = (
1125 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1126 input_api,
1127 owners_db.email_regexp,
1128 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551129
1130 owner_email = owner_email or input_api.change.author_email
1131
[email protected]de4f7d22013-05-23 14:27:461132 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511133 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461134 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551135 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1136 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411137
1138 # We strip the /DEPS part that was added by
1139 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1140 # directory.
1141 def StripDeps(path):
1142 start_deps = path.rfind('/DEPS')
1143 if start_deps != -1:
1144 return path[:start_deps]
1145 else:
1146 return path
1147 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551148 for path in missing_files]
1149
1150 if unapproved_dependencies:
1151 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151152 output('You need LGTM from owners of depends-on paths in DEPS that were '
1153 'modified in this CL:\n %s' %
1154 '\n '.join(sorted(unapproved_dependencies)))]
1155 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1156 output_list.append(output(
1157 'Suggested missing target path OWNERS:\n %s' %
1158 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551159 return output_list
1160
1161 return []
1162
1163
[email protected]85218562013-11-22 07:41:401164def _CheckSpamLogging(input_api, output_api):
1165 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1166 black_list = (_EXCLUDED_PATHS +
1167 _TEST_CODE_EXCLUDED_PATHS +
1168 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501169 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191170 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481171 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461172 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121173 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1174 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581175 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161176 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031177 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151178 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1179 r"^chromecast[\\\/]",
1180 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311181 r"^components[\\\/]html_viewer[\\\/]"
1182 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461183 # TODO(peter): Remove this exception. https://crbug.com/534537
1184 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1185 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251186 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1187 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241188 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111189 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151190 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111191 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521192 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501193 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361194 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311195 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131196 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441197 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451198 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021199 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441200 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401201 source_file_filter = lambda x: input_api.FilterSourceFile(
1202 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1203
1204 log_info = []
1205 printf = []
1206
1207 for f in input_api.AffectedSourceFiles(source_file_filter):
1208 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471209 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401210 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471211 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131212 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371213
mohan.reddyf21db962014-10-16 12:26:471214 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371215 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471216 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401217 printf.append(f.LocalPath())
1218
1219 if log_info:
1220 return [output_api.PresubmitError(
1221 'These files spam the console log with LOG(INFO):',
1222 items=log_info)]
1223 if printf:
1224 return [output_api.PresubmitError(
1225 'These files spam the console log with printf/fprintf:',
1226 items=printf)]
1227 return []
1228
1229
[email protected]49aa76a2013-12-04 06:59:161230def _CheckForAnonymousVariables(input_api, output_api):
1231 """These types are all expected to hold locks while in scope and
1232 so should never be anonymous (which causes them to be immediately
1233 destroyed)."""
1234 they_who_must_be_named = [
1235 'base::AutoLock',
1236 'base::AutoReset',
1237 'base::AutoUnlock',
1238 'SkAutoAlphaRestore',
1239 'SkAutoBitmapShaderInstall',
1240 'SkAutoBlitterChoose',
1241 'SkAutoBounderCommit',
1242 'SkAutoCallProc',
1243 'SkAutoCanvasRestore',
1244 'SkAutoCommentBlock',
1245 'SkAutoDescriptor',
1246 'SkAutoDisableDirectionCheck',
1247 'SkAutoDisableOvalCheck',
1248 'SkAutoFree',
1249 'SkAutoGlyphCache',
1250 'SkAutoHDC',
1251 'SkAutoLockColors',
1252 'SkAutoLockPixels',
1253 'SkAutoMalloc',
1254 'SkAutoMaskFreeImage',
1255 'SkAutoMutexAcquire',
1256 'SkAutoPathBoundsUpdate',
1257 'SkAutoPDFRelease',
1258 'SkAutoRasterClipValidate',
1259 'SkAutoRef',
1260 'SkAutoTime',
1261 'SkAutoTrace',
1262 'SkAutoUnref',
1263 ]
1264 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1265 # bad: base::AutoLock(lock.get());
1266 # not bad: base::AutoLock lock(lock.get());
1267 bad_pattern = input_api.re.compile(anonymous)
1268 # good: new base::AutoLock(lock.get())
1269 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1270 errors = []
1271
1272 for f in input_api.AffectedFiles():
1273 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1274 continue
1275 for linenum, line in f.ChangedContents():
1276 if bad_pattern.search(line) and not good_pattern.search(line):
1277 errors.append('%s:%d' % (f.LocalPath(), linenum))
1278
1279 if errors:
1280 return [output_api.PresubmitError(
1281 'These lines create anonymous variables that need to be named:',
1282 items=errors)]
1283 return []
1284
1285
[email protected]5fe0f8742013-11-29 01:04:591286def _CheckCygwinShell(input_api, output_api):
1287 source_file_filter = lambda x: input_api.FilterSourceFile(
1288 x, white_list=(r'.+\.(gyp|gypi)$',))
1289 cygwin_shell = []
1290
1291 for f in input_api.AffectedSourceFiles(source_file_filter):
1292 for linenum, line in f.ChangedContents():
1293 if 'msvs_cygwin_shell' in line:
1294 cygwin_shell.append(f.LocalPath())
1295 break
1296
1297 if cygwin_shell:
1298 return [output_api.PresubmitError(
1299 'These files should not use msvs_cygwin_shell (the default is 0):',
1300 items=cygwin_shell)]
1301 return []
1302
[email protected]85218562013-11-22 07:41:401303
[email protected]999261d2014-03-03 20:08:081304def _CheckUserActionUpdate(input_api, output_api):
1305 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521306 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081307 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521308 # If actions.xml is already included in the changelist, the PRESUBMIT
1309 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081310 return []
1311
[email protected]999261d2014-03-03 20:08:081312 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1313 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521314 current_actions = None
[email protected]999261d2014-03-03 20:08:081315 for f in input_api.AffectedFiles(file_filter=file_filter):
1316 for line_num, line in f.ChangedContents():
1317 match = input_api.re.search(action_re, line)
1318 if match:
[email protected]2f92dec2014-03-07 19:21:521319 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1320 # loaded only once.
1321 if not current_actions:
1322 with open('tools/metrics/actions/actions.xml') as actions_f:
1323 current_actions = actions_f.read()
1324 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081325 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521326 action = 'name="{0}"'.format(action_name)
1327 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081328 return [output_api.PresubmitPromptWarning(
1329 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521330 'tools/metrics/actions/actions.xml. Please run '
1331 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081332 % (f.LocalPath(), line_num, action_name))]
1333 return []
1334
1335
[email protected]99171a92014-06-03 08:44:471336def _GetJSONParseError(input_api, filename, eat_comments=True):
1337 try:
1338 contents = input_api.ReadFile(filename)
1339 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131340 import sys
1341 original_sys_path = sys.path
1342 try:
1343 sys.path = sys.path + [input_api.os_path.join(
1344 input_api.PresubmitLocalPath(),
1345 'tools', 'json_comment_eater')]
1346 import json_comment_eater
1347 finally:
1348 sys.path = original_sys_path
1349 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471350
1351 input_api.json.loads(contents)
1352 except ValueError as e:
1353 return e
1354 return None
1355
1356
1357def _GetIDLParseError(input_api, filename):
1358 try:
1359 contents = input_api.ReadFile(filename)
1360 idl_schema = input_api.os_path.join(
1361 input_api.PresubmitLocalPath(),
1362 'tools', 'json_schema_compiler', 'idl_schema.py')
1363 process = input_api.subprocess.Popen(
1364 [input_api.python_executable, idl_schema],
1365 stdin=input_api.subprocess.PIPE,
1366 stdout=input_api.subprocess.PIPE,
1367 stderr=input_api.subprocess.PIPE,
1368 universal_newlines=True)
1369 (_, error) = process.communicate(input=contents)
1370 return error or None
1371 except ValueError as e:
1372 return e
1373
1374
1375def _CheckParseErrors(input_api, output_api):
1376 """Check that IDL and JSON files do not contain syntax errors."""
1377 actions = {
1378 '.idl': _GetIDLParseError,
1379 '.json': _GetJSONParseError,
1380 }
1381 # These paths contain test data and other known invalid JSON files.
1382 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491383 r'test[\\\/]data[\\\/]',
1384 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471385 ]
1386 # Most JSON files are preprocessed and support comments, but these do not.
1387 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491388 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471389 ]
1390 # Only run IDL checker on files in these directories.
1391 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491392 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1393 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471394 ]
1395
1396 def get_action(affected_file):
1397 filename = affected_file.LocalPath()
1398 return actions.get(input_api.os_path.splitext(filename)[1])
1399
1400 def MatchesFile(patterns, path):
1401 for pattern in patterns:
1402 if input_api.re.search(pattern, path):
1403 return True
1404 return False
1405
1406 def FilterFile(affected_file):
1407 action = get_action(affected_file)
1408 if not action:
1409 return False
1410 path = affected_file.LocalPath()
1411
1412 if MatchesFile(excluded_patterns, path):
1413 return False
1414
1415 if (action == _GetIDLParseError and
1416 not MatchesFile(idl_included_patterns, path)):
1417 return False
1418 return True
1419
1420 results = []
1421 for affected_file in input_api.AffectedFiles(
1422 file_filter=FilterFile, include_deletes=False):
1423 action = get_action(affected_file)
1424 kwargs = {}
1425 if (action == _GetJSONParseError and
1426 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1427 kwargs['eat_comments'] = False
1428 parse_error = action(input_api,
1429 affected_file.AbsoluteLocalPath(),
1430 **kwargs)
1431 if parse_error:
1432 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1433 (affected_file.LocalPath(), parse_error)))
1434 return results
1435
1436
[email protected]760deea2013-12-10 19:33:491437def _CheckJavaStyle(input_api, output_api):
1438 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471439 import sys
[email protected]760deea2013-12-10 19:33:491440 original_sys_path = sys.path
1441 try:
1442 sys.path = sys.path + [input_api.os_path.join(
1443 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1444 import checkstyle
1445 finally:
1446 # Restore sys.path to what it was before.
1447 sys.path = original_sys_path
1448
1449 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091450 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511451 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491452
1453
dchenge07de812016-06-20 19:27:171454def _CheckIpcOwners(input_api, output_api):
1455 """Checks that affected files involving IPC have an IPC OWNERS rule.
1456
1457 Whether or not a file affects IPC is determined by a simple whitelist of
1458 filename patterns."""
1459 file_patterns = [
1460 '*_messages.cc',
1461 '*_messages*.h',
1462 '*_param_traits*.*',
1463 '*.mojom',
1464 '*_struct_traits*.*',
1465 '*_type_converter*.*',
1466 # Blink uses a different file naming convention
1467 '*StructTraits*.*',
1468 '*TypeConverter*.*',
1469 ]
1470
1471 # Dictionary mapping an OWNERS file path to Patterns.
1472 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1473 # rules ) to a PatternEntry.
1474 # PatternEntry is a dictionary with two keys:
1475 # - 'files': the files that are matched by this pattern
1476 # - 'rules': the per-file rules needed for this pattern
1477 # For example, if we expect OWNERS file to contain rules for *.mojom and
1478 # *_struct_traits*.*, Patterns might look like this:
1479 # {
1480 # '*.mojom': {
1481 # 'files': ...,
1482 # 'rules': [
1483 # 'per-file *.mojom=set noparent',
1484 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1485 # ],
1486 # },
1487 # '*_struct_traits*.*': {
1488 # 'files': ...,
1489 # 'rules': [
1490 # 'per-file *_struct_traits*.*=set noparent',
1491 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1492 # ],
1493 # },
1494 # }
1495 to_check = {}
1496
1497 # Iterate through the affected files to see what we actually need to check
1498 # for. We should only nag patch authors about per-file rules if a file in that
1499 # directory would match that pattern. If a directory only contains *.mojom
1500 # files and no *_messages*.h files, we should only nag about rules for
1501 # *.mojom files.
rockot51249332016-06-23 16:32:251502 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171503 for pattern in file_patterns:
1504 if input_api.fnmatch.fnmatch(
1505 input_api.os_path.basename(f.LocalPath()), pattern):
1506 owners_file = input_api.os_path.join(
1507 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1508 if owners_file not in to_check:
1509 to_check[owners_file] = {}
1510 if pattern not in to_check[owners_file]:
1511 to_check[owners_file][pattern] = {
1512 'files': [],
1513 'rules': [
1514 'per-file %s=set noparent' % pattern,
1515 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1516 ]
1517 }
1518 to_check[owners_file][pattern]['files'].append(f)
1519 break
1520
1521 # Now go through the OWNERS files we collected, filtering out rules that are
1522 # already present in that OWNERS file.
1523 for owners_file, patterns in to_check.iteritems():
1524 try:
1525 with file(owners_file) as f:
1526 lines = set(f.read().splitlines())
1527 for entry in patterns.itervalues():
1528 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1529 ]
1530 except IOError:
1531 # No OWNERS file, so all the rules are definitely missing.
1532 continue
1533
1534 # All the remaining lines weren't found in OWNERS files, so emit an error.
1535 errors = []
1536 for owners_file, patterns in to_check.iteritems():
1537 missing_lines = []
1538 files = []
1539 for pattern, entry in patterns.iteritems():
1540 missing_lines.extend(entry['rules'])
1541 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1542 if missing_lines:
1543 errors.append(
1544 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1545 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1546
1547 results = []
1548 if errors:
vabrf5ce3bf92016-07-11 14:52:411549 if input_api.is_committing:
1550 output = output_api.PresubmitError
1551 else:
1552 output = output_api.PresubmitPromptWarning
1553 results.append(output(
dchenge07de812016-06-20 19:27:171554 'Found changes to IPC files without a security OWNER!',
1555 long_text='\n\n'.join(errors)))
1556
1557 return results
1558
1559
yzshend99f726a2016-07-25 21:44:231560def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1561 """Checks to make sure that all newly added mojom targets map array/map/string
1562 to STL (for chromium) or WTF (for blink) types.
1563 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1564 """
1565 files = []
1566 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1567 input_api.re.MULTILINE)
1568
1569 for f in input_api.AffectedFiles():
1570 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1571 continue
1572
1573 for _, line in f.ChangedContents():
1574 if pattern.search(line):
1575 files.append(f)
1576 break
1577
1578 if len(files):
1579 return [output_api.PresubmitError(
1580 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1581 'false. The mode is deprecated and will be removed soon.',
1582 files)]
1583 return []
1584
1585
dskiba88634f4e2015-08-14 23:03:291586def _CheckAndroidToastUsage(input_api, output_api):
1587 """Checks that code uses org.chromium.ui.widget.Toast instead of
1588 android.widget.Toast (Chromium Toast doesn't force hardware
1589 acceleration on low-end devices, saving memory).
1590 """
1591 toast_import_pattern = input_api.re.compile(
1592 r'^import android\.widget\.Toast;$')
1593
1594 errors = []
1595
1596 sources = lambda affected_file: input_api.FilterSourceFile(
1597 affected_file,
1598 black_list=(_EXCLUDED_PATHS +
1599 _TEST_CODE_EXCLUDED_PATHS +
1600 input_api.DEFAULT_BLACK_LIST +
1601 (r'^chromecast[\\\/].*',
1602 r'^remoting[\\\/].*')),
1603 white_list=(r'.*\.java$',))
1604
1605 for f in input_api.AffectedSourceFiles(sources):
1606 for line_num, line in f.ChangedContents():
1607 if toast_import_pattern.search(line):
1608 errors.append("%s:%d" % (f.LocalPath(), line_num))
1609
1610 results = []
1611
1612 if errors:
1613 results.append(output_api.PresubmitError(
1614 'android.widget.Toast usage is detected. Android toasts use hardware'
1615 ' acceleration, and can be\ncostly on low-end devices. Please use'
1616 ' org.chromium.ui.widget.Toast instead.\n'
1617 'Contact [email protected] if you have any questions.',
1618 errors))
1619
1620 return results
1621
1622
dgnaa68d5e2015-06-10 10:08:221623def _CheckAndroidCrLogUsage(input_api, output_api):
1624 """Checks that new logs using org.chromium.base.Log:
1625 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511626 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221627 """
pkotwicza1dd0b002016-05-16 14:41:041628
1629 # Do not check format of logs in //chrome/android/webapk because
1630 # //chrome/android/webapk cannot depend on //base
1631 cr_log_check_excluded_paths = [
1632 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1633 ]
1634
dgnaa68d5e2015-06-10 10:08:221635 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121636 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1637 class_in_base_pattern = input_api.re.compile(
1638 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1639 has_some_log_import_pattern = input_api.re.compile(
1640 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221641 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121642 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221643 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511644 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221645 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221646
Vincent Scheib16d7b272015-09-15 18:09:071647 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221648 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041649 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1650 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121651
dgnaa68d5e2015-06-10 10:08:221652 tag_decl_errors = []
1653 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121654 tag_errors = []
dgn38736db2015-09-18 19:20:511655 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121656 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221657
1658 for f in input_api.AffectedSourceFiles(sources):
1659 file_content = input_api.ReadFile(f)
1660 has_modified_logs = False
1661
1662 # Per line checks
dgn87d9fb62015-06-12 09:15:121663 if (cr_log_import_pattern.search(file_content) or
1664 (class_in_base_pattern.search(file_content) and
1665 not has_some_log_import_pattern.search(file_content))):
1666 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221667 for line_num, line in f.ChangedContents():
1668
1669 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121670 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221671 if match:
1672 has_modified_logs = True
1673
1674 # Make sure it uses "TAG"
1675 if not match.group('tag') == 'TAG':
1676 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121677 else:
1678 # Report non cr Log function calls in changed lines
1679 for line_num, line in f.ChangedContents():
1680 if log_call_pattern.search(line):
1681 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221682
1683 # Per file checks
1684 if has_modified_logs:
1685 # Make sure the tag is using the "cr" prefix and is not too long
1686 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511687 tag_name = match.group('name') if match else None
1688 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221689 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511690 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221691 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511692 elif '.' in tag_name:
1693 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221694
1695 results = []
1696 if tag_decl_errors:
1697 results.append(output_api.PresubmitPromptWarning(
1698 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511699 '"private static final String TAG = "<package tag>".\n'
1700 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221701 tag_decl_errors))
1702
1703 if tag_length_errors:
1704 results.append(output_api.PresubmitError(
1705 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511706 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221707 tag_length_errors))
1708
1709 if tag_errors:
1710 results.append(output_api.PresubmitPromptWarning(
1711 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1712 tag_errors))
1713
dgn87d9fb62015-06-12 09:15:121714 if util_log_errors:
dgn4401aa52015-04-29 16:26:171715 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121716 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1717 util_log_errors))
1718
dgn38736db2015-09-18 19:20:511719 if tag_with_dot_errors:
1720 results.append(output_api.PresubmitPromptWarning(
1721 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1722 tag_with_dot_errors))
1723
dgn4401aa52015-04-29 16:26:171724 return results
1725
1726
agrieve7b6479d82015-10-07 14:24:221727def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1728 """Checks if MDPI assets are placed in a correct directory."""
1729 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1730 ('/res/drawable/' in f.LocalPath() or
1731 '/res/drawable-ldrtl/' in f.LocalPath()))
1732 errors = []
1733 for f in input_api.AffectedFiles(include_deletes=False,
1734 file_filter=file_filter):
1735 errors.append(' %s' % f.LocalPath())
1736
1737 results = []
1738 if errors:
1739 results.append(output_api.PresubmitError(
1740 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1741 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1742 '/res/drawable-ldrtl/.\n'
1743 'Contact [email protected] if you have questions.', errors))
1744 return results
1745
1746
agrievef32bcc72016-04-04 14:57:401747class PydepsChecker(object):
1748 def __init__(self, input_api, pydeps_files):
1749 self._file_cache = {}
1750 self._input_api = input_api
1751 self._pydeps_files = pydeps_files
1752
1753 def _LoadFile(self, path):
1754 """Returns the list of paths within a .pydeps file relative to //."""
1755 if path not in self._file_cache:
1756 with open(path) as f:
1757 self._file_cache[path] = f.read()
1758 return self._file_cache[path]
1759
1760 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1761 """Returns an interable of paths within the .pydep, relativized to //."""
1762 os_path = self._input_api.os_path
1763 pydeps_dir = os_path.dirname(pydeps_path)
1764 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1765 if not l.startswith('*'))
1766 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1767
1768 def _CreateFilesToPydepsMap(self):
1769 """Returns a map of local_path -> list_of_pydeps."""
1770 ret = {}
1771 for pydep_local_path in self._pydeps_files:
1772 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1773 ret.setdefault(path, []).append(pydep_local_path)
1774 return ret
1775
1776 def ComputeAffectedPydeps(self):
1777 """Returns an iterable of .pydeps files that might need regenerating."""
1778 affected_pydeps = set()
1779 file_to_pydeps_map = None
1780 for f in self._input_api.AffectedFiles(include_deletes=True):
1781 local_path = f.LocalPath()
1782 if local_path == 'DEPS':
1783 return self._pydeps_files
1784 elif local_path.endswith('.pydeps'):
1785 if local_path in self._pydeps_files:
1786 affected_pydeps.add(local_path)
1787 elif local_path.endswith('.py'):
1788 if file_to_pydeps_map is None:
1789 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1790 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1791 return affected_pydeps
1792
1793 def DetermineIfStale(self, pydeps_path):
1794 """Runs print_python_deps.py to see if the files is stale."""
1795 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1796 cmd = old_pydeps_data[1][1:].strip()
1797 new_pydeps_data = self._input_api.subprocess.check_output(
1798 cmd + ' --output ""', shell=True)
1799 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1800 return cmd
1801
1802
1803def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1804 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001805 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281806 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1807 # Mac, so skip it on other platforms.
1808 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001809 return []
agrievef32bcc72016-04-04 14:57:401810 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1811 is_android = input_api.os_path.exists('third_party/android_tools')
1812 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1813 results = []
1814 # First, check for new / deleted .pydeps.
1815 for f in input_api.AffectedFiles(include_deletes=True):
1816 if f.LocalPath().endswith('.pydeps'):
1817 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1818 results.append(output_api.PresubmitError(
1819 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1820 'remove %s' % f.LocalPath()))
1821 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1822 results.append(output_api.PresubmitError(
1823 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1824 'include %s' % f.LocalPath()))
1825
1826 if results:
1827 return results
1828
1829 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1830
1831 for pydep_path in checker.ComputeAffectedPydeps():
1832 try:
1833 cmd = checker.DetermineIfStale(pydep_path)
1834 if cmd:
1835 results.append(output_api.PresubmitError(
1836 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1837 (pydep_path, cmd)))
1838 except input_api.subprocess.CalledProcessError as error:
1839 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1840 long_text=error.output)]
1841
1842 return results
1843
1844
glidere61efad2015-02-18 17:39:431845def _CheckSingletonInHeaders(input_api, output_api):
1846 """Checks to make sure no header files have |Singleton<|."""
1847 def FileFilter(affected_file):
1848 # It's ok for base/memory/singleton.h to have |Singleton<|.
1849 black_list = (_EXCLUDED_PATHS +
1850 input_api.DEFAULT_BLACK_LIST +
1851 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1852 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1853
sergeyu34d21222015-09-16 00:11:441854 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431855 files = []
1856 for f in input_api.AffectedSourceFiles(FileFilter):
1857 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1858 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1859 contents = input_api.ReadFile(f)
1860 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241861 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431862 pattern.search(line)):
1863 files.append(f)
1864 break
1865
1866 if files:
yolandyandaabc6d2016-04-18 18:29:391867 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441868 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431869 'Please move them to an appropriate source file so that the ' +
1870 'template gets instantiated in a single compilation unit.',
1871 files) ]
1872 return []
1873
1874
dbeam37e8e7402016-02-10 22:58:201875def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1876 """Checks for old style compiled_resources.gyp files."""
1877 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1878
1879 added_compiled_resources = filter(is_compiled_resource, [
1880 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1881 ])
1882
1883 if not added_compiled_resources:
1884 return []
1885
1886 return [output_api.PresubmitError(
1887 "Found new compiled_resources.gyp files:\n%s\n\n"
1888 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551889 "please use compiled_resources2.gyp instead:\n"
1890 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1891 %
dbeam37e8e7402016-02-10 22:58:201892 "\n".join(added_compiled_resources))]
1893
1894
[email protected]fd20b902014-05-09 02:14:531895_DEPRECATED_CSS = [
1896 # Values
1897 ( "-webkit-box", "flex" ),
1898 ( "-webkit-inline-box", "inline-flex" ),
1899 ( "-webkit-flex", "flex" ),
1900 ( "-webkit-inline-flex", "inline-flex" ),
1901 ( "-webkit-min-content", "min-content" ),
1902 ( "-webkit-max-content", "max-content" ),
1903
1904 # Properties
1905 ( "-webkit-background-clip", "background-clip" ),
1906 ( "-webkit-background-origin", "background-origin" ),
1907 ( "-webkit-background-size", "background-size" ),
1908 ( "-webkit-box-shadow", "box-shadow" ),
1909
1910 # Functions
1911 ( "-webkit-gradient", "gradient" ),
1912 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1913 ( "-webkit-linear-gradient", "linear-gradient" ),
1914 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1915 ( "-webkit-radial-gradient", "radial-gradient" ),
1916 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1917]
1918
1919def _CheckNoDeprecatedCSS(input_api, output_api):
1920 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251921 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341922 documentation and iOS CSS for dom distiller
1923 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251924 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531925 results = []
dbeam070cfe62014-10-22 06:44:021926 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251927 black_list = (_EXCLUDED_PATHS +
1928 _TEST_CODE_EXCLUDED_PATHS +
1929 input_api.DEFAULT_BLACK_LIST +
1930 (r"^chrome/common/extensions/docs",
1931 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341932 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051933 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441934 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251935 r"^native_client_sdk"))
1936 file_filter = lambda f: input_api.FilterSourceFile(
1937 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531938 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1939 for line_num, line in fpath.ChangedContents():
1940 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021941 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531942 results.append(output_api.PresubmitError(
1943 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1944 (fpath.LocalPath(), line_num, deprecated_value, value)))
1945 return results
1946
mohan.reddyf21db962014-10-16 12:26:471947
dbeam070cfe62014-10-22 06:44:021948_DEPRECATED_JS = [
1949 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1950 ( "__defineGetter__", "Object.defineProperty" ),
1951 ( "__defineSetter__", "Object.defineProperty" ),
1952]
1953
1954def _CheckNoDeprecatedJS(input_api, output_api):
1955 """Make sure that we don't use deprecated JS in Chrome code."""
1956 results = []
1957 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1958 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1959 input_api.DEFAULT_BLACK_LIST)
1960 file_filter = lambda f: input_api.FilterSourceFile(
1961 f, white_list=file_inclusion_pattern, black_list=black_list)
1962 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1963 for lnum, line in fpath.ChangedContents():
1964 for (deprecated, replacement) in _DEPRECATED_JS:
1965 if deprecated in line:
1966 results.append(output_api.PresubmitError(
1967 "%s:%d: Use of deprecated JS %s, use %s instead" %
1968 (fpath.LocalPath(), lnum, deprecated, replacement)))
1969 return results
1970
1971
dgnaa68d5e2015-06-10 10:08:221972def _AndroidSpecificOnUploadChecks(input_api, output_api):
1973 """Groups checks that target android code."""
1974 results = []
dgnaa68d5e2015-06-10 10:08:221975 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221976 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291977 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221978 return results
1979
1980
[email protected]22c9bd72011-03-27 16:47:391981def _CommonChecks(input_api, output_api):
1982 """Checks common to both upload and commit."""
1983 results = []
1984 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381985 input_api, output_api,
1986 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461987 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191988 results.extend(
[email protected]760deea2013-12-10 19:33:491989 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541990 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181991 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521992 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221993 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441994 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591995 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061996 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121997 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181998 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221999 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492000 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272001 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032002 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492003 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442004 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272005 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542006 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442007 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392008 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552009 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042010 results.extend(
2011 input_api.canned_checks.CheckChangeHasNoTabs(
2012 input_api,
2013 output_api,
2014 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402015 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162016 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592017 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082018 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:532019 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:022020 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472021 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042022 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232023 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432024 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:202025 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402026 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152027 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172028 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232029 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242030
2031 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2032 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2033 input_api, output_api,
2034 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382035 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392036 return results
[email protected]1f7b4172010-01-28 01:17:342037
[email protected]b337cb5b2011-01-23 21:24:052038
[email protected]66daa702011-05-28 14:41:462039def _CheckAuthorizedAuthor(input_api, output_api):
2040 """For non-googler/chromites committers, verify the author's email address is
2041 in AUTHORS.
2042 """
2043 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012044 if not author:
2045 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462046 return []
[email protected]c99663292011-05-31 19:46:082047 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462048 input_api.PresubmitLocalPath(), 'AUTHORS')
2049 valid_authors = (
2050 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2051 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182052 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172053 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2054 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232055 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462056 return [output_api.PresubmitPromptWarning(
2057 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2058 '\n'
2059 'http://www.chromium.org/developers/contributing-code and read the '
2060 '"Legal" section\n'
2061 'If you are a chromite, verify the contributor signed the CLA.') %
2062 author)]
2063 return []
2064
2065
[email protected]b8079ae4a2012-12-05 19:56:492066def _CheckPatchFiles(input_api, output_api):
2067 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2068 if f.LocalPath().endswith(('.orig', '.rej'))]
2069 if problems:
2070 return [output_api.PresubmitError(
2071 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032072 else:
2073 return []
[email protected]b8079ae4a2012-12-05 19:56:492074
2075
[email protected]b00342e7f2013-03-26 16:21:542076def _DidYouMeanOSMacro(bad_macro):
2077 try:
2078 return {'A': 'OS_ANDROID',
2079 'B': 'OS_BSD',
2080 'C': 'OS_CHROMEOS',
2081 'F': 'OS_FREEBSD',
2082 'L': 'OS_LINUX',
2083 'M': 'OS_MACOSX',
2084 'N': 'OS_NACL',
2085 'O': 'OS_OPENBSD',
2086 'P': 'OS_POSIX',
2087 'S': 'OS_SOLARIS',
2088 'W': 'OS_WIN'}[bad_macro[3].upper()]
2089 except KeyError:
2090 return ''
2091
2092
2093def _CheckForInvalidOSMacrosInFile(input_api, f):
2094 """Check for sensible looking, totally invalid OS macros."""
2095 preprocessor_statement = input_api.re.compile(r'^\s*#')
2096 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2097 results = []
2098 for lnum, line in f.ChangedContents():
2099 if preprocessor_statement.search(line):
2100 for match in os_macro.finditer(line):
2101 if not match.group(1) in _VALID_OS_MACROS:
2102 good = _DidYouMeanOSMacro(match.group(1))
2103 did_you_mean = ' (did you mean %s?)' % good if good else ''
2104 results.append(' %s:%d %s%s' % (f.LocalPath(),
2105 lnum,
2106 match.group(1),
2107 did_you_mean))
2108 return results
2109
2110
2111def _CheckForInvalidOSMacros(input_api, output_api):
2112 """Check all affected files for invalid OS macros."""
2113 bad_macros = []
2114 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472115 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542116 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2117
2118 if not bad_macros:
2119 return []
2120
2121 return [output_api.PresubmitError(
2122 'Possibly invalid OS macro[s] found. Please fix your code\n'
2123 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2124
lliabraa35bab3932014-10-01 12:16:442125
2126def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2127 """Check all affected files for invalid "if defined" macros."""
2128 ALWAYS_DEFINED_MACROS = (
2129 "TARGET_CPU_PPC",
2130 "TARGET_CPU_PPC64",
2131 "TARGET_CPU_68K",
2132 "TARGET_CPU_X86",
2133 "TARGET_CPU_ARM",
2134 "TARGET_CPU_MIPS",
2135 "TARGET_CPU_SPARC",
2136 "TARGET_CPU_ALPHA",
2137 "TARGET_IPHONE_SIMULATOR",
2138 "TARGET_OS_EMBEDDED",
2139 "TARGET_OS_IPHONE",
2140 "TARGET_OS_MAC",
2141 "TARGET_OS_UNIX",
2142 "TARGET_OS_WIN32",
2143 )
2144 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2145 results = []
2146 for lnum, line in f.ChangedContents():
2147 for match in ifdef_macro.finditer(line):
2148 if match.group(1) in ALWAYS_DEFINED_MACROS:
2149 always_defined = ' %s is always defined. ' % match.group(1)
2150 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2151 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2152 lnum,
2153 always_defined,
2154 did_you_mean))
2155 return results
2156
2157
2158def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2159 """Check all affected files for invalid "if defined" macros."""
2160 bad_macros = []
2161 for f in input_api.AffectedFiles():
2162 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2163 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2164
2165 if not bad_macros:
2166 return []
2167
2168 return [output_api.PresubmitError(
2169 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2170 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2171 bad_macros)]
2172
2173
mlamouria82272622014-09-16 18:45:042174def _CheckForIPCRules(input_api, output_api):
2175 """Check for same IPC rules described in
2176 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2177 """
2178 base_pattern = r'IPC_ENUM_TRAITS\('
2179 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2180 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2181
2182 problems = []
2183 for f in input_api.AffectedSourceFiles(None):
2184 local_path = f.LocalPath()
2185 if not local_path.endswith('.h'):
2186 continue
2187 for line_number, line in f.ChangedContents():
2188 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2189 problems.append(
2190 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2191
2192 if problems:
2193 return [output_api.PresubmitPromptWarning(
2194 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2195 else:
2196 return []
2197
[email protected]b00342e7f2013-03-26 16:21:542198
mostynbb639aca52015-01-07 20:31:232199def _CheckForWindowsLineEndings(input_api, output_api):
2200 """Check source code and known ascii text files for Windows style line
2201 endings.
2202 """
earthdok1b5e0ee2015-03-10 15:19:102203 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232204
2205 file_inclusion_pattern = (
2206 known_text_files,
2207 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2208 )
2209
2210 filter = lambda f: input_api.FilterSourceFile(
2211 f, white_list=file_inclusion_pattern, black_list=None)
2212 files = [f.LocalPath() for f in
2213 input_api.AffectedSourceFiles(filter)]
2214
2215 problems = []
2216
2217 for file in files:
2218 fp = open(file, 'r')
2219 for line in fp:
2220 if line.endswith('\r\n'):
2221 problems.append(file)
2222 break
2223 fp.close()
2224
2225 if problems:
2226 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2227 'these files to contain Windows style line endings?\n' +
2228 '\n'.join(problems))]
2229
2230 return []
2231
2232
pastarmovj89f7ee12016-09-20 14:58:132233def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2234 lint_filters=None, verbose_level=None):
2235 """Checks that all source files use SYSLOG properly."""
2236 syslog_files = []
2237 for f in input_api.AffectedSourceFiles(source_file_filter):
2238 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2239 syslog_files.append(f.LocalPath())
2240 if syslog_files:
2241 return [output_api.PresubmitPromptWarning(
2242 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2243 ' calls.\nFiles to check:\n', items=syslog_files)]
2244 return []
2245
2246
[email protected]1f7b4172010-01-28 01:17:342247def CheckChangeOnUpload(input_api, output_api):
2248 results = []
2249 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472250 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282251 results.extend(
2252 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192253 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222254 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132255 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542256 return results
[email protected]ca8d19842009-02-19 16:33:122257
2258
[email protected]1bfb8322014-04-23 01:02:412259def GetTryServerMasterForBot(bot):
2260 """Returns the Try Server master for the given bot.
2261
[email protected]0bb112362014-07-26 04:38:322262 It tries to guess the master from the bot name, but may still fail
2263 and return None. There is no longer a default master.
2264 """
2265 # Potentially ambiguous bot names are listed explicitly.
2266 master_map = {
tandriie5587792016-07-14 00:34:502267 'chromium_presubmit': 'master.tryserver.chromium.linux',
2268 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412269 }
[email protected]0bb112362014-07-26 04:38:322270 master = master_map.get(bot)
2271 if not master:
wnwen4fbaab82016-05-25 12:54:362272 if 'android' in bot:
tandriie5587792016-07-14 00:34:502273 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362274 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502275 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322276 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502277 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322278 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502279 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322280 return master
[email protected]1bfb8322014-04-23 01:02:412281
2282
Paweł Hajdan, Jr55083782014-12-19 20:32:562283def GetDefaultTryConfigs(bots):
2284 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012285 """
2286
Paweł Hajdan, Jr55083782014-12-19 20:32:562287 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412288
2289 # Build up the mapping from tryserver master to bot/test.
2290 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562291 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412292 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2293 return out
[email protected]38c6a512013-12-18 23:48:012294
2295
[email protected]ca8d19842009-02-19 16:33:122296def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542297 results = []
[email protected]1f7b4172010-01-28 01:17:342298 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542299 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272300 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342301 input_api,
2302 output_api,
[email protected]2fdd1f362013-01-16 03:56:032303 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272304
[email protected]3e4eb112011-01-18 03:29:542305 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2306 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412307 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2308 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542309 return results