blob: d78629a6d802bea59f45596784536cb99aeb33a9 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d1982009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d1982009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
jif65398702016-10-27 10:19:48148 (
149 r"/\s+UTF8String\s*]",
150 (
151 'The use of -[NSString UTF8String] is dangerous as it can return null',
152 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
153 'Please use |SysNSStringToUTF8| instead.',
154 ),
155 True,
156 ),
[email protected]127f18ec2012-06-16 05:05:59157)
158
159
160_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20161 # Make sure that gtest's FRIEND_TEST() macro is not used; the
162 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30163 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20164 (
165 'FRIEND_TEST(',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20168 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
169 ),
170 False,
[email protected]7345da02012-11-27 14:31:49171 (),
[email protected]23e6cbc2012-06-16 18:51:20172 ),
173 (
thomasanderson4b569052016-09-14 20:15:53174 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
175 (
176 'Chrome clients wishing to select events on X windows should use',
177 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
178 'you are selecting events from the GPU process, or if you are using',
179 'an XDisplay other than gfx::GetXDisplay().',
180 ),
181 True,
182 (
183 r"^ui[\\\/]gl[\\\/].*\.cc$",
184 r"^media[\\\/]gpu[\\\/].*\.cc$",
185 r"^gpu[\\\/].*\.cc$",
186 ),
187 ),
188 (
[email protected]23e6cbc2012-06-16 18:51:20189 'ScopedAllowIO',
190 (
[email protected]e3c945502012-06-26 20:01:49191 'New code should not use ScopedAllowIO. Post a task to the blocking',
192 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20193 ),
[email protected]e3c945502012-06-26 20:01:49194 True,
[email protected]7345da02012-11-27 14:31:49195 (
nyad2c548b2015-12-09 03:22:32196 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10197 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49198 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22199 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31200 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51201 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
202 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09203 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49204 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
205 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25206 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41207 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
208 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25209 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48210 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
211 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01212 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25213 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
214 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
215 r"embedded_test_server\.cc$",
216 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
217 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54218 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53219 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
220 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45221 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
222 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
223 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
224 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
225 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49226 ),
[email protected]23e6cbc2012-06-16 18:51:20227 ),
[email protected]52657f62013-05-20 05:30:31228 (
tomhudsone2c14d552016-05-26 17:07:46229 'setMatrixClip',
230 (
231 'Overriding setMatrixClip() is prohibited; ',
232 'the base function is deprecated. ',
233 ),
234 True,
235 (),
236 ),
237 (
[email protected]52657f62013-05-20 05:30:31238 'SkRefPtr',
239 (
240 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22241 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31242 ),
243 True,
244 (),
245 ),
246 (
247 'SkAutoRef',
248 (
249 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22250 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31251 ),
252 True,
253 (),
254 ),
255 (
256 'SkAutoTUnref',
257 (
258 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22259 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31260 ),
261 True,
262 (),
263 ),
264 (
265 'SkAutoUnref',
266 (
267 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
268 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22269 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31270 ),
271 True,
272 (),
273 ),
[email protected]d89eec82013-12-03 14:10:59274 (
275 r'/HANDLE_EINTR\(.*close',
276 (
277 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
278 'descriptor will be closed, and it is incorrect to retry the close.',
279 'Either call close directly and ignore its return value, or wrap close',
280 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
281 ),
282 True,
283 (),
284 ),
285 (
286 r'/IGNORE_EINTR\((?!.*close)',
287 (
288 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
289 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
290 ),
291 True,
292 (
293 # Files that #define IGNORE_EINTR.
294 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
295 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
296 ),
297 ),
[email protected]ec5b3f02014-04-04 18:43:43298 (
299 r'/v8::Extension\(',
300 (
301 'Do not introduce new v8::Extensions into the code base, use',
302 'gin::Wrappable instead. See http://crbug.com/334679',
303 ),
304 True,
[email protected]f55c90ee62014-04-12 00:50:03305 (
joaodasilva718f87672014-08-30 09:25:49306 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03307 ),
[email protected]ec5b3f02014-04-04 18:43:43308 ),
skyostilf9469f72015-04-20 10:38:52309 (
jame2d1a952016-04-02 00:27:10310 '#pragma comment(lib,',
311 (
312 'Specify libraries to link with in build files and not in the source.',
313 ),
314 True,
315 (),
316 ),
dcheng8f0694bae2016-10-12 15:58:15317 (
avid5a337982016-10-19 23:07:15318 r'STLDeleteElements', # http://crbug.com/555865
319 (
320 'This call is obsolete with C++ 11; create a container with owning',
321 'pointers instead (e.g. std::vector<std::unique_ptr<x>> ).',
322 ),
323 True,
324 (),
325 ),
326 (
327 r'STLDeleteValues', # http://crbug.com/555865
328 (
329 'This call is obsolete with C++ 11; create a map with owning',
330 'pointers instead (e.g. std::map<std::string, std::unique_ptr<x>> ).',
331 ),
332 True,
333 (),
334 ),
[email protected]127f18ec2012-06-16 05:05:59335)
336
wnwenbdc444e2016-05-25 13:44:15337
mlamouria82272622014-09-16 18:45:04338_IPC_ENUM_TRAITS_DEPRECATED = (
339 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
340 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
341
[email protected]127f18ec2012-06-16 05:05:59342
[email protected]b00342e7f2013-03-26 16:21:54343_VALID_OS_MACROS = (
344 # Please keep sorted.
345 'OS_ANDROID',
346 'OS_BSD',
347 'OS_CAT', # For testing.
348 'OS_CHROMEOS',
349 'OS_FREEBSD',
350 'OS_IOS',
351 'OS_LINUX',
352 'OS_MACOSX',
353 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21354 'OS_NACL_NONSFI',
355 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12356 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54357 'OS_OPENBSD',
358 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37359 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54360 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54361 'OS_WIN',
362)
363
364
agrievef32bcc72016-04-04 14:57:40365_ANDROID_SPECIFIC_PYDEPS_FILES = [
366 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19367 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40368]
369
wnwenbdc444e2016-05-25 13:44:15370
agrievef32bcc72016-04-04 14:57:40371_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40372]
373
wnwenbdc444e2016-05-25 13:44:15374
agrievef32bcc72016-04-04 14:57:40375_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
376
377
[email protected]55459852011-08-10 15:17:19378def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
379 """Attempts to prevent use of functions intended only for testing in
380 non-testing code. For now this is just a best-effort implementation
381 that ignores header files and may have some false positives. A
382 better implementation would probably need a proper C++ parser.
383 """
384 # We only scan .cc files and the like, as the declaration of
385 # for-testing functions in header files are hard to distinguish from
386 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44387 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19388
jochenc0d4808c2015-07-27 09:25:42389 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19390 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09391 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19392 exclusion_pattern = input_api.re.compile(
393 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
394 base_function_pattern, base_function_pattern))
395
396 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44397 black_list = (_EXCLUDED_PATHS +
398 _TEST_CODE_EXCLUDED_PATHS +
399 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19400 return input_api.FilterSourceFile(
401 affected_file,
402 white_list=(file_inclusion_pattern, ),
403 black_list=black_list)
404
405 problems = []
406 for f in input_api.AffectedSourceFiles(FilterFile):
407 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24408 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03409 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46410 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03411 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19412 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03413 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19414
415 if problems:
[email protected]f7051d52013-04-02 18:31:42416 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03417 else:
418 return []
[email protected]55459852011-08-10 15:17:19419
420
[email protected]10689ca2011-09-02 02:31:54421def _CheckNoIOStreamInHeaders(input_api, output_api):
422 """Checks to make sure no .h files include <iostream>."""
423 files = []
424 pattern = input_api.re.compile(r'^#include\s*<iostream>',
425 input_api.re.MULTILINE)
426 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
427 if not f.LocalPath().endswith('.h'):
428 continue
429 contents = input_api.ReadFile(f)
430 if pattern.search(contents):
431 files.append(f)
432
433 if len(files):
yolandyandaabc6d2016-04-18 18:29:39434 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06435 'Do not #include <iostream> in header files, since it inserts static '
436 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54437 '#include <ostream>. See http://crbug.com/94794',
438 files) ]
439 return []
440
441
[email protected]72df4e782012-06-21 16:28:18442def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52443 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18444 problems = []
445 for f in input_api.AffectedFiles():
446 if (not f.LocalPath().endswith(('.cc', '.mm'))):
447 continue
448
449 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04450 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18451 problems.append(' %s:%d' % (f.LocalPath(), line_num))
452
453 if not problems:
454 return []
455 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
456 '\n'.join(problems))]
457
458
danakj61c1aa22015-10-26 19:55:52459def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
460 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
461 errors = []
462 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
463 input_api.re.MULTILINE)
464 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
465 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
466 continue
467 for lnum, line in f.ChangedContents():
468 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17469 errors.append(output_api.PresubmitError(
470 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
471 'DCHECK_IS_ON()", not forgetting the braces.')
472 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52473 return errors
474
475
mcasasb7440c282015-02-04 14:52:19476def _FindHistogramNameInLine(histogram_name, line):
477 """Tries to find a histogram name or prefix in a line."""
478 if not "affected-histogram" in line:
479 return histogram_name in line
480 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
481 # the histogram_name.
482 if not '"' in line:
483 return False
484 histogram_prefix = line.split('\"')[1]
485 return histogram_prefix in histogram_name
486
487
488def _CheckUmaHistogramChanges(input_api, output_api):
489 """Check that UMA histogram names in touched lines can still be found in other
490 lines of the patch or in histograms.xml. Note that this check would not catch
491 the reverse: changes in histograms.xml not matched in the code itself."""
492 touched_histograms = []
493 histograms_xml_modifications = []
494 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
495 for f in input_api.AffectedFiles():
496 # If histograms.xml itself is modified, keep the modified lines for later.
497 if f.LocalPath().endswith(('histograms.xml')):
498 histograms_xml_modifications = f.ChangedContents()
499 continue
500 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
501 continue
502 for line_num, line in f.ChangedContents():
503 found = pattern.search(line)
504 if found:
505 touched_histograms.append([found.group(1), f, line_num])
506
507 # Search for the touched histogram names in the local modifications to
508 # histograms.xml, and, if not found, on the base histograms.xml file.
509 unmatched_histograms = []
510 for histogram_info in touched_histograms:
511 histogram_name_found = False
512 for line_num, line in histograms_xml_modifications:
513 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
514 if histogram_name_found:
515 break
516 if not histogram_name_found:
517 unmatched_histograms.append(histogram_info)
518
eromanb90c82e7e32015-04-01 15:13:49519 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19520 problems = []
521 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49522 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19523 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45524 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19525 histogram_name_found = False
526 for line in histograms_xml:
527 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
528 if histogram_name_found:
529 break
530 if not histogram_name_found:
531 problems.append(' [%s:%d] %s' %
532 (f.LocalPath(), line_num, histogram_name))
533
534 if not problems:
535 return []
536 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
537 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49538 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19539
wnwenbdc444e2016-05-25 13:44:15540
yolandyandaabc6d2016-04-18 18:29:39541def _CheckFlakyTestUsage(input_api, output_api):
542 """Check that FlakyTest annotation is our own instead of the android one"""
543 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
544 files = []
545 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
546 if f.LocalPath().endswith('Test.java'):
547 if pattern.search(input_api.ReadFile(f)):
548 files.append(f)
549 if len(files):
550 return [output_api.PresubmitError(
551 'Use org.chromium.base.test.util.FlakyTest instead of '
552 'android.test.FlakyTest',
553 files)]
554 return []
mcasasb7440c282015-02-04 14:52:19555
wnwenbdc444e2016-05-25 13:44:15556
[email protected]8ea5d4b2011-09-13 21:49:22557def _CheckNoNewWStrings(input_api, output_api):
558 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27559 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22560 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20561 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57562 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34563 '/win/' in f.LocalPath() or
564 'chrome_elf' in f.LocalPath() or
565 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20566 continue
[email protected]8ea5d4b2011-09-13 21:49:22567
[email protected]a11dbe9b2012-08-07 01:32:58568 allowWString = False
[email protected]b5c24292011-11-28 14:38:20569 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58570 if 'presubmit: allow wstring' in line:
571 allowWString = True
572 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27573 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58574 allowWString = False
575 else:
576 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22577
[email protected]55463aa62011-10-12 00:48:27578 if not problems:
579 return []
580 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58581 ' If you are calling a cross-platform API that accepts a wstring, '
582 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27583 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22584
585
[email protected]2a8ac9c2011-10-19 17:20:44586def _CheckNoDEPSGIT(input_api, output_api):
587 """Make sure .DEPS.git is never modified manually."""
588 if any(f.LocalPath().endswith('.DEPS.git') for f in
589 input_api.AffectedFiles()):
590 return [output_api.PresubmitError(
591 'Never commit changes to .DEPS.git. This file is maintained by an\n'
592 'automated system based on what\'s in DEPS and your changes will be\n'
593 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34594 '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:44595 'for more information')]
596 return []
597
598
tandriief664692014-09-23 14:51:47599def _CheckValidHostsInDEPS(input_api, output_api):
600 """Checks that DEPS file deps are from allowed_hosts."""
601 # Run only if DEPS file has been modified to annoy fewer bystanders.
602 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
603 return []
604 # Outsource work to gclient verify
605 try:
606 input_api.subprocess.check_output(['gclient', 'verify'])
607 return []
608 except input_api.subprocess.CalledProcessError, error:
609 return [output_api.PresubmitError(
610 'DEPS file must have only git dependencies.',
611 long_text=error.output)]
612
613
[email protected]127f18ec2012-06-16 05:05:59614def _CheckNoBannedFunctions(input_api, output_api):
615 """Make sure that banned functions are not used."""
616 warnings = []
617 errors = []
618
wnwenbdc444e2016-05-25 13:44:15619 def IsBlacklisted(affected_file, blacklist):
620 local_path = affected_file.LocalPath()
621 for item in blacklist:
622 if input_api.re.match(item, local_path):
623 return True
624 return False
625
626 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
627 matched = False
628 if func_name[0:1] == '/':
629 regex = func_name[1:]
630 if input_api.re.search(regex, line):
631 matched = True
632 elif func_name in line:
dchenge07de812016-06-20 19:27:17633 matched = True
wnwenbdc444e2016-05-25 13:44:15634 if matched:
dchenge07de812016-06-20 19:27:17635 problems = warnings
wnwenbdc444e2016-05-25 13:44:15636 if error:
dchenge07de812016-06-20 19:27:17637 problems = errors
wnwenbdc444e2016-05-25 13:44:15638 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
639 for message_line in message:
640 problems.append(' %s' % message_line)
641
[email protected]127f18ec2012-06-16 05:05:59642 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
643 for f in input_api.AffectedFiles(file_filter=file_filter):
644 for line_num, line in f.ChangedContents():
645 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15646 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59647
648 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
649 for f in input_api.AffectedFiles(file_filter=file_filter):
650 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49651 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49652 if IsBlacklisted(f, excluded_paths):
653 continue
wnwenbdc444e2016-05-25 13:44:15654 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59655
656 result = []
657 if (warnings):
658 result.append(output_api.PresubmitPromptWarning(
659 'Banned functions were used.\n' + '\n'.join(warnings)))
660 if (errors):
661 result.append(output_api.PresubmitError(
662 'Banned functions were used.\n' + '\n'.join(errors)))
663 return result
664
665
[email protected]6c063c62012-07-11 19:11:06666def _CheckNoPragmaOnce(input_api, output_api):
667 """Make sure that banned functions are not used."""
668 files = []
669 pattern = input_api.re.compile(r'^#pragma\s+once',
670 input_api.re.MULTILINE)
671 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
672 if not f.LocalPath().endswith('.h'):
673 continue
674 contents = input_api.ReadFile(f)
675 if pattern.search(contents):
676 files.append(f)
677
678 if files:
679 return [output_api.PresubmitError(
680 'Do not use #pragma once in header files.\n'
681 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
682 files)]
683 return []
684
[email protected]127f18ec2012-06-16 05:05:59685
[email protected]e7479052012-09-19 00:26:12686def _CheckNoTrinaryTrueFalse(input_api, output_api):
687 """Checks to make sure we don't introduce use of foo ? true : false."""
688 problems = []
689 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
690 for f in input_api.AffectedFiles():
691 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
692 continue
693
694 for line_num, line in f.ChangedContents():
695 if pattern.match(line):
696 problems.append(' %s:%d' % (f.LocalPath(), line_num))
697
698 if not problems:
699 return []
700 return [output_api.PresubmitPromptWarning(
701 'Please consider avoiding the "? true : false" pattern if possible.\n' +
702 '\n'.join(problems))]
703
704
[email protected]55f9f382012-07-31 11:02:18705def _CheckUnwantedDependencies(input_api, output_api):
706 """Runs checkdeps on #include statements added in this
707 change. Breaking - rules is an error, breaking ! rules is a
708 warning.
709 """
mohan.reddyf21db962014-10-16 12:26:47710 import sys
[email protected]55f9f382012-07-31 11:02:18711 # We need to wait until we have an input_api object and use this
712 # roundabout construct to import checkdeps because this file is
713 # eval-ed and thus doesn't have __file__.
714 original_sys_path = sys.path
715 try:
716 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47717 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18718 import checkdeps
719 from cpp_checker import CppChecker
720 from rules import Rule
721 finally:
722 # Restore sys.path to what it was before.
723 sys.path = original_sys_path
724
725 added_includes = []
726 for f in input_api.AffectedFiles():
727 if not CppChecker.IsCppFile(f.LocalPath()):
728 continue
729
730 changed_lines = [line for line_num, line in f.ChangedContents()]
731 added_includes.append([f.LocalPath(), changed_lines])
732
[email protected]26385172013-05-09 23:11:35733 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18734
735 error_descriptions = []
736 warning_descriptions = []
737 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
738 added_includes):
739 description_with_path = '%s\n %s' % (path, rule_description)
740 if rule_type == Rule.DISALLOW:
741 error_descriptions.append(description_with_path)
742 else:
743 warning_descriptions.append(description_with_path)
744
745 results = []
746 if error_descriptions:
747 results.append(output_api.PresubmitError(
748 'You added one or more #includes that violate checkdeps rules.',
749 error_descriptions))
750 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42751 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18752 'You added one or more #includes of files that are temporarily\n'
753 'allowed but being removed. Can you avoid introducing the\n'
754 '#include? See relevant DEPS file(s) for details and contacts.',
755 warning_descriptions))
756 return results
757
758
[email protected]fbcafe5a2012-08-08 15:31:22759def _CheckFilePermissions(input_api, output_api):
760 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15761 if input_api.platform == 'win32':
762 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29763 checkperms_tool = input_api.os_path.join(
764 input_api.PresubmitLocalPath(),
765 'tools', 'checkperms', 'checkperms.py')
766 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47767 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22768 for f in input_api.AffectedFiles():
769 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11770 try:
771 input_api.subprocess.check_output(args)
772 return []
773 except input_api.subprocess.CalledProcessError as error:
774 return [output_api.PresubmitError(
775 'checkperms.py failed:',
776 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22777
778
[email protected]c8278b32012-10-30 20:35:49779def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
780 """Makes sure we don't include ui/aura/window_property.h
781 in header files.
782 """
783 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
784 errors = []
785 for f in input_api.AffectedFiles():
786 if not f.LocalPath().endswith('.h'):
787 continue
788 for line_num, line in f.ChangedContents():
789 if pattern.match(line):
790 errors.append(' %s:%d' % (f.LocalPath(), line_num))
791
792 results = []
793 if errors:
794 results.append(output_api.PresubmitError(
795 'Header files should not include ui/aura/window_property.h', errors))
796 return results
797
798
[email protected]cf9b78f2012-11-14 11:40:28799def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
800 """Checks that the lines in scope occur in the right order.
801
802 1. C system files in alphabetical order
803 2. C++ system files in alphabetical order
804 3. Project's .h files
805 """
806
807 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
808 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
809 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
810
811 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
812
813 state = C_SYSTEM_INCLUDES
814
815 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57816 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28817 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55818 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28819 for line_num, line in scope:
820 if c_system_include_pattern.match(line):
821 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55822 problem_linenums.append((line_num, previous_line_num,
823 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28824 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55825 problem_linenums.append((line_num, previous_line_num,
826 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28827 elif cpp_system_include_pattern.match(line):
828 if state == C_SYSTEM_INCLUDES:
829 state = CPP_SYSTEM_INCLUDES
830 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55831 problem_linenums.append((line_num, previous_line_num,
832 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28833 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55834 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28835 elif custom_include_pattern.match(line):
836 if state != CUSTOM_INCLUDES:
837 state = CUSTOM_INCLUDES
838 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55839 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28840 else:
brucedawson70fadb02015-06-30 17:47:55841 problem_linenums.append((line_num, previous_line_num,
842 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28843 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57844 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28845
846 warnings = []
brucedawson70fadb02015-06-30 17:47:55847 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57848 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55849 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28850 return warnings
851
852
[email protected]ac294a12012-12-06 16:38:43853def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28854 """Checks the #include order for the given file f."""
855
[email protected]2299dcf2012-11-15 19:56:24856 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30857 # Exclude the following includes from the check:
858 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
859 # specific order.
860 # 2) <atlbase.h>, "build/build_config.h"
861 excluded_include_pattern = input_api.re.compile(
862 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24863 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33864 # Match the final or penultimate token if it is xxxtest so we can ignore it
865 # when considering the special first include.
866 test_file_tag_pattern = input_api.re.compile(
867 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11868 if_pattern = input_api.re.compile(
869 r'\s*#\s*(if|elif|else|endif|define|undef).*')
870 # Some files need specialized order of includes; exclude such files from this
871 # check.
872 uncheckable_includes_pattern = input_api.re.compile(
873 r'\s*#include '
874 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28875
876 contents = f.NewContents()
877 warnings = []
878 line_num = 0
879
[email protected]ac294a12012-12-06 16:38:43880 # Handle the special first include. If the first include file is
881 # some/path/file.h, the corresponding including file can be some/path/file.cc,
882 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
883 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33884 # If the included file is some/path/file_platform.h the including file could
885 # also be some/path/file_xxxtest_platform.h.
886 including_file_base_name = test_file_tag_pattern.sub(
887 '', input_api.os_path.basename(f.LocalPath()))
888
[email protected]ac294a12012-12-06 16:38:43889 for line in contents:
890 line_num += 1
891 if system_include_pattern.match(line):
892 # No special first include -> process the line again along with normal
893 # includes.
894 line_num -= 1
895 break
896 match = custom_include_pattern.match(line)
897 if match:
898 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33899 header_basename = test_file_tag_pattern.sub(
900 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
901
902 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24903 # No special first include -> process the line again along with normal
904 # includes.
905 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43906 break
[email protected]cf9b78f2012-11-14 11:40:28907
908 # Split into scopes: Each region between #if and #endif is its own scope.
909 scopes = []
910 current_scope = []
911 for line in contents[line_num:]:
912 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11913 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54914 continue
[email protected]2309b0fa02012-11-16 12:18:27915 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28916 scopes.append(current_scope)
917 current_scope = []
[email protected]962f117e2012-11-22 18:11:56918 elif ((system_include_pattern.match(line) or
919 custom_include_pattern.match(line)) and
920 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28921 current_scope.append((line_num, line))
922 scopes.append(current_scope)
923
924 for scope in scopes:
925 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
926 changed_linenums))
927 return warnings
928
929
930def _CheckIncludeOrder(input_api, output_api):
931 """Checks that the #include order is correct.
932
933 1. The corresponding header for source files.
934 2. C system files in alphabetical order
935 3. C++ system files in alphabetical order
936 4. Project's .h files in alphabetical order
937
[email protected]ac294a12012-12-06 16:38:43938 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
939 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28940 """
[email protected]e120b012014-08-15 19:08:35941 def FileFilterIncludeOrder(affected_file):
942 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
943 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28944
945 warnings = []
[email protected]e120b012014-08-15 19:08:35946 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08947 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43948 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
949 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28950
951 results = []
952 if warnings:
[email protected]f7051d52013-04-02 18:31:42953 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53954 warnings))
[email protected]cf9b78f2012-11-14 11:40:28955 return results
956
957
[email protected]70ca77752012-11-20 03:45:03958def _CheckForVersionControlConflictsInFile(input_api, f):
959 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
960 errors = []
961 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23962 if f.LocalPath().endswith('.md'):
963 # First-level headers in markdown look a lot like version control
964 # conflict markers. http://daringfireball.net/projects/markdown/basics
965 continue
[email protected]70ca77752012-11-20 03:45:03966 if pattern.match(line):
967 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
968 return errors
969
970
971def _CheckForVersionControlConflicts(input_api, output_api):
972 """Usually this is not intentional and will cause a compile failure."""
973 errors = []
974 for f in input_api.AffectedFiles():
975 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
976
977 results = []
978 if errors:
979 results.append(output_api.PresubmitError(
980 'Version control conflict markers found, please resolve.', errors))
981 return results
982
983
[email protected]06e6d0ff2012-12-11 01:36:44984def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
985 def FilterFile(affected_file):
986 """Filter function for use with input_api.AffectedSourceFiles,
987 below. This filters out everything except non-test files from
988 top-level directories that generally speaking should not hard-code
989 service URLs (e.g. src/android_webview/, src/content/ and others).
990 """
991 return input_api.FilterSourceFile(
992 affected_file,
[email protected]78bb39d62012-12-11 15:11:56993 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44994 black_list=(_EXCLUDED_PATHS +
995 _TEST_CODE_EXCLUDED_PATHS +
996 input_api.DEFAULT_BLACK_LIST))
997
reillyi38965732015-11-16 18:27:33998 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
999 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461000 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1001 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441002 problems = [] # items are (filename, line_number, line)
1003 for f in input_api.AffectedSourceFiles(FilterFile):
1004 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461005 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441006 problems.append((f.LocalPath(), line_num, line))
1007
1008 if problems:
[email protected]f7051d52013-04-02 18:31:421009 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441010 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581011 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441012 [' %s:%d: %s' % (
1013 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031014 else:
1015 return []
[email protected]06e6d0ff2012-12-11 01:36:441016
1017
[email protected]d2530012013-01-25 16:39:271018def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1019 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311020 The native_client_sdk directory is excluded because it has auto-generated PNG
1021 files for documentation.
[email protected]d2530012013-01-25 16:39:271022 """
[email protected]d2530012013-01-25 16:39:271023 errors = []
binji0dcdf342014-12-12 18:32:311024 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1025 black_list = (r'^native_client_sdk[\\\/]',)
1026 file_filter = lambda f: input_api.FilterSourceFile(
1027 f, white_list=white_list, black_list=black_list)
1028 for f in input_api.AffectedFiles(include_deletes=False,
1029 file_filter=file_filter):
1030 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271031
1032 results = []
1033 if errors:
1034 results.append(output_api.PresubmitError(
1035 'The name of PNG files should not have abbreviations. \n'
1036 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1037 'Contact [email protected] if you have questions.', errors))
1038 return results
1039
1040
[email protected]14a6131c2014-01-08 01:15:411041def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081042 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411043 a set of DEPS entries that we should look up.
1044
1045 For a directory (rather than a specific filename) we fake a path to
1046 a specific filename by adding /DEPS. This is chosen as a file that
1047 will seldom or never be subject to per-file include_rules.
1048 """
[email protected]2b438d62013-11-14 17:54:141049 # We ignore deps entries on auto-generated directories.
1050 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081051
1052 # This pattern grabs the path without basename in the first
1053 # parentheses, and the basename (if present) in the second. It
1054 # relies on the simple heuristic that if there is a basename it will
1055 # be a header file ending in ".h".
1056 pattern = re.compile(
1057 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141058 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081059 for changed_line in changed_lines:
1060 m = pattern.match(changed_line)
1061 if m:
1062 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141063 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411064 if m.group(2):
1065 results.add('%s%s' % (path, m.group(2)))
1066 else:
1067 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081068 return results
1069
1070
[email protected]e871964c2013-05-13 14:14:551071def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1072 """When a dependency prefixed with + is added to a DEPS file, we
1073 want to make sure that the change is reviewed by an OWNER of the
1074 target file or directory, to avoid layering violations from being
1075 introduced. This check verifies that this happens.
1076 """
1077 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241078
1079 file_filter = lambda f: not input_api.re.match(
1080 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1081 for f in input_api.AffectedFiles(include_deletes=False,
1082 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551083 filename = input_api.os_path.basename(f.LocalPath())
1084 if filename == 'DEPS':
1085 changed_lines |= set(line.strip()
1086 for line_num, line
1087 in f.ChangedContents())
1088 if not changed_lines:
1089 return []
1090
[email protected]14a6131c2014-01-08 01:15:411091 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1092 changed_lines)
[email protected]e871964c2013-05-13 14:14:551093 if not virtual_depended_on_files:
1094 return []
1095
1096 if input_api.is_committing:
1097 if input_api.tbr:
1098 return [output_api.PresubmitNotifyResult(
1099 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271100 if input_api.dry_run:
1101 return [output_api.PresubmitNotifyResult(
1102 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551103 if not input_api.change.issue:
1104 return [output_api.PresubmitError(
1105 "DEPS approval by OWNERS check failed: this change has "
1106 "no Rietveld issue number, so we can't check it for approvals.")]
1107 output = output_api.PresubmitError
1108 else:
1109 output = output_api.PresubmitNotifyResult
1110
1111 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501112 owner_email, reviewers = (
1113 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1114 input_api,
1115 owners_db.email_regexp,
1116 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551117
1118 owner_email = owner_email or input_api.change.author_email
1119
[email protected]de4f7d22013-05-23 14:27:461120 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511121 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461122 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551123 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1124 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411125
1126 # We strip the /DEPS part that was added by
1127 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1128 # directory.
1129 def StripDeps(path):
1130 start_deps = path.rfind('/DEPS')
1131 if start_deps != -1:
1132 return path[:start_deps]
1133 else:
1134 return path
1135 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551136 for path in missing_files]
1137
1138 if unapproved_dependencies:
1139 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151140 output('You need LGTM from owners of depends-on paths in DEPS that were '
1141 'modified in this CL:\n %s' %
1142 '\n '.join(sorted(unapproved_dependencies)))]
1143 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1144 output_list.append(output(
1145 'Suggested missing target path OWNERS:\n %s' %
1146 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551147 return output_list
1148
1149 return []
1150
1151
[email protected]85218562013-11-22 07:41:401152def _CheckSpamLogging(input_api, output_api):
1153 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1154 black_list = (_EXCLUDED_PATHS +
1155 _TEST_CODE_EXCLUDED_PATHS +
1156 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501157 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191158 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481159 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461160 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121161 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1162 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581163 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161164 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031165 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151166 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1167 r"^chromecast[\\\/]",
1168 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311169 r"^components[\\\/]html_viewer[\\\/]"
1170 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461171 # TODO(peter): Remove this exception. https://crbug.com/534537
1172 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1173 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251174 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1175 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241176 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111177 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151178 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111179 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521180 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501181 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361182 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311183 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131184 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441185 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451186 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021187 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441188 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401189 source_file_filter = lambda x: input_api.FilterSourceFile(
1190 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1191
1192 log_info = []
1193 printf = []
1194
1195 for f in input_api.AffectedSourceFiles(source_file_filter):
1196 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471197 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401198 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471199 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131200 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371201
mohan.reddyf21db962014-10-16 12:26:471202 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371203 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471204 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401205 printf.append(f.LocalPath())
1206
1207 if log_info:
1208 return [output_api.PresubmitError(
1209 'These files spam the console log with LOG(INFO):',
1210 items=log_info)]
1211 if printf:
1212 return [output_api.PresubmitError(
1213 'These files spam the console log with printf/fprintf:',
1214 items=printf)]
1215 return []
1216
1217
[email protected]49aa76a2013-12-04 06:59:161218def _CheckForAnonymousVariables(input_api, output_api):
1219 """These types are all expected to hold locks while in scope and
1220 so should never be anonymous (which causes them to be immediately
1221 destroyed)."""
1222 they_who_must_be_named = [
1223 'base::AutoLock',
1224 'base::AutoReset',
1225 'base::AutoUnlock',
1226 'SkAutoAlphaRestore',
1227 'SkAutoBitmapShaderInstall',
1228 'SkAutoBlitterChoose',
1229 'SkAutoBounderCommit',
1230 'SkAutoCallProc',
1231 'SkAutoCanvasRestore',
1232 'SkAutoCommentBlock',
1233 'SkAutoDescriptor',
1234 'SkAutoDisableDirectionCheck',
1235 'SkAutoDisableOvalCheck',
1236 'SkAutoFree',
1237 'SkAutoGlyphCache',
1238 'SkAutoHDC',
1239 'SkAutoLockColors',
1240 'SkAutoLockPixels',
1241 'SkAutoMalloc',
1242 'SkAutoMaskFreeImage',
1243 'SkAutoMutexAcquire',
1244 'SkAutoPathBoundsUpdate',
1245 'SkAutoPDFRelease',
1246 'SkAutoRasterClipValidate',
1247 'SkAutoRef',
1248 'SkAutoTime',
1249 'SkAutoTrace',
1250 'SkAutoUnref',
1251 ]
1252 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1253 # bad: base::AutoLock(lock.get());
1254 # not bad: base::AutoLock lock(lock.get());
1255 bad_pattern = input_api.re.compile(anonymous)
1256 # good: new base::AutoLock(lock.get())
1257 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1258 errors = []
1259
1260 for f in input_api.AffectedFiles():
1261 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1262 continue
1263 for linenum, line in f.ChangedContents():
1264 if bad_pattern.search(line) and not good_pattern.search(line):
1265 errors.append('%s:%d' % (f.LocalPath(), linenum))
1266
1267 if errors:
1268 return [output_api.PresubmitError(
1269 'These lines create anonymous variables that need to be named:',
1270 items=errors)]
1271 return []
1272
1273
[email protected]5fe0f8742013-11-29 01:04:591274def _CheckCygwinShell(input_api, output_api):
1275 source_file_filter = lambda x: input_api.FilterSourceFile(
1276 x, white_list=(r'.+\.(gyp|gypi)$',))
1277 cygwin_shell = []
1278
1279 for f in input_api.AffectedSourceFiles(source_file_filter):
1280 for linenum, line in f.ChangedContents():
1281 if 'msvs_cygwin_shell' in line:
1282 cygwin_shell.append(f.LocalPath())
1283 break
1284
1285 if cygwin_shell:
1286 return [output_api.PresubmitError(
1287 'These files should not use msvs_cygwin_shell (the default is 0):',
1288 items=cygwin_shell)]
1289 return []
1290
[email protected]85218562013-11-22 07:41:401291
[email protected]999261d2014-03-03 20:08:081292def _CheckUserActionUpdate(input_api, output_api):
1293 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521294 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081295 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521296 # If actions.xml is already included in the changelist, the PRESUBMIT
1297 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081298 return []
1299
[email protected]999261d2014-03-03 20:08:081300 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1301 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521302 current_actions = None
[email protected]999261d2014-03-03 20:08:081303 for f in input_api.AffectedFiles(file_filter=file_filter):
1304 for line_num, line in f.ChangedContents():
1305 match = input_api.re.search(action_re, line)
1306 if match:
[email protected]2f92dec2014-03-07 19:21:521307 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1308 # loaded only once.
1309 if not current_actions:
1310 with open('tools/metrics/actions/actions.xml') as actions_f:
1311 current_actions = actions_f.read()
1312 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081313 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521314 action = 'name="{0}"'.format(action_name)
1315 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081316 return [output_api.PresubmitPromptWarning(
1317 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521318 'tools/metrics/actions/actions.xml. Please run '
1319 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081320 % (f.LocalPath(), line_num, action_name))]
1321 return []
1322
1323
[email protected]99171a92014-06-03 08:44:471324def _GetJSONParseError(input_api, filename, eat_comments=True):
1325 try:
1326 contents = input_api.ReadFile(filename)
1327 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131328 import sys
1329 original_sys_path = sys.path
1330 try:
1331 sys.path = sys.path + [input_api.os_path.join(
1332 input_api.PresubmitLocalPath(),
1333 'tools', 'json_comment_eater')]
1334 import json_comment_eater
1335 finally:
1336 sys.path = original_sys_path
1337 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471338
1339 input_api.json.loads(contents)
1340 except ValueError as e:
1341 return e
1342 return None
1343
1344
1345def _GetIDLParseError(input_api, filename):
1346 try:
1347 contents = input_api.ReadFile(filename)
1348 idl_schema = input_api.os_path.join(
1349 input_api.PresubmitLocalPath(),
1350 'tools', 'json_schema_compiler', 'idl_schema.py')
1351 process = input_api.subprocess.Popen(
1352 [input_api.python_executable, idl_schema],
1353 stdin=input_api.subprocess.PIPE,
1354 stdout=input_api.subprocess.PIPE,
1355 stderr=input_api.subprocess.PIPE,
1356 universal_newlines=True)
1357 (_, error) = process.communicate(input=contents)
1358 return error or None
1359 except ValueError as e:
1360 return e
1361
1362
1363def _CheckParseErrors(input_api, output_api):
1364 """Check that IDL and JSON files do not contain syntax errors."""
1365 actions = {
1366 '.idl': _GetIDLParseError,
1367 '.json': _GetJSONParseError,
1368 }
1369 # These paths contain test data and other known invalid JSON files.
1370 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491371 r'test[\\\/]data[\\\/]',
1372 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471373 ]
1374 # Most JSON files are preprocessed and support comments, but these do not.
1375 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491376 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471377 ]
1378 # Only run IDL checker on files in these directories.
1379 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491380 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1381 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471382 ]
1383
1384 def get_action(affected_file):
1385 filename = affected_file.LocalPath()
1386 return actions.get(input_api.os_path.splitext(filename)[1])
1387
1388 def MatchesFile(patterns, path):
1389 for pattern in patterns:
1390 if input_api.re.search(pattern, path):
1391 return True
1392 return False
1393
1394 def FilterFile(affected_file):
1395 action = get_action(affected_file)
1396 if not action:
1397 return False
1398 path = affected_file.LocalPath()
1399
1400 if MatchesFile(excluded_patterns, path):
1401 return False
1402
1403 if (action == _GetIDLParseError and
1404 not MatchesFile(idl_included_patterns, path)):
1405 return False
1406 return True
1407
1408 results = []
1409 for affected_file in input_api.AffectedFiles(
1410 file_filter=FilterFile, include_deletes=False):
1411 action = get_action(affected_file)
1412 kwargs = {}
1413 if (action == _GetJSONParseError and
1414 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1415 kwargs['eat_comments'] = False
1416 parse_error = action(input_api,
1417 affected_file.AbsoluteLocalPath(),
1418 **kwargs)
1419 if parse_error:
1420 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1421 (affected_file.LocalPath(), parse_error)))
1422 return results
1423
1424
[email protected]760deea2013-12-10 19:33:491425def _CheckJavaStyle(input_api, output_api):
1426 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471427 import sys
[email protected]760deea2013-12-10 19:33:491428 original_sys_path = sys.path
1429 try:
1430 sys.path = sys.path + [input_api.os_path.join(
1431 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1432 import checkstyle
1433 finally:
1434 # Restore sys.path to what it was before.
1435 sys.path = original_sys_path
1436
1437 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091438 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511439 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491440
1441
dchenge07de812016-06-20 19:27:171442def _CheckIpcOwners(input_api, output_api):
1443 """Checks that affected files involving IPC have an IPC OWNERS rule.
1444
1445 Whether or not a file affects IPC is determined by a simple whitelist of
1446 filename patterns."""
1447 file_patterns = [
1448 '*_messages.cc',
1449 '*_messages*.h',
1450 '*_param_traits*.*',
1451 '*.mojom',
1452 '*_struct_traits*.*',
1453 '*_type_converter*.*',
1454 # Blink uses a different file naming convention
1455 '*StructTraits*.*',
1456 '*TypeConverter*.*',
1457 ]
1458
scottmg7a6ed5ba2016-11-04 18:22:041459 # These third_party directories do not contain IPCs, but contain files
1460 # matching the above patterns, which trigger false positives.
1461 exclude_paths = [
1462 'third_party/crashpad/*',
1463 ]
1464
dchenge07de812016-06-20 19:27:171465 # Dictionary mapping an OWNERS file path to Patterns.
1466 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1467 # rules ) to a PatternEntry.
1468 # PatternEntry is a dictionary with two keys:
1469 # - 'files': the files that are matched by this pattern
1470 # - 'rules': the per-file rules needed for this pattern
1471 # For example, if we expect OWNERS file to contain rules for *.mojom and
1472 # *_struct_traits*.*, Patterns might look like this:
1473 # {
1474 # '*.mojom': {
1475 # 'files': ...,
1476 # 'rules': [
1477 # 'per-file *.mojom=set noparent',
1478 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1479 # ],
1480 # },
1481 # '*_struct_traits*.*': {
1482 # 'files': ...,
1483 # 'rules': [
1484 # 'per-file *_struct_traits*.*=set noparent',
1485 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1486 # ],
1487 # },
1488 # }
1489 to_check = {}
1490
1491 # Iterate through the affected files to see what we actually need to check
1492 # for. We should only nag patch authors about per-file rules if a file in that
1493 # directory would match that pattern. If a directory only contains *.mojom
1494 # files and no *_messages*.h files, we should only nag about rules for
1495 # *.mojom files.
rockot51249332016-06-23 16:32:251496 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171497 for pattern in file_patterns:
1498 if input_api.fnmatch.fnmatch(
1499 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041500 skip = False
1501 for exclude in exclude_paths:
1502 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1503 skip = True
1504 break
1505 if skip:
1506 continue
dchenge07de812016-06-20 19:27:171507 owners_file = input_api.os_path.join(
1508 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1509 if owners_file not in to_check:
1510 to_check[owners_file] = {}
1511 if pattern not in to_check[owners_file]:
1512 to_check[owners_file][pattern] = {
1513 'files': [],
1514 'rules': [
1515 'per-file %s=set noparent' % pattern,
1516 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1517 ]
1518 }
1519 to_check[owners_file][pattern]['files'].append(f)
1520 break
1521
1522 # Now go through the OWNERS files we collected, filtering out rules that are
1523 # already present in that OWNERS file.
1524 for owners_file, patterns in to_check.iteritems():
1525 try:
1526 with file(owners_file) as f:
1527 lines = set(f.read().splitlines())
1528 for entry in patterns.itervalues():
1529 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1530 ]
1531 except IOError:
1532 # No OWNERS file, so all the rules are definitely missing.
1533 continue
1534
1535 # All the remaining lines weren't found in OWNERS files, so emit an error.
1536 errors = []
1537 for owners_file, patterns in to_check.iteritems():
1538 missing_lines = []
1539 files = []
1540 for pattern, entry in patterns.iteritems():
1541 missing_lines.extend(entry['rules'])
1542 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1543 if missing_lines:
1544 errors.append(
1545 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1546 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1547
1548 results = []
1549 if errors:
vabrf5ce3bf92016-07-11 14:52:411550 if input_api.is_committing:
1551 output = output_api.PresubmitError
1552 else:
1553 output = output_api.PresubmitPromptWarning
1554 results.append(output(
dchenge07de812016-06-20 19:27:171555 'Found changes to IPC files without a security OWNER!',
1556 long_text='\n\n'.join(errors)))
1557
1558 return results
1559
1560
yzshend99f726a2016-07-25 21:44:231561def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1562 """Checks to make sure that all newly added mojom targets map array/map/string
1563 to STL (for chromium) or WTF (for blink) types.
1564 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1565 """
1566 files = []
1567 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1568 input_api.re.MULTILINE)
1569
1570 for f in input_api.AffectedFiles():
1571 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1572 continue
1573
1574 for _, line in f.ChangedContents():
1575 if pattern.search(line):
1576 files.append(f)
1577 break
1578
1579 if len(files):
1580 return [output_api.PresubmitError(
1581 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1582 'false. The mode is deprecated and will be removed soon.',
1583 files)]
1584 return []
1585
1586
dskiba88634f4e2015-08-14 23:03:291587def _CheckAndroidToastUsage(input_api, output_api):
1588 """Checks that code uses org.chromium.ui.widget.Toast instead of
1589 android.widget.Toast (Chromium Toast doesn't force hardware
1590 acceleration on low-end devices, saving memory).
1591 """
1592 toast_import_pattern = input_api.re.compile(
1593 r'^import android\.widget\.Toast;$')
1594
1595 errors = []
1596
1597 sources = lambda affected_file: input_api.FilterSourceFile(
1598 affected_file,
1599 black_list=(_EXCLUDED_PATHS +
1600 _TEST_CODE_EXCLUDED_PATHS +
1601 input_api.DEFAULT_BLACK_LIST +
1602 (r'^chromecast[\\\/].*',
1603 r'^remoting[\\\/].*')),
1604 white_list=(r'.*\.java$',))
1605
1606 for f in input_api.AffectedSourceFiles(sources):
1607 for line_num, line in f.ChangedContents():
1608 if toast_import_pattern.search(line):
1609 errors.append("%s:%d" % (f.LocalPath(), line_num))
1610
1611 results = []
1612
1613 if errors:
1614 results.append(output_api.PresubmitError(
1615 'android.widget.Toast usage is detected. Android toasts use hardware'
1616 ' acceleration, and can be\ncostly on low-end devices. Please use'
1617 ' org.chromium.ui.widget.Toast instead.\n'
1618 'Contact [email protected] if you have any questions.',
1619 errors))
1620
1621 return results
1622
1623
dgnaa68d5e2015-06-10 10:08:221624def _CheckAndroidCrLogUsage(input_api, output_api):
1625 """Checks that new logs using org.chromium.base.Log:
1626 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511627 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221628 """
pkotwicza1dd0b002016-05-16 14:41:041629
1630 # Do not check format of logs in //chrome/android/webapk because
1631 # //chrome/android/webapk cannot depend on //base
1632 cr_log_check_excluded_paths = [
1633 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1634 ]
1635
dgnaa68d5e2015-06-10 10:08:221636 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121637 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1638 class_in_base_pattern = input_api.re.compile(
1639 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1640 has_some_log_import_pattern = input_api.re.compile(
1641 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221642 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121643 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221644 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511645 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221646 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221647
Vincent Scheib16d7b272015-09-15 18:09:071648 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221649 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041650 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1651 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121652
dgnaa68d5e2015-06-10 10:08:221653 tag_decl_errors = []
1654 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121655 tag_errors = []
dgn38736db2015-09-18 19:20:511656 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121657 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221658
1659 for f in input_api.AffectedSourceFiles(sources):
1660 file_content = input_api.ReadFile(f)
1661 has_modified_logs = False
1662
1663 # Per line checks
dgn87d9fb62015-06-12 09:15:121664 if (cr_log_import_pattern.search(file_content) or
1665 (class_in_base_pattern.search(file_content) and
1666 not has_some_log_import_pattern.search(file_content))):
1667 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221668 for line_num, line in f.ChangedContents():
1669
1670 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121671 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221672 if match:
1673 has_modified_logs = True
1674
1675 # Make sure it uses "TAG"
1676 if not match.group('tag') == 'TAG':
1677 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121678 else:
1679 # Report non cr Log function calls in changed lines
1680 for line_num, line in f.ChangedContents():
1681 if log_call_pattern.search(line):
1682 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221683
1684 # Per file checks
1685 if has_modified_logs:
1686 # Make sure the tag is using the "cr" prefix and is not too long
1687 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511688 tag_name = match.group('name') if match else None
1689 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221690 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511691 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221692 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511693 elif '.' in tag_name:
1694 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221695
1696 results = []
1697 if tag_decl_errors:
1698 results.append(output_api.PresubmitPromptWarning(
1699 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511700 '"private static final String TAG = "<package tag>".\n'
1701 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221702 tag_decl_errors))
1703
1704 if tag_length_errors:
1705 results.append(output_api.PresubmitError(
1706 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511707 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221708 tag_length_errors))
1709
1710 if tag_errors:
1711 results.append(output_api.PresubmitPromptWarning(
1712 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1713 tag_errors))
1714
dgn87d9fb62015-06-12 09:15:121715 if util_log_errors:
dgn4401aa52015-04-29 16:26:171716 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121717 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1718 util_log_errors))
1719
dgn38736db2015-09-18 19:20:511720 if tag_with_dot_errors:
1721 results.append(output_api.PresubmitPromptWarning(
1722 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1723 tag_with_dot_errors))
1724
dgn4401aa52015-04-29 16:26:171725 return results
1726
1727
agrieve7b6479d82015-10-07 14:24:221728def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1729 """Checks if MDPI assets are placed in a correct directory."""
1730 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1731 ('/res/drawable/' in f.LocalPath() or
1732 '/res/drawable-ldrtl/' in f.LocalPath()))
1733 errors = []
1734 for f in input_api.AffectedFiles(include_deletes=False,
1735 file_filter=file_filter):
1736 errors.append(' %s' % f.LocalPath())
1737
1738 results = []
1739 if errors:
1740 results.append(output_api.PresubmitError(
1741 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1742 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1743 '/res/drawable-ldrtl/.\n'
1744 'Contact [email protected] if you have questions.', errors))
1745 return results
1746
1747
agrievef32bcc72016-04-04 14:57:401748class PydepsChecker(object):
1749 def __init__(self, input_api, pydeps_files):
1750 self._file_cache = {}
1751 self._input_api = input_api
1752 self._pydeps_files = pydeps_files
1753
1754 def _LoadFile(self, path):
1755 """Returns the list of paths within a .pydeps file relative to //."""
1756 if path not in self._file_cache:
1757 with open(path) as f:
1758 self._file_cache[path] = f.read()
1759 return self._file_cache[path]
1760
1761 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1762 """Returns an interable of paths within the .pydep, relativized to //."""
1763 os_path = self._input_api.os_path
1764 pydeps_dir = os_path.dirname(pydeps_path)
1765 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1766 if not l.startswith('*'))
1767 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1768
1769 def _CreateFilesToPydepsMap(self):
1770 """Returns a map of local_path -> list_of_pydeps."""
1771 ret = {}
1772 for pydep_local_path in self._pydeps_files:
1773 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1774 ret.setdefault(path, []).append(pydep_local_path)
1775 return ret
1776
1777 def ComputeAffectedPydeps(self):
1778 """Returns an iterable of .pydeps files that might need regenerating."""
1779 affected_pydeps = set()
1780 file_to_pydeps_map = None
1781 for f in self._input_api.AffectedFiles(include_deletes=True):
1782 local_path = f.LocalPath()
1783 if local_path == 'DEPS':
1784 return self._pydeps_files
1785 elif local_path.endswith('.pydeps'):
1786 if local_path in self._pydeps_files:
1787 affected_pydeps.add(local_path)
1788 elif local_path.endswith('.py'):
1789 if file_to_pydeps_map is None:
1790 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1791 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1792 return affected_pydeps
1793
1794 def DetermineIfStale(self, pydeps_path):
1795 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411796 import difflib
agrievef32bcc72016-04-04 14:57:401797 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1798 cmd = old_pydeps_data[1][1:].strip()
1799 new_pydeps_data = self._input_api.subprocess.check_output(
1800 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411801 old_contents = old_pydeps_data[2:]
1802 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401803 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411804 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401805
1806
1807def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1808 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001809 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281810 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1811 # Mac, so skip it on other platforms.
1812 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001813 return []
agrievef32bcc72016-04-04 14:57:401814 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1815 is_android = input_api.os_path.exists('third_party/android_tools')
1816 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1817 results = []
1818 # First, check for new / deleted .pydeps.
1819 for f in input_api.AffectedFiles(include_deletes=True):
1820 if f.LocalPath().endswith('.pydeps'):
1821 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1822 results.append(output_api.PresubmitError(
1823 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1824 'remove %s' % f.LocalPath()))
1825 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1826 results.append(output_api.PresubmitError(
1827 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1828 'include %s' % f.LocalPath()))
1829
1830 if results:
1831 return results
1832
1833 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1834
1835 for pydep_path in checker.ComputeAffectedPydeps():
1836 try:
phajdan.jr0d9878552016-11-04 10:49:411837 result = checker.DetermineIfStale(pydep_path)
1838 if result:
1839 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401840 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411841 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1842 'To regenerate, run:\n\n %s' %
1843 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401844 except input_api.subprocess.CalledProcessError as error:
1845 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1846 long_text=error.output)]
1847
1848 return results
1849
1850
glidere61efad2015-02-18 17:39:431851def _CheckSingletonInHeaders(input_api, output_api):
1852 """Checks to make sure no header files have |Singleton<|."""
1853 def FileFilter(affected_file):
1854 # It's ok for base/memory/singleton.h to have |Singleton<|.
1855 black_list = (_EXCLUDED_PATHS +
1856 input_api.DEFAULT_BLACK_LIST +
1857 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1858 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1859
sergeyu34d21222015-09-16 00:11:441860 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431861 files = []
1862 for f in input_api.AffectedSourceFiles(FileFilter):
1863 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1864 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1865 contents = input_api.ReadFile(f)
1866 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241867 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431868 pattern.search(line)):
1869 files.append(f)
1870 break
1871
1872 if files:
yolandyandaabc6d2016-04-18 18:29:391873 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441874 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431875 'Please move them to an appropriate source file so that the ' +
1876 'template gets instantiated in a single compilation unit.',
1877 files) ]
1878 return []
1879
1880
dbeam37e8e7402016-02-10 22:58:201881def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1882 """Checks for old style compiled_resources.gyp files."""
1883 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1884
1885 added_compiled_resources = filter(is_compiled_resource, [
1886 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1887 ])
1888
1889 if not added_compiled_resources:
1890 return []
1891
1892 return [output_api.PresubmitError(
1893 "Found new compiled_resources.gyp files:\n%s\n\n"
1894 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551895 "please use compiled_resources2.gyp instead:\n"
1896 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1897 %
dbeam37e8e7402016-02-10 22:58:201898 "\n".join(added_compiled_resources))]
1899
1900
[email protected]fd20b902014-05-09 02:14:531901_DEPRECATED_CSS = [
1902 # Values
1903 ( "-webkit-box", "flex" ),
1904 ( "-webkit-inline-box", "inline-flex" ),
1905 ( "-webkit-flex", "flex" ),
1906 ( "-webkit-inline-flex", "inline-flex" ),
1907 ( "-webkit-min-content", "min-content" ),
1908 ( "-webkit-max-content", "max-content" ),
1909
1910 # Properties
1911 ( "-webkit-background-clip", "background-clip" ),
1912 ( "-webkit-background-origin", "background-origin" ),
1913 ( "-webkit-background-size", "background-size" ),
1914 ( "-webkit-box-shadow", "box-shadow" ),
1915
1916 # Functions
1917 ( "-webkit-gradient", "gradient" ),
1918 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1919 ( "-webkit-linear-gradient", "linear-gradient" ),
1920 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1921 ( "-webkit-radial-gradient", "radial-gradient" ),
1922 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1923]
1924
1925def _CheckNoDeprecatedCSS(input_api, output_api):
1926 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251927 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341928 documentation and iOS CSS for dom distiller
1929 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251930 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531931 results = []
dbeam070cfe62014-10-22 06:44:021932 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251933 black_list = (_EXCLUDED_PATHS +
1934 _TEST_CODE_EXCLUDED_PATHS +
1935 input_api.DEFAULT_BLACK_LIST +
1936 (r"^chrome/common/extensions/docs",
1937 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341938 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051939 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441940 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251941 r"^native_client_sdk"))
1942 file_filter = lambda f: input_api.FilterSourceFile(
1943 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531944 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1945 for line_num, line in fpath.ChangedContents():
1946 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021947 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531948 results.append(output_api.PresubmitError(
1949 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1950 (fpath.LocalPath(), line_num, deprecated_value, value)))
1951 return results
1952
mohan.reddyf21db962014-10-16 12:26:471953
dbeam070cfe62014-10-22 06:44:021954_DEPRECATED_JS = [
1955 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1956 ( "__defineGetter__", "Object.defineProperty" ),
1957 ( "__defineSetter__", "Object.defineProperty" ),
1958]
1959
1960def _CheckNoDeprecatedJS(input_api, output_api):
1961 """Make sure that we don't use deprecated JS in Chrome code."""
1962 results = []
1963 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1964 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1965 input_api.DEFAULT_BLACK_LIST)
1966 file_filter = lambda f: input_api.FilterSourceFile(
1967 f, white_list=file_inclusion_pattern, black_list=black_list)
1968 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1969 for lnum, line in fpath.ChangedContents():
1970 for (deprecated, replacement) in _DEPRECATED_JS:
1971 if deprecated in line:
1972 results.append(output_api.PresubmitError(
1973 "%s:%d: Use of deprecated JS %s, use %s instead" %
1974 (fpath.LocalPath(), lnum, deprecated, replacement)))
1975 return results
1976
1977
dgnaa68d5e2015-06-10 10:08:221978def _AndroidSpecificOnUploadChecks(input_api, output_api):
1979 """Groups checks that target android code."""
1980 results = []
dgnaa68d5e2015-06-10 10:08:221981 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221982 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291983 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221984 return results
1985
1986
[email protected]22c9bd72011-03-27 16:47:391987def _CommonChecks(input_api, output_api):
1988 """Checks common to both upload and commit."""
1989 results = []
1990 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381991 input_api, output_api,
1992 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461993 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191994 results.extend(
[email protected]760deea2013-12-10 19:33:491995 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541996 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181997 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521998 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221999 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442000 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592001 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062002 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122003 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182004 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222005 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492006 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272007 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032008 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492009 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442010 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272011 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542012 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442013 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392014 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552015 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042016 results.extend(
2017 input_api.canned_checks.CheckChangeHasNoTabs(
2018 input_api,
2019 output_api,
2020 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402021 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162022 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592023 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082024 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:532025 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:022026 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472027 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042028 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232029 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432030 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:202031 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402032 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152033 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172034 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232035 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242036
2037 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2038 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2039 input_api, output_api,
2040 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382041 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392042 return results
[email protected]1f7b4172010-01-28 01:17:342043
[email protected]b337cb5b2011-01-23 21:24:052044
[email protected]66daa702011-05-28 14:41:462045def _CheckAuthorizedAuthor(input_api, output_api):
2046 """For non-googler/chromites committers, verify the author's email address is
2047 in AUTHORS.
2048 """
2049 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012050 if not author:
2051 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462052 return []
[email protected]c99663292011-05-31 19:46:082053 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462054 input_api.PresubmitLocalPath(), 'AUTHORS')
2055 valid_authors = (
2056 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2057 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182058 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172059 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2060 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232061 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462062 return [output_api.PresubmitPromptWarning(
2063 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2064 '\n'
2065 'http://www.chromium.org/developers/contributing-code and read the '
2066 '"Legal" section\n'
2067 'If you are a chromite, verify the contributor signed the CLA.') %
2068 author)]
2069 return []
2070
2071
[email protected]b8079ae4a2012-12-05 19:56:492072def _CheckPatchFiles(input_api, output_api):
2073 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2074 if f.LocalPath().endswith(('.orig', '.rej'))]
2075 if problems:
2076 return [output_api.PresubmitError(
2077 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032078 else:
2079 return []
[email protected]b8079ae4a2012-12-05 19:56:492080
2081
[email protected]b00342e7f2013-03-26 16:21:542082def _DidYouMeanOSMacro(bad_macro):
2083 try:
2084 return {'A': 'OS_ANDROID',
2085 'B': 'OS_BSD',
2086 'C': 'OS_CHROMEOS',
2087 'F': 'OS_FREEBSD',
2088 'L': 'OS_LINUX',
2089 'M': 'OS_MACOSX',
2090 'N': 'OS_NACL',
2091 'O': 'OS_OPENBSD',
2092 'P': 'OS_POSIX',
2093 'S': 'OS_SOLARIS',
2094 'W': 'OS_WIN'}[bad_macro[3].upper()]
2095 except KeyError:
2096 return ''
2097
2098
2099def _CheckForInvalidOSMacrosInFile(input_api, f):
2100 """Check for sensible looking, totally invalid OS macros."""
2101 preprocessor_statement = input_api.re.compile(r'^\s*#')
2102 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2103 results = []
2104 for lnum, line in f.ChangedContents():
2105 if preprocessor_statement.search(line):
2106 for match in os_macro.finditer(line):
2107 if not match.group(1) in _VALID_OS_MACROS:
2108 good = _DidYouMeanOSMacro(match.group(1))
2109 did_you_mean = ' (did you mean %s?)' % good if good else ''
2110 results.append(' %s:%d %s%s' % (f.LocalPath(),
2111 lnum,
2112 match.group(1),
2113 did_you_mean))
2114 return results
2115
2116
2117def _CheckForInvalidOSMacros(input_api, output_api):
2118 """Check all affected files for invalid OS macros."""
2119 bad_macros = []
2120 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472121 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542122 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2123
2124 if not bad_macros:
2125 return []
2126
2127 return [output_api.PresubmitError(
2128 'Possibly invalid OS macro[s] found. Please fix your code\n'
2129 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2130
lliabraa35bab3932014-10-01 12:16:442131
2132def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2133 """Check all affected files for invalid "if defined" macros."""
2134 ALWAYS_DEFINED_MACROS = (
2135 "TARGET_CPU_PPC",
2136 "TARGET_CPU_PPC64",
2137 "TARGET_CPU_68K",
2138 "TARGET_CPU_X86",
2139 "TARGET_CPU_ARM",
2140 "TARGET_CPU_MIPS",
2141 "TARGET_CPU_SPARC",
2142 "TARGET_CPU_ALPHA",
2143 "TARGET_IPHONE_SIMULATOR",
2144 "TARGET_OS_EMBEDDED",
2145 "TARGET_OS_IPHONE",
2146 "TARGET_OS_MAC",
2147 "TARGET_OS_UNIX",
2148 "TARGET_OS_WIN32",
2149 )
2150 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2151 results = []
2152 for lnum, line in f.ChangedContents():
2153 for match in ifdef_macro.finditer(line):
2154 if match.group(1) in ALWAYS_DEFINED_MACROS:
2155 always_defined = ' %s is always defined. ' % match.group(1)
2156 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2157 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2158 lnum,
2159 always_defined,
2160 did_you_mean))
2161 return results
2162
2163
2164def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2165 """Check all affected files for invalid "if defined" macros."""
2166 bad_macros = []
2167 for f in input_api.AffectedFiles():
2168 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2169 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2170
2171 if not bad_macros:
2172 return []
2173
2174 return [output_api.PresubmitError(
2175 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2176 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2177 bad_macros)]
2178
2179
mlamouria82272622014-09-16 18:45:042180def _CheckForIPCRules(input_api, output_api):
2181 """Check for same IPC rules described in
2182 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2183 """
2184 base_pattern = r'IPC_ENUM_TRAITS\('
2185 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2186 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2187
2188 problems = []
2189 for f in input_api.AffectedSourceFiles(None):
2190 local_path = f.LocalPath()
2191 if not local_path.endswith('.h'):
2192 continue
2193 for line_number, line in f.ChangedContents():
2194 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2195 problems.append(
2196 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2197
2198 if problems:
2199 return [output_api.PresubmitPromptWarning(
2200 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2201 else:
2202 return []
2203
[email protected]b00342e7f2013-03-26 16:21:542204
mostynbb639aca52015-01-07 20:31:232205def _CheckForWindowsLineEndings(input_api, output_api):
2206 """Check source code and known ascii text files for Windows style line
2207 endings.
2208 """
earthdok1b5e0ee2015-03-10 15:19:102209 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232210
2211 file_inclusion_pattern = (
2212 known_text_files,
2213 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2214 )
2215
2216 filter = lambda f: input_api.FilterSourceFile(
2217 f, white_list=file_inclusion_pattern, black_list=None)
2218 files = [f.LocalPath() for f in
2219 input_api.AffectedSourceFiles(filter)]
2220
2221 problems = []
2222
2223 for file in files:
2224 fp = open(file, 'r')
2225 for line in fp:
2226 if line.endswith('\r\n'):
2227 problems.append(file)
2228 break
2229 fp.close()
2230
2231 if problems:
2232 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2233 'these files to contain Windows style line endings?\n' +
2234 '\n'.join(problems))]
2235
2236 return []
2237
2238
pastarmovj89f7ee12016-09-20 14:58:132239def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2240 lint_filters=None, verbose_level=None):
2241 """Checks that all source files use SYSLOG properly."""
2242 syslog_files = []
2243 for f in input_api.AffectedSourceFiles(source_file_filter):
2244 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2245 syslog_files.append(f.LocalPath())
2246 if syslog_files:
2247 return [output_api.PresubmitPromptWarning(
2248 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2249 ' calls.\nFiles to check:\n', items=syslog_files)]
2250 return []
2251
2252
[email protected]1f7b4172010-01-28 01:17:342253def CheckChangeOnUpload(input_api, output_api):
2254 results = []
2255 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472256 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282257 results.extend(
2258 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192259 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222260 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132261 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542262 return results
[email protected]ca8d1982009-02-19 16:33:122263
2264
[email protected]1bfb8322014-04-23 01:02:412265def GetTryServerMasterForBot(bot):
2266 """Returns the Try Server master for the given bot.
2267
[email protected]0bb112362014-07-26 04:38:322268 It tries to guess the master from the bot name, but may still fail
2269 and return None. There is no longer a default master.
2270 """
2271 # Potentially ambiguous bot names are listed explicitly.
2272 master_map = {
tandriie5587792016-07-14 00:34:502273 'chromium_presubmit': 'master.tryserver.chromium.linux',
2274 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412275 }
[email protected]0bb112362014-07-26 04:38:322276 master = master_map.get(bot)
2277 if not master:
wnwen4fbaab82016-05-25 12:54:362278 if 'android' in bot:
tandriie5587792016-07-14 00:34:502279 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362280 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502281 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322282 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502283 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322284 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502285 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322286 return master
[email protected]1bfb8322014-04-23 01:02:412287
2288
Paweł Hajdan, Jr55083782014-12-19 20:32:562289def GetDefaultTryConfigs(bots):
2290 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012291 """
2292
Paweł Hajdan, Jr55083782014-12-19 20:32:562293 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412294
2295 # Build up the mapping from tryserver master to bot/test.
2296 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562297 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412298 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2299 return out
[email protected]38c6a512013-12-18 23:48:012300
2301
[email protected]ca8d1982009-02-19 16:33:122302def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542303 results = []
[email protected]1f7b4172010-01-28 01:17:342304 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542305 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272306 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342307 input_api,
2308 output_api,
[email protected]2fdd1f362013-01-16 03:56:032309 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272310
[email protected]3e4eb112011-01-18 03:29:542311 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2312 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412313 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2314 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542315 return results