blob: b7680b1a65d97a9d0139bac63d1eeee944fd487b [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d19842009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]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]ca8d19842009-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
jbriance9e12f162016-11-25 07:57:501587def _CheckUselessForwardDeclarations(input_api, output_api):
1588 """Checks that added or removed lines in affected header files
1589 do not lead to new useless class or struct forward declaration.
1590 """
1591 results = []
1592 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1593 input_api.re.MULTILINE)
1594 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1595 input_api.re.MULTILINE)
1596 for f in input_api.AffectedFiles(include_deletes=False):
1597 if not f.LocalPath().endswith('.h'):
1598 continue
1599
1600 contents = input_api.ReadFile(f)
1601 fwd_decls = input_api.re.findall(class_pattern, contents)
1602 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1603
1604 useless_fwd_decls = []
1605 for decl in fwd_decls:
1606 count = sum(1 for _ in input_api.re.finditer(
1607 r'\b%s\b' % input_api.re.escape(decl), contents))
1608 if count == 1:
1609 useless_fwd_decls.append(decl)
1610
1611 if not useless_fwd_decls:
1612 continue
1613
1614 for line in f.GenerateScmDiff().splitlines():
1615 if (line.startswith('-') and not line.startswith('--') or
1616 line.startswith('+') and not line.startswith('++')):
1617 for decl in useless_fwd_decls:
1618 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1619 results.append(output_api.PresubmitPromptWarning(
1620 '%s: %s forward declaration is becoming useless' %
1621 (f.LocalPath(), decl)))
1622 useless_fwd_decls.remove(decl)
1623
1624 return results
1625
1626
dskiba88634f4e2015-08-14 23:03:291627def _CheckAndroidToastUsage(input_api, output_api):
1628 """Checks that code uses org.chromium.ui.widget.Toast instead of
1629 android.widget.Toast (Chromium Toast doesn't force hardware
1630 acceleration on low-end devices, saving memory).
1631 """
1632 toast_import_pattern = input_api.re.compile(
1633 r'^import android\.widget\.Toast;$')
1634
1635 errors = []
1636
1637 sources = lambda affected_file: input_api.FilterSourceFile(
1638 affected_file,
1639 black_list=(_EXCLUDED_PATHS +
1640 _TEST_CODE_EXCLUDED_PATHS +
1641 input_api.DEFAULT_BLACK_LIST +
1642 (r'^chromecast[\\\/].*',
1643 r'^remoting[\\\/].*')),
1644 white_list=(r'.*\.java$',))
1645
1646 for f in input_api.AffectedSourceFiles(sources):
1647 for line_num, line in f.ChangedContents():
1648 if toast_import_pattern.search(line):
1649 errors.append("%s:%d" % (f.LocalPath(), line_num))
1650
1651 results = []
1652
1653 if errors:
1654 results.append(output_api.PresubmitError(
1655 'android.widget.Toast usage is detected. Android toasts use hardware'
1656 ' acceleration, and can be\ncostly on low-end devices. Please use'
1657 ' org.chromium.ui.widget.Toast instead.\n'
1658 'Contact [email protected] if you have any questions.',
1659 errors))
1660
1661 return results
1662
1663
dgnaa68d5e2015-06-10 10:08:221664def _CheckAndroidCrLogUsage(input_api, output_api):
1665 """Checks that new logs using org.chromium.base.Log:
1666 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511667 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221668 """
pkotwicza1dd0b002016-05-16 14:41:041669
1670 # Do not check format of logs in //chrome/android/webapk because
1671 # //chrome/android/webapk cannot depend on //base
1672 cr_log_check_excluded_paths = [
1673 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1674 ]
1675
dgnaa68d5e2015-06-10 10:08:221676 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121677 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1678 class_in_base_pattern = input_api.re.compile(
1679 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1680 has_some_log_import_pattern = input_api.re.compile(
1681 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221682 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121683 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221684 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511685 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221686 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221687
Vincent Scheib16d7b272015-09-15 18:09:071688 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221689 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041690 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1691 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121692
dgnaa68d5e2015-06-10 10:08:221693 tag_decl_errors = []
1694 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121695 tag_errors = []
dgn38736db2015-09-18 19:20:511696 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121697 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221698
1699 for f in input_api.AffectedSourceFiles(sources):
1700 file_content = input_api.ReadFile(f)
1701 has_modified_logs = False
1702
1703 # Per line checks
dgn87d9fb62015-06-12 09:15:121704 if (cr_log_import_pattern.search(file_content) or
1705 (class_in_base_pattern.search(file_content) and
1706 not has_some_log_import_pattern.search(file_content))):
1707 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221708 for line_num, line in f.ChangedContents():
1709
1710 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121711 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221712 if match:
1713 has_modified_logs = True
1714
1715 # Make sure it uses "TAG"
1716 if not match.group('tag') == 'TAG':
1717 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121718 else:
1719 # Report non cr Log function calls in changed lines
1720 for line_num, line in f.ChangedContents():
1721 if log_call_pattern.search(line):
1722 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221723
1724 # Per file checks
1725 if has_modified_logs:
1726 # Make sure the tag is using the "cr" prefix and is not too long
1727 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511728 tag_name = match.group('name') if match else None
1729 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221730 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511731 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221732 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511733 elif '.' in tag_name:
1734 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221735
1736 results = []
1737 if tag_decl_errors:
1738 results.append(output_api.PresubmitPromptWarning(
1739 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511740 '"private static final String TAG = "<package tag>".\n'
1741 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221742 tag_decl_errors))
1743
1744 if tag_length_errors:
1745 results.append(output_api.PresubmitError(
1746 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511747 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221748 tag_length_errors))
1749
1750 if tag_errors:
1751 results.append(output_api.PresubmitPromptWarning(
1752 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1753 tag_errors))
1754
dgn87d9fb62015-06-12 09:15:121755 if util_log_errors:
dgn4401aa52015-04-29 16:26:171756 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121757 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1758 util_log_errors))
1759
dgn38736db2015-09-18 19:20:511760 if tag_with_dot_errors:
1761 results.append(output_api.PresubmitPromptWarning(
1762 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1763 tag_with_dot_errors))
1764
dgn4401aa52015-04-29 16:26:171765 return results
1766
1767
agrieve7b6479d82015-10-07 14:24:221768def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1769 """Checks if MDPI assets are placed in a correct directory."""
1770 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1771 ('/res/drawable/' in f.LocalPath() or
1772 '/res/drawable-ldrtl/' in f.LocalPath()))
1773 errors = []
1774 for f in input_api.AffectedFiles(include_deletes=False,
1775 file_filter=file_filter):
1776 errors.append(' %s' % f.LocalPath())
1777
1778 results = []
1779 if errors:
1780 results.append(output_api.PresubmitError(
1781 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1782 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1783 '/res/drawable-ldrtl/.\n'
1784 'Contact [email protected] if you have questions.', errors))
1785 return results
1786
1787
agrievef32bcc72016-04-04 14:57:401788class PydepsChecker(object):
1789 def __init__(self, input_api, pydeps_files):
1790 self._file_cache = {}
1791 self._input_api = input_api
1792 self._pydeps_files = pydeps_files
1793
1794 def _LoadFile(self, path):
1795 """Returns the list of paths within a .pydeps file relative to //."""
1796 if path not in self._file_cache:
1797 with open(path) as f:
1798 self._file_cache[path] = f.read()
1799 return self._file_cache[path]
1800
1801 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1802 """Returns an interable of paths within the .pydep, relativized to //."""
1803 os_path = self._input_api.os_path
1804 pydeps_dir = os_path.dirname(pydeps_path)
1805 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1806 if not l.startswith('*'))
1807 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1808
1809 def _CreateFilesToPydepsMap(self):
1810 """Returns a map of local_path -> list_of_pydeps."""
1811 ret = {}
1812 for pydep_local_path in self._pydeps_files:
1813 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1814 ret.setdefault(path, []).append(pydep_local_path)
1815 return ret
1816
1817 def ComputeAffectedPydeps(self):
1818 """Returns an iterable of .pydeps files that might need regenerating."""
1819 affected_pydeps = set()
1820 file_to_pydeps_map = None
1821 for f in self._input_api.AffectedFiles(include_deletes=True):
1822 local_path = f.LocalPath()
1823 if local_path == 'DEPS':
1824 return self._pydeps_files
1825 elif local_path.endswith('.pydeps'):
1826 if local_path in self._pydeps_files:
1827 affected_pydeps.add(local_path)
1828 elif local_path.endswith('.py'):
1829 if file_to_pydeps_map is None:
1830 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1831 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1832 return affected_pydeps
1833
1834 def DetermineIfStale(self, pydeps_path):
1835 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411836 import difflib
agrievef32bcc72016-04-04 14:57:401837 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1838 cmd = old_pydeps_data[1][1:].strip()
1839 new_pydeps_data = self._input_api.subprocess.check_output(
1840 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411841 old_contents = old_pydeps_data[2:]
1842 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401843 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411844 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401845
1846
1847def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1848 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001849 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281850 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1851 # Mac, so skip it on other platforms.
1852 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001853 return []
agrievef32bcc72016-04-04 14:57:401854 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1855 is_android = input_api.os_path.exists('third_party/android_tools')
1856 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1857 results = []
1858 # First, check for new / deleted .pydeps.
1859 for f in input_api.AffectedFiles(include_deletes=True):
1860 if f.LocalPath().endswith('.pydeps'):
1861 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1862 results.append(output_api.PresubmitError(
1863 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1864 'remove %s' % f.LocalPath()))
1865 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1866 results.append(output_api.PresubmitError(
1867 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1868 'include %s' % f.LocalPath()))
1869
1870 if results:
1871 return results
1872
1873 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1874
1875 for pydep_path in checker.ComputeAffectedPydeps():
1876 try:
phajdan.jr0d9878552016-11-04 10:49:411877 result = checker.DetermineIfStale(pydep_path)
1878 if result:
1879 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401880 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411881 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1882 'To regenerate, run:\n\n %s' %
1883 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401884 except input_api.subprocess.CalledProcessError as error:
1885 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1886 long_text=error.output)]
1887
1888 return results
1889
1890
glidere61efad2015-02-18 17:39:431891def _CheckSingletonInHeaders(input_api, output_api):
1892 """Checks to make sure no header files have |Singleton<|."""
1893 def FileFilter(affected_file):
1894 # It's ok for base/memory/singleton.h to have |Singleton<|.
1895 black_list = (_EXCLUDED_PATHS +
1896 input_api.DEFAULT_BLACK_LIST +
1897 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1898 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1899
sergeyu34d21222015-09-16 00:11:441900 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431901 files = []
1902 for f in input_api.AffectedSourceFiles(FileFilter):
1903 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1904 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1905 contents = input_api.ReadFile(f)
1906 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241907 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431908 pattern.search(line)):
1909 files.append(f)
1910 break
1911
1912 if files:
yolandyandaabc6d2016-04-18 18:29:391913 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441914 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431915 'Please move them to an appropriate source file so that the ' +
1916 'template gets instantiated in a single compilation unit.',
1917 files) ]
1918 return []
1919
1920
dbeam37e8e7402016-02-10 22:58:201921def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1922 """Checks for old style compiled_resources.gyp files."""
1923 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1924
1925 added_compiled_resources = filter(is_compiled_resource, [
1926 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1927 ])
1928
1929 if not added_compiled_resources:
1930 return []
1931
1932 return [output_api.PresubmitError(
1933 "Found new compiled_resources.gyp files:\n%s\n\n"
1934 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551935 "please use compiled_resources2.gyp instead:\n"
1936 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1937 %
dbeam37e8e7402016-02-10 22:58:201938 "\n".join(added_compiled_resources))]
1939
1940
[email protected]fd20b902014-05-09 02:14:531941_DEPRECATED_CSS = [
1942 # Values
1943 ( "-webkit-box", "flex" ),
1944 ( "-webkit-inline-box", "inline-flex" ),
1945 ( "-webkit-flex", "flex" ),
1946 ( "-webkit-inline-flex", "inline-flex" ),
1947 ( "-webkit-min-content", "min-content" ),
1948 ( "-webkit-max-content", "max-content" ),
1949
1950 # Properties
1951 ( "-webkit-background-clip", "background-clip" ),
1952 ( "-webkit-background-origin", "background-origin" ),
1953 ( "-webkit-background-size", "background-size" ),
1954 ( "-webkit-box-shadow", "box-shadow" ),
1955
1956 # Functions
1957 ( "-webkit-gradient", "gradient" ),
1958 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1959 ( "-webkit-linear-gradient", "linear-gradient" ),
1960 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1961 ( "-webkit-radial-gradient", "radial-gradient" ),
1962 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1963]
1964
1965def _CheckNoDeprecatedCSS(input_api, output_api):
1966 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251967 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341968 documentation and iOS CSS for dom distiller
1969 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251970 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531971 results = []
dbeam070cfe62014-10-22 06:44:021972 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251973 black_list = (_EXCLUDED_PATHS +
1974 _TEST_CODE_EXCLUDED_PATHS +
1975 input_api.DEFAULT_BLACK_LIST +
1976 (r"^chrome/common/extensions/docs",
1977 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341978 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051979 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441980 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251981 r"^native_client_sdk"))
1982 file_filter = lambda f: input_api.FilterSourceFile(
1983 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531984 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1985 for line_num, line in fpath.ChangedContents():
1986 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021987 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531988 results.append(output_api.PresubmitError(
1989 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1990 (fpath.LocalPath(), line_num, deprecated_value, value)))
1991 return results
1992
mohan.reddyf21db962014-10-16 12:26:471993
dbeam070cfe62014-10-22 06:44:021994_DEPRECATED_JS = [
1995 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1996 ( "__defineGetter__", "Object.defineProperty" ),
1997 ( "__defineSetter__", "Object.defineProperty" ),
1998]
1999
2000def _CheckNoDeprecatedJS(input_api, output_api):
2001 """Make sure that we don't use deprecated JS in Chrome code."""
2002 results = []
2003 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2004 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2005 input_api.DEFAULT_BLACK_LIST)
2006 file_filter = lambda f: input_api.FilterSourceFile(
2007 f, white_list=file_inclusion_pattern, black_list=black_list)
2008 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2009 for lnum, line in fpath.ChangedContents():
2010 for (deprecated, replacement) in _DEPRECATED_JS:
2011 if deprecated in line:
2012 results.append(output_api.PresubmitError(
2013 "%s:%d: Use of deprecated JS %s, use %s instead" %
2014 (fpath.LocalPath(), lnum, deprecated, replacement)))
2015 return results
2016
2017
dgnaa68d5e2015-06-10 10:08:222018def _AndroidSpecificOnUploadChecks(input_api, output_api):
2019 """Groups checks that target android code."""
2020 results = []
dgnaa68d5e2015-06-10 10:08:222021 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222022 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292023 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222024 return results
2025
2026
[email protected]22c9bd72011-03-27 16:47:392027def _CommonChecks(input_api, output_api):
2028 """Checks common to both upload and commit."""
2029 results = []
2030 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382031 input_api, output_api,
2032 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
machenbachfbda9b72016-12-06 13:13:582033 results.extend(
2034 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192035 results.extend(
[email protected]760deea2013-12-10 19:33:492036 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542037 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182038 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522039 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222040 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442041 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592042 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062043 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122044 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182045 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222046 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492047 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272048 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032049 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492050 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442051 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272052 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542053 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442054 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392055 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552056 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042057 results.extend(
2058 input_api.canned_checks.CheckChangeHasNoTabs(
2059 input_api,
2060 output_api,
2061 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402062 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162063 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592064 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082065 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:532066 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:022067 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472068 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042069 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232070 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432071 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:202072 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402073 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152074 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172075 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232076 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502077 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242078
2079 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2080 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2081 input_api, output_api,
2082 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382083 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392084 return results
[email protected]1f7b4172010-01-28 01:17:342085
[email protected]b337cb5b2011-01-23 21:24:052086
[email protected]b8079ae4a2012-12-05 19:56:492087def _CheckPatchFiles(input_api, output_api):
2088 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2089 if f.LocalPath().endswith(('.orig', '.rej'))]
2090 if problems:
2091 return [output_api.PresubmitError(
2092 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032093 else:
2094 return []
[email protected]b8079ae4a2012-12-05 19:56:492095
2096
[email protected]b00342e7f2013-03-26 16:21:542097def _DidYouMeanOSMacro(bad_macro):
2098 try:
2099 return {'A': 'OS_ANDROID',
2100 'B': 'OS_BSD',
2101 'C': 'OS_CHROMEOS',
2102 'F': 'OS_FREEBSD',
2103 'L': 'OS_LINUX',
2104 'M': 'OS_MACOSX',
2105 'N': 'OS_NACL',
2106 'O': 'OS_OPENBSD',
2107 'P': 'OS_POSIX',
2108 'S': 'OS_SOLARIS',
2109 'W': 'OS_WIN'}[bad_macro[3].upper()]
2110 except KeyError:
2111 return ''
2112
2113
2114def _CheckForInvalidOSMacrosInFile(input_api, f):
2115 """Check for sensible looking, totally invalid OS macros."""
2116 preprocessor_statement = input_api.re.compile(r'^\s*#')
2117 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2118 results = []
2119 for lnum, line in f.ChangedContents():
2120 if preprocessor_statement.search(line):
2121 for match in os_macro.finditer(line):
2122 if not match.group(1) in _VALID_OS_MACROS:
2123 good = _DidYouMeanOSMacro(match.group(1))
2124 did_you_mean = ' (did you mean %s?)' % good if good else ''
2125 results.append(' %s:%d %s%s' % (f.LocalPath(),
2126 lnum,
2127 match.group(1),
2128 did_you_mean))
2129 return results
2130
2131
2132def _CheckForInvalidOSMacros(input_api, output_api):
2133 """Check all affected files for invalid OS macros."""
2134 bad_macros = []
2135 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472136 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542137 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2138
2139 if not bad_macros:
2140 return []
2141
2142 return [output_api.PresubmitError(
2143 'Possibly invalid OS macro[s] found. Please fix your code\n'
2144 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2145
lliabraa35bab3932014-10-01 12:16:442146
2147def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2148 """Check all affected files for invalid "if defined" macros."""
2149 ALWAYS_DEFINED_MACROS = (
2150 "TARGET_CPU_PPC",
2151 "TARGET_CPU_PPC64",
2152 "TARGET_CPU_68K",
2153 "TARGET_CPU_X86",
2154 "TARGET_CPU_ARM",
2155 "TARGET_CPU_MIPS",
2156 "TARGET_CPU_SPARC",
2157 "TARGET_CPU_ALPHA",
2158 "TARGET_IPHONE_SIMULATOR",
2159 "TARGET_OS_EMBEDDED",
2160 "TARGET_OS_IPHONE",
2161 "TARGET_OS_MAC",
2162 "TARGET_OS_UNIX",
2163 "TARGET_OS_WIN32",
2164 )
2165 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2166 results = []
2167 for lnum, line in f.ChangedContents():
2168 for match in ifdef_macro.finditer(line):
2169 if match.group(1) in ALWAYS_DEFINED_MACROS:
2170 always_defined = ' %s is always defined. ' % match.group(1)
2171 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2172 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2173 lnum,
2174 always_defined,
2175 did_you_mean))
2176 return results
2177
2178
2179def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2180 """Check all affected files for invalid "if defined" macros."""
2181 bad_macros = []
2182 for f in input_api.AffectedFiles():
2183 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2184 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2185
2186 if not bad_macros:
2187 return []
2188
2189 return [output_api.PresubmitError(
2190 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2191 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2192 bad_macros)]
2193
2194
mlamouria82272622014-09-16 18:45:042195def _CheckForIPCRules(input_api, output_api):
2196 """Check for same IPC rules described in
2197 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2198 """
2199 base_pattern = r'IPC_ENUM_TRAITS\('
2200 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2201 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2202
2203 problems = []
2204 for f in input_api.AffectedSourceFiles(None):
2205 local_path = f.LocalPath()
2206 if not local_path.endswith('.h'):
2207 continue
2208 for line_number, line in f.ChangedContents():
2209 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2210 problems.append(
2211 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2212
2213 if problems:
2214 return [output_api.PresubmitPromptWarning(
2215 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2216 else:
2217 return []
2218
[email protected]b00342e7f2013-03-26 16:21:542219
mostynbb639aca52015-01-07 20:31:232220def _CheckForWindowsLineEndings(input_api, output_api):
2221 """Check source code and known ascii text files for Windows style line
2222 endings.
2223 """
earthdok1b5e0ee2015-03-10 15:19:102224 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232225
2226 file_inclusion_pattern = (
2227 known_text_files,
2228 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2229 )
2230
2231 filter = lambda f: input_api.FilterSourceFile(
2232 f, white_list=file_inclusion_pattern, black_list=None)
2233 files = [f.LocalPath() for f in
2234 input_api.AffectedSourceFiles(filter)]
2235
2236 problems = []
2237
2238 for file in files:
2239 fp = open(file, 'r')
2240 for line in fp:
2241 if line.endswith('\r\n'):
2242 problems.append(file)
2243 break
2244 fp.close()
2245
2246 if problems:
2247 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2248 'these files to contain Windows style line endings?\n' +
2249 '\n'.join(problems))]
2250
2251 return []
2252
2253
pastarmovj89f7ee12016-09-20 14:58:132254def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2255 lint_filters=None, verbose_level=None):
2256 """Checks that all source files use SYSLOG properly."""
2257 syslog_files = []
2258 for f in input_api.AffectedSourceFiles(source_file_filter):
2259 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2260 syslog_files.append(f.LocalPath())
2261 if syslog_files:
2262 return [output_api.PresubmitPromptWarning(
2263 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2264 ' calls.\nFiles to check:\n', items=syslog_files)]
2265 return []
2266
2267
[email protected]1f7b4172010-01-28 01:17:342268def CheckChangeOnUpload(input_api, output_api):
2269 results = []
2270 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472271 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282272 results.extend(
2273 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192274 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222275 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132276 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542277 return results
[email protected]ca8d19842009-02-19 16:33:122278
2279
[email protected]1bfb8322014-04-23 01:02:412280def GetTryServerMasterForBot(bot):
2281 """Returns the Try Server master for the given bot.
2282
[email protected]0bb112362014-07-26 04:38:322283 It tries to guess the master from the bot name, but may still fail
2284 and return None. There is no longer a default master.
2285 """
2286 # Potentially ambiguous bot names are listed explicitly.
2287 master_map = {
tandriie5587792016-07-14 00:34:502288 'chromium_presubmit': 'master.tryserver.chromium.linux',
2289 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412290 }
[email protected]0bb112362014-07-26 04:38:322291 master = master_map.get(bot)
2292 if not master:
wnwen4fbaab82016-05-25 12:54:362293 if 'android' in bot:
tandriie5587792016-07-14 00:34:502294 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362295 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502296 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322297 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502298 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322299 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502300 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322301 return master
[email protected]1bfb8322014-04-23 01:02:412302
2303
Paweł Hajdan, Jr55083782014-12-19 20:32:562304def GetDefaultTryConfigs(bots):
2305 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012306 """
2307
Paweł Hajdan, Jr55083782014-12-19 20:32:562308 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412309
2310 # Build up the mapping from tryserver master to bot/test.
2311 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562312 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412313 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2314 return out
[email protected]38c6a512013-12-18 23:48:012315
2316
[email protected]ca8d19842009-02-19 16:33:122317def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542318 results = []
[email protected]1f7b4172010-01-28 01:17:342319 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542320 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272321 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342322 input_api,
2323 output_api,
[email protected]2fdd1f362013-01-16 03:56:032324 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272325
[email protected]3e4eb112011-01-18 03:29:542326 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2327 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412328 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2329 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542330 return results