blob: 60090e1533deaf9505ed87ba045f16b51f8200c1 [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$",
sergeyu2c41f9842016-12-10 01:45:16219 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53220 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
221 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45222 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
223 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
224 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
225 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
226 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49227 ),
[email protected]23e6cbc2012-06-16 18:51:20228 ),
[email protected]52657f62013-05-20 05:30:31229 (
tomhudsone2c14d552016-05-26 17:07:46230 'setMatrixClip',
231 (
232 'Overriding setMatrixClip() is prohibited; ',
233 'the base function is deprecated. ',
234 ),
235 True,
236 (),
237 ),
238 (
[email protected]52657f62013-05-20 05:30:31239 'SkRefPtr',
240 (
241 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22242 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31243 ),
244 True,
245 (),
246 ),
247 (
248 'SkAutoRef',
249 (
250 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22251 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31252 ),
253 True,
254 (),
255 ),
256 (
257 'SkAutoTUnref',
258 (
259 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22260 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31261 ),
262 True,
263 (),
264 ),
265 (
266 'SkAutoUnref',
267 (
268 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
269 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22270 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31271 ),
272 True,
273 (),
274 ),
[email protected]d89eec82013-12-03 14:10:59275 (
276 r'/HANDLE_EINTR\(.*close',
277 (
278 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
279 'descriptor will be closed, and it is incorrect to retry the close.',
280 'Either call close directly and ignore its return value, or wrap close',
281 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
282 ),
283 True,
284 (),
285 ),
286 (
287 r'/IGNORE_EINTR\((?!.*close)',
288 (
289 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
290 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
291 ),
292 True,
293 (
294 # Files that #define IGNORE_EINTR.
295 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
296 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
297 ),
298 ),
[email protected]ec5b3f02014-04-04 18:43:43299 (
300 r'/v8::Extension\(',
301 (
302 'Do not introduce new v8::Extensions into the code base, use',
303 'gin::Wrappable instead. See http://crbug.com/334679',
304 ),
305 True,
[email protected]f55c90ee62014-04-12 00:50:03306 (
joaodasilva718f87672014-08-30 09:25:49307 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03308 ),
[email protected]ec5b3f02014-04-04 18:43:43309 ),
skyostilf9469f72015-04-20 10:38:52310 (
jame2d1a952016-04-02 00:27:10311 '#pragma comment(lib,',
312 (
313 'Specify libraries to link with in build files and not in the source.',
314 ),
315 True,
316 (),
317 ),
dcheng8f0694bae2016-10-12 15:58:15318 (
avid5a337982016-10-19 23:07:15319 r'STLDeleteElements', # http://crbug.com/555865
320 (
321 'This call is obsolete with C++ 11; create a container with owning',
322 'pointers instead (e.g. std::vector<std::unique_ptr<x>> ).',
323 ),
324 True,
325 (),
326 ),
327 (
328 r'STLDeleteValues', # http://crbug.com/555865
329 (
330 'This call is obsolete with C++ 11; create a map with owning',
331 'pointers instead (e.g. std::map<std::string, std::unique_ptr<x>> ).',
332 ),
333 True,
334 (),
335 ),
[email protected]127f18ec2012-06-16 05:05:59336)
337
wnwenbdc444e2016-05-25 13:44:15338
mlamouria82272622014-09-16 18:45:04339_IPC_ENUM_TRAITS_DEPRECATED = (
340 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
341 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
342
[email protected]127f18ec2012-06-16 05:05:59343
[email protected]b00342e7f2013-03-26 16:21:54344_VALID_OS_MACROS = (
345 # Please keep sorted.
346 'OS_ANDROID',
347 'OS_BSD',
348 'OS_CAT', # For testing.
349 'OS_CHROMEOS',
350 'OS_FREEBSD',
351 'OS_IOS',
352 'OS_LINUX',
353 'OS_MACOSX',
354 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21355 'OS_NACL_NONSFI',
356 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12357 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54358 'OS_OPENBSD',
359 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37360 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54361 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54362 'OS_WIN',
363)
364
365
agrievef32bcc72016-04-04 14:57:40366_ANDROID_SPECIFIC_PYDEPS_FILES = [
367 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19368 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40369]
370
wnwenbdc444e2016-05-25 13:44:15371
agrievef32bcc72016-04-04 14:57:40372_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40373]
374
wnwenbdc444e2016-05-25 13:44:15375
agrievef32bcc72016-04-04 14:57:40376_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
377
378
[email protected]55459852011-08-10 15:17:19379def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
380 """Attempts to prevent use of functions intended only for testing in
381 non-testing code. For now this is just a best-effort implementation
382 that ignores header files and may have some false positives. A
383 better implementation would probably need a proper C++ parser.
384 """
385 # We only scan .cc files and the like, as the declaration of
386 # for-testing functions in header files are hard to distinguish from
387 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44388 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19389
jochenc0d4808c2015-07-27 09:25:42390 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19391 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09392 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19393 exclusion_pattern = input_api.re.compile(
394 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
395 base_function_pattern, base_function_pattern))
396
397 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44398 black_list = (_EXCLUDED_PATHS +
399 _TEST_CODE_EXCLUDED_PATHS +
400 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19401 return input_api.FilterSourceFile(
402 affected_file,
403 white_list=(file_inclusion_pattern, ),
404 black_list=black_list)
405
406 problems = []
407 for f in input_api.AffectedSourceFiles(FilterFile):
408 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24409 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03410 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46411 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03412 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19413 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03414 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19415
416 if problems:
[email protected]f7051d52013-04-02 18:31:42417 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03418 else:
419 return []
[email protected]55459852011-08-10 15:17:19420
421
[email protected]10689ca2011-09-02 02:31:54422def _CheckNoIOStreamInHeaders(input_api, output_api):
423 """Checks to make sure no .h files include <iostream>."""
424 files = []
425 pattern = input_api.re.compile(r'^#include\s*<iostream>',
426 input_api.re.MULTILINE)
427 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
428 if not f.LocalPath().endswith('.h'):
429 continue
430 contents = input_api.ReadFile(f)
431 if pattern.search(contents):
432 files.append(f)
433
434 if len(files):
yolandyandaabc6d2016-04-18 18:29:39435 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06436 'Do not #include <iostream> in header files, since it inserts static '
437 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54438 '#include <ostream>. See http://crbug.com/94794',
439 files) ]
440 return []
441
442
[email protected]72df4e782012-06-21 16:28:18443def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52444 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18445 problems = []
446 for f in input_api.AffectedFiles():
447 if (not f.LocalPath().endswith(('.cc', '.mm'))):
448 continue
449
450 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04451 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18452 problems.append(' %s:%d' % (f.LocalPath(), line_num))
453
454 if not problems:
455 return []
456 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
457 '\n'.join(problems))]
458
459
danakj61c1aa22015-10-26 19:55:52460def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
461 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
462 errors = []
463 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
464 input_api.re.MULTILINE)
465 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
466 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
467 continue
468 for lnum, line in f.ChangedContents():
469 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17470 errors.append(output_api.PresubmitError(
471 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
472 'DCHECK_IS_ON()", not forgetting the braces.')
473 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52474 return errors
475
476
mcasasb7440c282015-02-04 14:52:19477def _FindHistogramNameInLine(histogram_name, line):
478 """Tries to find a histogram name or prefix in a line."""
479 if not "affected-histogram" in line:
480 return histogram_name in line
481 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
482 # the histogram_name.
483 if not '"' in line:
484 return False
485 histogram_prefix = line.split('\"')[1]
486 return histogram_prefix in histogram_name
487
488
489def _CheckUmaHistogramChanges(input_api, output_api):
490 """Check that UMA histogram names in touched lines can still be found in other
491 lines of the patch or in histograms.xml. Note that this check would not catch
492 the reverse: changes in histograms.xml not matched in the code itself."""
493 touched_histograms = []
494 histograms_xml_modifications = []
495 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
496 for f in input_api.AffectedFiles():
497 # If histograms.xml itself is modified, keep the modified lines for later.
498 if f.LocalPath().endswith(('histograms.xml')):
499 histograms_xml_modifications = f.ChangedContents()
500 continue
501 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
502 continue
503 for line_num, line in f.ChangedContents():
504 found = pattern.search(line)
505 if found:
506 touched_histograms.append([found.group(1), f, line_num])
507
508 # Search for the touched histogram names in the local modifications to
509 # histograms.xml, and, if not found, on the base histograms.xml file.
510 unmatched_histograms = []
511 for histogram_info in touched_histograms:
512 histogram_name_found = False
513 for line_num, line in histograms_xml_modifications:
514 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
515 if histogram_name_found:
516 break
517 if not histogram_name_found:
518 unmatched_histograms.append(histogram_info)
519
eromanb90c82e7e32015-04-01 15:13:49520 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19521 problems = []
522 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49523 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19524 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45525 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19526 histogram_name_found = False
527 for line in histograms_xml:
528 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
529 if histogram_name_found:
530 break
531 if not histogram_name_found:
532 problems.append(' [%s:%d] %s' %
533 (f.LocalPath(), line_num, histogram_name))
534
535 if not problems:
536 return []
537 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
538 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49539 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19540
wnwenbdc444e2016-05-25 13:44:15541
yolandyandaabc6d2016-04-18 18:29:39542def _CheckFlakyTestUsage(input_api, output_api):
543 """Check that FlakyTest annotation is our own instead of the android one"""
544 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
545 files = []
546 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
547 if f.LocalPath().endswith('Test.java'):
548 if pattern.search(input_api.ReadFile(f)):
549 files.append(f)
550 if len(files):
551 return [output_api.PresubmitError(
552 'Use org.chromium.base.test.util.FlakyTest instead of '
553 'android.test.FlakyTest',
554 files)]
555 return []
mcasasb7440c282015-02-04 14:52:19556
wnwenbdc444e2016-05-25 13:44:15557
[email protected]8ea5d4b2011-09-13 21:49:22558def _CheckNoNewWStrings(input_api, output_api):
559 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27560 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22561 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20562 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57563 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34564 '/win/' in f.LocalPath() or
565 'chrome_elf' in f.LocalPath() or
566 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20567 continue
[email protected]8ea5d4b2011-09-13 21:49:22568
[email protected]a11dbe9b2012-08-07 01:32:58569 allowWString = False
[email protected]b5c24292011-11-28 14:38:20570 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58571 if 'presubmit: allow wstring' in line:
572 allowWString = True
573 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27574 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58575 allowWString = False
576 else:
577 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22578
[email protected]55463aa62011-10-12 00:48:27579 if not problems:
580 return []
581 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58582 ' If you are calling a cross-platform API that accepts a wstring, '
583 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27584 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22585
586
[email protected]2a8ac9c2011-10-19 17:20:44587def _CheckNoDEPSGIT(input_api, output_api):
588 """Make sure .DEPS.git is never modified manually."""
589 if any(f.LocalPath().endswith('.DEPS.git') for f in
590 input_api.AffectedFiles()):
591 return [output_api.PresubmitError(
592 'Never commit changes to .DEPS.git. This file is maintained by an\n'
593 'automated system based on what\'s in DEPS and your changes will be\n'
594 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34595 '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:44596 'for more information')]
597 return []
598
599
tandriief664692014-09-23 14:51:47600def _CheckValidHostsInDEPS(input_api, output_api):
601 """Checks that DEPS file deps are from allowed_hosts."""
602 # Run only if DEPS file has been modified to annoy fewer bystanders.
603 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
604 return []
605 # Outsource work to gclient verify
606 try:
607 input_api.subprocess.check_output(['gclient', 'verify'])
608 return []
609 except input_api.subprocess.CalledProcessError, error:
610 return [output_api.PresubmitError(
611 'DEPS file must have only git dependencies.',
612 long_text=error.output)]
613
614
[email protected]127f18ec2012-06-16 05:05:59615def _CheckNoBannedFunctions(input_api, output_api):
616 """Make sure that banned functions are not used."""
617 warnings = []
618 errors = []
619
wnwenbdc444e2016-05-25 13:44:15620 def IsBlacklisted(affected_file, blacklist):
621 local_path = affected_file.LocalPath()
622 for item in blacklist:
623 if input_api.re.match(item, local_path):
624 return True
625 return False
626
627 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
628 matched = False
629 if func_name[0:1] == '/':
630 regex = func_name[1:]
631 if input_api.re.search(regex, line):
632 matched = True
633 elif func_name in line:
dchenge07de812016-06-20 19:27:17634 matched = True
wnwenbdc444e2016-05-25 13:44:15635 if matched:
dchenge07de812016-06-20 19:27:17636 problems = warnings
wnwenbdc444e2016-05-25 13:44:15637 if error:
dchenge07de812016-06-20 19:27:17638 problems = errors
wnwenbdc444e2016-05-25 13:44:15639 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
640 for message_line in message:
641 problems.append(' %s' % message_line)
642
[email protected]127f18ec2012-06-16 05:05:59643 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
644 for f in input_api.AffectedFiles(file_filter=file_filter):
645 for line_num, line in f.ChangedContents():
646 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15647 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59648
649 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
650 for f in input_api.AffectedFiles(file_filter=file_filter):
651 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49652 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49653 if IsBlacklisted(f, excluded_paths):
654 continue
wnwenbdc444e2016-05-25 13:44:15655 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59656
657 result = []
658 if (warnings):
659 result.append(output_api.PresubmitPromptWarning(
660 'Banned functions were used.\n' + '\n'.join(warnings)))
661 if (errors):
662 result.append(output_api.PresubmitError(
663 'Banned functions were used.\n' + '\n'.join(errors)))
664 return result
665
666
[email protected]6c063c62012-07-11 19:11:06667def _CheckNoPragmaOnce(input_api, output_api):
668 """Make sure that banned functions are not used."""
669 files = []
670 pattern = input_api.re.compile(r'^#pragma\s+once',
671 input_api.re.MULTILINE)
672 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
673 if not f.LocalPath().endswith('.h'):
674 continue
675 contents = input_api.ReadFile(f)
676 if pattern.search(contents):
677 files.append(f)
678
679 if files:
680 return [output_api.PresubmitError(
681 'Do not use #pragma once in header files.\n'
682 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
683 files)]
684 return []
685
[email protected]127f18ec2012-06-16 05:05:59686
[email protected]e7479052012-09-19 00:26:12687def _CheckNoTrinaryTrueFalse(input_api, output_api):
688 """Checks to make sure we don't introduce use of foo ? true : false."""
689 problems = []
690 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
691 for f in input_api.AffectedFiles():
692 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
693 continue
694
695 for line_num, line in f.ChangedContents():
696 if pattern.match(line):
697 problems.append(' %s:%d' % (f.LocalPath(), line_num))
698
699 if not problems:
700 return []
701 return [output_api.PresubmitPromptWarning(
702 'Please consider avoiding the "? true : false" pattern if possible.\n' +
703 '\n'.join(problems))]
704
705
[email protected]55f9f382012-07-31 11:02:18706def _CheckUnwantedDependencies(input_api, output_api):
707 """Runs checkdeps on #include statements added in this
708 change. Breaking - rules is an error, breaking ! rules is a
709 warning.
710 """
mohan.reddyf21db962014-10-16 12:26:47711 import sys
[email protected]55f9f382012-07-31 11:02:18712 # We need to wait until we have an input_api object and use this
713 # roundabout construct to import checkdeps because this file is
714 # eval-ed and thus doesn't have __file__.
715 original_sys_path = sys.path
716 try:
717 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47718 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18719 import checkdeps
720 from cpp_checker import CppChecker
721 from rules import Rule
722 finally:
723 # Restore sys.path to what it was before.
724 sys.path = original_sys_path
725
726 added_includes = []
727 for f in input_api.AffectedFiles():
728 if not CppChecker.IsCppFile(f.LocalPath()):
729 continue
730
731 changed_lines = [line for line_num, line in f.ChangedContents()]
732 added_includes.append([f.LocalPath(), changed_lines])
733
[email protected]26385172013-05-09 23:11:35734 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18735
736 error_descriptions = []
737 warning_descriptions = []
738 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
739 added_includes):
740 description_with_path = '%s\n %s' % (path, rule_description)
741 if rule_type == Rule.DISALLOW:
742 error_descriptions.append(description_with_path)
743 else:
744 warning_descriptions.append(description_with_path)
745
746 results = []
747 if error_descriptions:
748 results.append(output_api.PresubmitError(
749 'You added one or more #includes that violate checkdeps rules.',
750 error_descriptions))
751 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42752 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18753 'You added one or more #includes of files that are temporarily\n'
754 'allowed but being removed. Can you avoid introducing the\n'
755 '#include? See relevant DEPS file(s) for details and contacts.',
756 warning_descriptions))
757 return results
758
759
[email protected]fbcafe5a2012-08-08 15:31:22760def _CheckFilePermissions(input_api, output_api):
761 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15762 if input_api.platform == 'win32':
763 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29764 checkperms_tool = input_api.os_path.join(
765 input_api.PresubmitLocalPath(),
766 'tools', 'checkperms', 'checkperms.py')
767 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47768 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22769 for f in input_api.AffectedFiles():
770 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11771 try:
772 input_api.subprocess.check_output(args)
773 return []
774 except input_api.subprocess.CalledProcessError as error:
775 return [output_api.PresubmitError(
776 'checkperms.py failed:',
777 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22778
779
[email protected]c8278b32012-10-30 20:35:49780def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
781 """Makes sure we don't include ui/aura/window_property.h
782 in header files.
783 """
784 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
785 errors = []
786 for f in input_api.AffectedFiles():
787 if not f.LocalPath().endswith('.h'):
788 continue
789 for line_num, line in f.ChangedContents():
790 if pattern.match(line):
791 errors.append(' %s:%d' % (f.LocalPath(), line_num))
792
793 results = []
794 if errors:
795 results.append(output_api.PresubmitError(
796 'Header files should not include ui/aura/window_property.h', errors))
797 return results
798
799
[email protected]cf9b78f2012-11-14 11:40:28800def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
801 """Checks that the lines in scope occur in the right order.
802
803 1. C system files in alphabetical order
804 2. C++ system files in alphabetical order
805 3. Project's .h files
806 """
807
808 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
809 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
810 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
811
812 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
813
814 state = C_SYSTEM_INCLUDES
815
816 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57817 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28818 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55819 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28820 for line_num, line in scope:
821 if c_system_include_pattern.match(line):
822 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55823 problem_linenums.append((line_num, previous_line_num,
824 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28825 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55826 problem_linenums.append((line_num, previous_line_num,
827 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28828 elif cpp_system_include_pattern.match(line):
829 if state == C_SYSTEM_INCLUDES:
830 state = CPP_SYSTEM_INCLUDES
831 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55832 problem_linenums.append((line_num, previous_line_num,
833 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28834 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55835 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28836 elif custom_include_pattern.match(line):
837 if state != CUSTOM_INCLUDES:
838 state = CUSTOM_INCLUDES
839 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55840 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28841 else:
brucedawson70fadb02015-06-30 17:47:55842 problem_linenums.append((line_num, previous_line_num,
843 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28844 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57845 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28846
847 warnings = []
brucedawson70fadb02015-06-30 17:47:55848 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57849 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55850 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28851 return warnings
852
853
[email protected]ac294a12012-12-06 16:38:43854def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28855 """Checks the #include order for the given file f."""
856
[email protected]2299dcf2012-11-15 19:56:24857 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30858 # Exclude the following includes from the check:
859 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
860 # specific order.
861 # 2) <atlbase.h>, "build/build_config.h"
862 excluded_include_pattern = input_api.re.compile(
863 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24864 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33865 # Match the final or penultimate token if it is xxxtest so we can ignore it
866 # when considering the special first include.
867 test_file_tag_pattern = input_api.re.compile(
868 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11869 if_pattern = input_api.re.compile(
870 r'\s*#\s*(if|elif|else|endif|define|undef).*')
871 # Some files need specialized order of includes; exclude such files from this
872 # check.
873 uncheckable_includes_pattern = input_api.re.compile(
874 r'\s*#include '
875 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28876
877 contents = f.NewContents()
878 warnings = []
879 line_num = 0
880
[email protected]ac294a12012-12-06 16:38:43881 # Handle the special first include. If the first include file is
882 # some/path/file.h, the corresponding including file can be some/path/file.cc,
883 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
884 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33885 # If the included file is some/path/file_platform.h the including file could
886 # also be some/path/file_xxxtest_platform.h.
887 including_file_base_name = test_file_tag_pattern.sub(
888 '', input_api.os_path.basename(f.LocalPath()))
889
[email protected]ac294a12012-12-06 16:38:43890 for line in contents:
891 line_num += 1
892 if system_include_pattern.match(line):
893 # No special first include -> process the line again along with normal
894 # includes.
895 line_num -= 1
896 break
897 match = custom_include_pattern.match(line)
898 if match:
899 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33900 header_basename = test_file_tag_pattern.sub(
901 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
902
903 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24904 # No special first include -> process the line again along with normal
905 # includes.
906 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43907 break
[email protected]cf9b78f2012-11-14 11:40:28908
909 # Split into scopes: Each region between #if and #endif is its own scope.
910 scopes = []
911 current_scope = []
912 for line in contents[line_num:]:
913 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11914 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54915 continue
[email protected]2309b0fa02012-11-16 12:18:27916 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28917 scopes.append(current_scope)
918 current_scope = []
[email protected]962f117e2012-11-22 18:11:56919 elif ((system_include_pattern.match(line) or
920 custom_include_pattern.match(line)) and
921 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28922 current_scope.append((line_num, line))
923 scopes.append(current_scope)
924
925 for scope in scopes:
926 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
927 changed_linenums))
928 return warnings
929
930
931def _CheckIncludeOrder(input_api, output_api):
932 """Checks that the #include order is correct.
933
934 1. The corresponding header for source files.
935 2. C system files in alphabetical order
936 3. C++ system files in alphabetical order
937 4. Project's .h files in alphabetical order
938
[email protected]ac294a12012-12-06 16:38:43939 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
940 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28941 """
[email protected]e120b012014-08-15 19:08:35942 def FileFilterIncludeOrder(affected_file):
943 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
944 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28945
946 warnings = []
[email protected]e120b012014-08-15 19:08:35947 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08948 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43949 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
950 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28951
952 results = []
953 if warnings:
[email protected]f7051d52013-04-02 18:31:42954 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53955 warnings))
[email protected]cf9b78f2012-11-14 11:40:28956 return results
957
958
[email protected]70ca77752012-11-20 03:45:03959def _CheckForVersionControlConflictsInFile(input_api, f):
960 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
961 errors = []
962 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23963 if f.LocalPath().endswith('.md'):
964 # First-level headers in markdown look a lot like version control
965 # conflict markers. http://daringfireball.net/projects/markdown/basics
966 continue
[email protected]70ca77752012-11-20 03:45:03967 if pattern.match(line):
968 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
969 return errors
970
971
972def _CheckForVersionControlConflicts(input_api, output_api):
973 """Usually this is not intentional and will cause a compile failure."""
974 errors = []
975 for f in input_api.AffectedFiles():
976 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
977
978 results = []
979 if errors:
980 results.append(output_api.PresubmitError(
981 'Version control conflict markers found, please resolve.', errors))
982 return results
983
984
[email protected]06e6d0ff2012-12-11 01:36:44985def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
986 def FilterFile(affected_file):
987 """Filter function for use with input_api.AffectedSourceFiles,
988 below. This filters out everything except non-test files from
989 top-level directories that generally speaking should not hard-code
990 service URLs (e.g. src/android_webview/, src/content/ and others).
991 """
992 return input_api.FilterSourceFile(
993 affected_file,
[email protected]78bb39d62012-12-11 15:11:56994 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44995 black_list=(_EXCLUDED_PATHS +
996 _TEST_CODE_EXCLUDED_PATHS +
997 input_api.DEFAULT_BLACK_LIST))
998
reillyi38965732015-11-16 18:27:33999 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
1000 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:461001 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
1002 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:441003 problems = [] # items are (filename, line_number, line)
1004 for f in input_api.AffectedSourceFiles(FilterFile):
1005 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:461006 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:441007 problems.append((f.LocalPath(), line_num, line))
1008
1009 if problems:
[email protected]f7051d52013-04-02 18:31:421010 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:441011 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:581012 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:441013 [' %s:%d: %s' % (
1014 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:031015 else:
1016 return []
[email protected]06e6d0ff2012-12-11 01:36:441017
1018
[email protected]d2530012013-01-25 16:39:271019def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1020 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311021 The native_client_sdk directory is excluded because it has auto-generated PNG
1022 files for documentation.
[email protected]d2530012013-01-25 16:39:271023 """
[email protected]d2530012013-01-25 16:39:271024 errors = []
binji0dcdf342014-12-12 18:32:311025 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1026 black_list = (r'^native_client_sdk[\\\/]',)
1027 file_filter = lambda f: input_api.FilterSourceFile(
1028 f, white_list=white_list, black_list=black_list)
1029 for f in input_api.AffectedFiles(include_deletes=False,
1030 file_filter=file_filter):
1031 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271032
1033 results = []
1034 if errors:
1035 results.append(output_api.PresubmitError(
1036 'The name of PNG files should not have abbreviations. \n'
1037 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1038 'Contact [email protected] if you have questions.', errors))
1039 return results
1040
1041
[email protected]14a6131c2014-01-08 01:15:411042def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081043 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411044 a set of DEPS entries that we should look up.
1045
1046 For a directory (rather than a specific filename) we fake a path to
1047 a specific filename by adding /DEPS. This is chosen as a file that
1048 will seldom or never be subject to per-file include_rules.
1049 """
[email protected]2b438d62013-11-14 17:54:141050 # We ignore deps entries on auto-generated directories.
1051 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081052
1053 # This pattern grabs the path without basename in the first
1054 # parentheses, and the basename (if present) in the second. It
1055 # relies on the simple heuristic that if there is a basename it will
1056 # be a header file ending in ".h".
1057 pattern = re.compile(
1058 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141059 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081060 for changed_line in changed_lines:
1061 m = pattern.match(changed_line)
1062 if m:
1063 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141064 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411065 if m.group(2):
1066 results.add('%s%s' % (path, m.group(2)))
1067 else:
1068 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081069 return results
1070
1071
[email protected]e871964c2013-05-13 14:14:551072def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1073 """When a dependency prefixed with + is added to a DEPS file, we
1074 want to make sure that the change is reviewed by an OWNER of the
1075 target file or directory, to avoid layering violations from being
1076 introduced. This check verifies that this happens.
1077 """
1078 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241079
1080 file_filter = lambda f: not input_api.re.match(
1081 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1082 for f in input_api.AffectedFiles(include_deletes=False,
1083 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551084 filename = input_api.os_path.basename(f.LocalPath())
1085 if filename == 'DEPS':
1086 changed_lines |= set(line.strip()
1087 for line_num, line
1088 in f.ChangedContents())
1089 if not changed_lines:
1090 return []
1091
[email protected]14a6131c2014-01-08 01:15:411092 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1093 changed_lines)
[email protected]e871964c2013-05-13 14:14:551094 if not virtual_depended_on_files:
1095 return []
1096
1097 if input_api.is_committing:
1098 if input_api.tbr:
1099 return [output_api.PresubmitNotifyResult(
1100 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271101 if input_api.dry_run:
1102 return [output_api.PresubmitNotifyResult(
1103 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551104 if not input_api.change.issue:
1105 return [output_api.PresubmitError(
1106 "DEPS approval by OWNERS check failed: this change has "
1107 "no Rietveld issue number, so we can't check it for approvals.")]
1108 output = output_api.PresubmitError
1109 else:
1110 output = output_api.PresubmitNotifyResult
1111
1112 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501113 owner_email, reviewers = (
1114 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1115 input_api,
1116 owners_db.email_regexp,
1117 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551118
1119 owner_email = owner_email or input_api.change.author_email
1120
[email protected]de4f7d22013-05-23 14:27:461121 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511122 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461123 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551124 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1125 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411126
1127 # We strip the /DEPS part that was added by
1128 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1129 # directory.
1130 def StripDeps(path):
1131 start_deps = path.rfind('/DEPS')
1132 if start_deps != -1:
1133 return path[:start_deps]
1134 else:
1135 return path
1136 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551137 for path in missing_files]
1138
1139 if unapproved_dependencies:
1140 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151141 output('You need LGTM from owners of depends-on paths in DEPS that were '
1142 'modified in this CL:\n %s' %
1143 '\n '.join(sorted(unapproved_dependencies)))]
1144 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1145 output_list.append(output(
1146 'Suggested missing target path OWNERS:\n %s' %
1147 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551148 return output_list
1149
1150 return []
1151
1152
[email protected]85218562013-11-22 07:41:401153def _CheckSpamLogging(input_api, output_api):
1154 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1155 black_list = (_EXCLUDED_PATHS +
1156 _TEST_CODE_EXCLUDED_PATHS +
1157 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501158 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191159 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481160 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461161 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121162 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1163 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581164 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161165 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031166 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151167 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1168 r"^chromecast[\\\/]",
1169 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311170 r"^components[\\\/]html_viewer[\\\/]"
1171 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461172 # TODO(peter): Remove this exception. https://crbug.com/534537
1173 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1174 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251175 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1176 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241177 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111178 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151179 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111180 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521181 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501182 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361183 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311184 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131185 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441186 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451187 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021188 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441189 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401190 source_file_filter = lambda x: input_api.FilterSourceFile(
1191 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1192
1193 log_info = []
1194 printf = []
1195
1196 for f in input_api.AffectedSourceFiles(source_file_filter):
1197 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471198 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401199 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471200 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131201 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371202
mohan.reddyf21db962014-10-16 12:26:471203 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371204 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471205 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401206 printf.append(f.LocalPath())
1207
1208 if log_info:
1209 return [output_api.PresubmitError(
1210 'These files spam the console log with LOG(INFO):',
1211 items=log_info)]
1212 if printf:
1213 return [output_api.PresubmitError(
1214 'These files spam the console log with printf/fprintf:',
1215 items=printf)]
1216 return []
1217
1218
[email protected]49aa76a2013-12-04 06:59:161219def _CheckForAnonymousVariables(input_api, output_api):
1220 """These types are all expected to hold locks while in scope and
1221 so should never be anonymous (which causes them to be immediately
1222 destroyed)."""
1223 they_who_must_be_named = [
1224 'base::AutoLock',
1225 'base::AutoReset',
1226 'base::AutoUnlock',
1227 'SkAutoAlphaRestore',
1228 'SkAutoBitmapShaderInstall',
1229 'SkAutoBlitterChoose',
1230 'SkAutoBounderCommit',
1231 'SkAutoCallProc',
1232 'SkAutoCanvasRestore',
1233 'SkAutoCommentBlock',
1234 'SkAutoDescriptor',
1235 'SkAutoDisableDirectionCheck',
1236 'SkAutoDisableOvalCheck',
1237 'SkAutoFree',
1238 'SkAutoGlyphCache',
1239 'SkAutoHDC',
1240 'SkAutoLockColors',
1241 'SkAutoLockPixels',
1242 'SkAutoMalloc',
1243 'SkAutoMaskFreeImage',
1244 'SkAutoMutexAcquire',
1245 'SkAutoPathBoundsUpdate',
1246 'SkAutoPDFRelease',
1247 'SkAutoRasterClipValidate',
1248 'SkAutoRef',
1249 'SkAutoTime',
1250 'SkAutoTrace',
1251 'SkAutoUnref',
1252 ]
1253 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1254 # bad: base::AutoLock(lock.get());
1255 # not bad: base::AutoLock lock(lock.get());
1256 bad_pattern = input_api.re.compile(anonymous)
1257 # good: new base::AutoLock(lock.get())
1258 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1259 errors = []
1260
1261 for f in input_api.AffectedFiles():
1262 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1263 continue
1264 for linenum, line in f.ChangedContents():
1265 if bad_pattern.search(line) and not good_pattern.search(line):
1266 errors.append('%s:%d' % (f.LocalPath(), linenum))
1267
1268 if errors:
1269 return [output_api.PresubmitError(
1270 'These lines create anonymous variables that need to be named:',
1271 items=errors)]
1272 return []
1273
1274
[email protected]5fe0f8742013-11-29 01:04:591275def _CheckCygwinShell(input_api, output_api):
1276 source_file_filter = lambda x: input_api.FilterSourceFile(
1277 x, white_list=(r'.+\.(gyp|gypi)$',))
1278 cygwin_shell = []
1279
1280 for f in input_api.AffectedSourceFiles(source_file_filter):
1281 for linenum, line in f.ChangedContents():
1282 if 'msvs_cygwin_shell' in line:
1283 cygwin_shell.append(f.LocalPath())
1284 break
1285
1286 if cygwin_shell:
1287 return [output_api.PresubmitError(
1288 'These files should not use msvs_cygwin_shell (the default is 0):',
1289 items=cygwin_shell)]
1290 return []
1291
[email protected]85218562013-11-22 07:41:401292
[email protected]999261d2014-03-03 20:08:081293def _CheckUserActionUpdate(input_api, output_api):
1294 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521295 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081296 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521297 # If actions.xml is already included in the changelist, the PRESUBMIT
1298 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081299 return []
1300
[email protected]999261d2014-03-03 20:08:081301 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1302 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521303 current_actions = None
[email protected]999261d2014-03-03 20:08:081304 for f in input_api.AffectedFiles(file_filter=file_filter):
1305 for line_num, line in f.ChangedContents():
1306 match = input_api.re.search(action_re, line)
1307 if match:
[email protected]2f92dec2014-03-07 19:21:521308 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1309 # loaded only once.
1310 if not current_actions:
1311 with open('tools/metrics/actions/actions.xml') as actions_f:
1312 current_actions = actions_f.read()
1313 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081314 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521315 action = 'name="{0}"'.format(action_name)
1316 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081317 return [output_api.PresubmitPromptWarning(
1318 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521319 'tools/metrics/actions/actions.xml. Please run '
1320 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081321 % (f.LocalPath(), line_num, action_name))]
1322 return []
1323
1324
[email protected]99171a92014-06-03 08:44:471325def _GetJSONParseError(input_api, filename, eat_comments=True):
1326 try:
1327 contents = input_api.ReadFile(filename)
1328 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131329 import sys
1330 original_sys_path = sys.path
1331 try:
1332 sys.path = sys.path + [input_api.os_path.join(
1333 input_api.PresubmitLocalPath(),
1334 'tools', 'json_comment_eater')]
1335 import json_comment_eater
1336 finally:
1337 sys.path = original_sys_path
1338 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471339
1340 input_api.json.loads(contents)
1341 except ValueError as e:
1342 return e
1343 return None
1344
1345
1346def _GetIDLParseError(input_api, filename):
1347 try:
1348 contents = input_api.ReadFile(filename)
1349 idl_schema = input_api.os_path.join(
1350 input_api.PresubmitLocalPath(),
1351 'tools', 'json_schema_compiler', 'idl_schema.py')
1352 process = input_api.subprocess.Popen(
1353 [input_api.python_executable, idl_schema],
1354 stdin=input_api.subprocess.PIPE,
1355 stdout=input_api.subprocess.PIPE,
1356 stderr=input_api.subprocess.PIPE,
1357 universal_newlines=True)
1358 (_, error) = process.communicate(input=contents)
1359 return error or None
1360 except ValueError as e:
1361 return e
1362
1363
1364def _CheckParseErrors(input_api, output_api):
1365 """Check that IDL and JSON files do not contain syntax errors."""
1366 actions = {
1367 '.idl': _GetIDLParseError,
1368 '.json': _GetJSONParseError,
1369 }
1370 # These paths contain test data and other known invalid JSON files.
1371 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491372 r'test[\\\/]data[\\\/]',
1373 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471374 ]
1375 # Most JSON files are preprocessed and support comments, but these do not.
1376 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491377 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471378 ]
1379 # Only run IDL checker on files in these directories.
1380 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491381 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1382 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471383 ]
1384
1385 def get_action(affected_file):
1386 filename = affected_file.LocalPath()
1387 return actions.get(input_api.os_path.splitext(filename)[1])
1388
1389 def MatchesFile(patterns, path):
1390 for pattern in patterns:
1391 if input_api.re.search(pattern, path):
1392 return True
1393 return False
1394
1395 def FilterFile(affected_file):
1396 action = get_action(affected_file)
1397 if not action:
1398 return False
1399 path = affected_file.LocalPath()
1400
1401 if MatchesFile(excluded_patterns, path):
1402 return False
1403
1404 if (action == _GetIDLParseError and
1405 not MatchesFile(idl_included_patterns, path)):
1406 return False
1407 return True
1408
1409 results = []
1410 for affected_file in input_api.AffectedFiles(
1411 file_filter=FilterFile, include_deletes=False):
1412 action = get_action(affected_file)
1413 kwargs = {}
1414 if (action == _GetJSONParseError and
1415 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1416 kwargs['eat_comments'] = False
1417 parse_error = action(input_api,
1418 affected_file.AbsoluteLocalPath(),
1419 **kwargs)
1420 if parse_error:
1421 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1422 (affected_file.LocalPath(), parse_error)))
1423 return results
1424
1425
[email protected]760deea2013-12-10 19:33:491426def _CheckJavaStyle(input_api, output_api):
1427 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471428 import sys
[email protected]760deea2013-12-10 19:33:491429 original_sys_path = sys.path
1430 try:
1431 sys.path = sys.path + [input_api.os_path.join(
1432 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1433 import checkstyle
1434 finally:
1435 # Restore sys.path to what it was before.
1436 sys.path = original_sys_path
1437
1438 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091439 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511440 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491441
1442
dchenge07de812016-06-20 19:27:171443def _CheckIpcOwners(input_api, output_api):
1444 """Checks that affected files involving IPC have an IPC OWNERS rule.
1445
1446 Whether or not a file affects IPC is determined by a simple whitelist of
1447 filename patterns."""
1448 file_patterns = [
1449 '*_messages.cc',
1450 '*_messages*.h',
1451 '*_param_traits*.*',
1452 '*.mojom',
1453 '*_struct_traits*.*',
1454 '*_type_converter*.*',
1455 # Blink uses a different file naming convention
1456 '*StructTraits*.*',
1457 '*TypeConverter*.*',
1458 ]
1459
scottmg7a6ed5ba2016-11-04 18:22:041460 # These third_party directories do not contain IPCs, but contain files
1461 # matching the above patterns, which trigger false positives.
1462 exclude_paths = [
1463 'third_party/crashpad/*',
1464 ]
1465
dchenge07de812016-06-20 19:27:171466 # Dictionary mapping an OWNERS file path to Patterns.
1467 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1468 # rules ) to a PatternEntry.
1469 # PatternEntry is a dictionary with two keys:
1470 # - 'files': the files that are matched by this pattern
1471 # - 'rules': the per-file rules needed for this pattern
1472 # For example, if we expect OWNERS file to contain rules for *.mojom and
1473 # *_struct_traits*.*, Patterns might look like this:
1474 # {
1475 # '*.mojom': {
1476 # 'files': ...,
1477 # 'rules': [
1478 # 'per-file *.mojom=set noparent',
1479 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1480 # ],
1481 # },
1482 # '*_struct_traits*.*': {
1483 # 'files': ...,
1484 # 'rules': [
1485 # 'per-file *_struct_traits*.*=set noparent',
1486 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1487 # ],
1488 # },
1489 # }
1490 to_check = {}
1491
1492 # Iterate through the affected files to see what we actually need to check
1493 # for. We should only nag patch authors about per-file rules if a file in that
1494 # directory would match that pattern. If a directory only contains *.mojom
1495 # files and no *_messages*.h files, we should only nag about rules for
1496 # *.mojom files.
rockot51249332016-06-23 16:32:251497 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171498 for pattern in file_patterns:
1499 if input_api.fnmatch.fnmatch(
1500 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041501 skip = False
1502 for exclude in exclude_paths:
1503 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1504 skip = True
1505 break
1506 if skip:
1507 continue
dchenge07de812016-06-20 19:27:171508 owners_file = input_api.os_path.join(
1509 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1510 if owners_file not in to_check:
1511 to_check[owners_file] = {}
1512 if pattern not in to_check[owners_file]:
1513 to_check[owners_file][pattern] = {
1514 'files': [],
1515 'rules': [
1516 'per-file %s=set noparent' % pattern,
1517 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1518 ]
1519 }
1520 to_check[owners_file][pattern]['files'].append(f)
1521 break
1522
1523 # Now go through the OWNERS files we collected, filtering out rules that are
1524 # already present in that OWNERS file.
1525 for owners_file, patterns in to_check.iteritems():
1526 try:
1527 with file(owners_file) as f:
1528 lines = set(f.read().splitlines())
1529 for entry in patterns.itervalues():
1530 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1531 ]
1532 except IOError:
1533 # No OWNERS file, so all the rules are definitely missing.
1534 continue
1535
1536 # All the remaining lines weren't found in OWNERS files, so emit an error.
1537 errors = []
1538 for owners_file, patterns in to_check.iteritems():
1539 missing_lines = []
1540 files = []
1541 for pattern, entry in patterns.iteritems():
1542 missing_lines.extend(entry['rules'])
1543 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1544 if missing_lines:
1545 errors.append(
1546 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1547 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1548
1549 results = []
1550 if errors:
vabrf5ce3bf92016-07-11 14:52:411551 if input_api.is_committing:
1552 output = output_api.PresubmitError
1553 else:
1554 output = output_api.PresubmitPromptWarning
1555 results.append(output(
dchenge07de812016-06-20 19:27:171556 'Found changes to IPC files without a security OWNER!',
1557 long_text='\n\n'.join(errors)))
1558
1559 return results
1560
1561
yzshend99f726a2016-07-25 21:44:231562def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1563 """Checks to make sure that all newly added mojom targets map array/map/string
1564 to STL (for chromium) or WTF (for blink) types.
1565 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1566 """
1567 files = []
1568 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1569 input_api.re.MULTILINE)
1570
1571 for f in input_api.AffectedFiles():
1572 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1573 continue
1574
1575 for _, line in f.ChangedContents():
1576 if pattern.search(line):
1577 files.append(f)
1578 break
1579
1580 if len(files):
1581 return [output_api.PresubmitError(
1582 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1583 'false. The mode is deprecated and will be removed soon.',
1584 files)]
1585 return []
1586
1587
jbriance9e12f162016-11-25 07:57:501588def _CheckUselessForwardDeclarations(input_api, output_api):
1589 """Checks that added or removed lines in affected header files
1590 do not lead to new useless class or struct forward declaration.
1591 """
1592 results = []
1593 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1594 input_api.re.MULTILINE)
1595 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1596 input_api.re.MULTILINE)
1597 for f in input_api.AffectedFiles(include_deletes=False):
1598 if not f.LocalPath().endswith('.h'):
1599 continue
1600
1601 contents = input_api.ReadFile(f)
1602 fwd_decls = input_api.re.findall(class_pattern, contents)
1603 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1604
1605 useless_fwd_decls = []
1606 for decl in fwd_decls:
1607 count = sum(1 for _ in input_api.re.finditer(
1608 r'\b%s\b' % input_api.re.escape(decl), contents))
1609 if count == 1:
1610 useless_fwd_decls.append(decl)
1611
1612 if not useless_fwd_decls:
1613 continue
1614
1615 for line in f.GenerateScmDiff().splitlines():
1616 if (line.startswith('-') and not line.startswith('--') or
1617 line.startswith('+') and not line.startswith('++')):
1618 for decl in useless_fwd_decls:
1619 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1620 results.append(output_api.PresubmitPromptWarning(
1621 '%s: %s forward declaration is becoming useless' %
1622 (f.LocalPath(), decl)))
1623 useless_fwd_decls.remove(decl)
1624
1625 return results
1626
1627
dskiba88634f4e2015-08-14 23:03:291628def _CheckAndroidToastUsage(input_api, output_api):
1629 """Checks that code uses org.chromium.ui.widget.Toast instead of
1630 android.widget.Toast (Chromium Toast doesn't force hardware
1631 acceleration on low-end devices, saving memory).
1632 """
1633 toast_import_pattern = input_api.re.compile(
1634 r'^import android\.widget\.Toast;$')
1635
1636 errors = []
1637
1638 sources = lambda affected_file: input_api.FilterSourceFile(
1639 affected_file,
1640 black_list=(_EXCLUDED_PATHS +
1641 _TEST_CODE_EXCLUDED_PATHS +
1642 input_api.DEFAULT_BLACK_LIST +
1643 (r'^chromecast[\\\/].*',
1644 r'^remoting[\\\/].*')),
1645 white_list=(r'.*\.java$',))
1646
1647 for f in input_api.AffectedSourceFiles(sources):
1648 for line_num, line in f.ChangedContents():
1649 if toast_import_pattern.search(line):
1650 errors.append("%s:%d" % (f.LocalPath(), line_num))
1651
1652 results = []
1653
1654 if errors:
1655 results.append(output_api.PresubmitError(
1656 'android.widget.Toast usage is detected. Android toasts use hardware'
1657 ' acceleration, and can be\ncostly on low-end devices. Please use'
1658 ' org.chromium.ui.widget.Toast instead.\n'
1659 'Contact [email protected] if you have any questions.',
1660 errors))
1661
1662 return results
1663
1664
dgnaa68d5e2015-06-10 10:08:221665def _CheckAndroidCrLogUsage(input_api, output_api):
1666 """Checks that new logs using org.chromium.base.Log:
1667 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511668 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221669 """
pkotwicza1dd0b002016-05-16 14:41:041670
1671 # Do not check format of logs in //chrome/android/webapk because
1672 # //chrome/android/webapk cannot depend on //base
1673 cr_log_check_excluded_paths = [
1674 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1675 ]
1676
dgnaa68d5e2015-06-10 10:08:221677 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121678 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1679 class_in_base_pattern = input_api.re.compile(
1680 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1681 has_some_log_import_pattern = input_api.re.compile(
1682 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221683 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121684 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221685 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511686 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221687 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221688
Vincent Scheib16d7b272015-09-15 18:09:071689 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221690 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041691 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1692 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121693
dgnaa68d5e2015-06-10 10:08:221694 tag_decl_errors = []
1695 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121696 tag_errors = []
dgn38736db2015-09-18 19:20:511697 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121698 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221699
1700 for f in input_api.AffectedSourceFiles(sources):
1701 file_content = input_api.ReadFile(f)
1702 has_modified_logs = False
1703
1704 # Per line checks
dgn87d9fb62015-06-12 09:15:121705 if (cr_log_import_pattern.search(file_content) or
1706 (class_in_base_pattern.search(file_content) and
1707 not has_some_log_import_pattern.search(file_content))):
1708 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221709 for line_num, line in f.ChangedContents():
1710
1711 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121712 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221713 if match:
1714 has_modified_logs = True
1715
1716 # Make sure it uses "TAG"
1717 if not match.group('tag') == 'TAG':
1718 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121719 else:
1720 # Report non cr Log function calls in changed lines
1721 for line_num, line in f.ChangedContents():
1722 if log_call_pattern.search(line):
1723 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221724
1725 # Per file checks
1726 if has_modified_logs:
1727 # Make sure the tag is using the "cr" prefix and is not too long
1728 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511729 tag_name = match.group('name') if match else None
1730 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221731 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511732 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221733 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511734 elif '.' in tag_name:
1735 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221736
1737 results = []
1738 if tag_decl_errors:
1739 results.append(output_api.PresubmitPromptWarning(
1740 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511741 '"private static final String TAG = "<package tag>".\n'
1742 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221743 tag_decl_errors))
1744
1745 if tag_length_errors:
1746 results.append(output_api.PresubmitError(
1747 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511748 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221749 tag_length_errors))
1750
1751 if tag_errors:
1752 results.append(output_api.PresubmitPromptWarning(
1753 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1754 tag_errors))
1755
dgn87d9fb62015-06-12 09:15:121756 if util_log_errors:
dgn4401aa52015-04-29 16:26:171757 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121758 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1759 util_log_errors))
1760
dgn38736db2015-09-18 19:20:511761 if tag_with_dot_errors:
1762 results.append(output_api.PresubmitPromptWarning(
1763 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1764 tag_with_dot_errors))
1765
dgn4401aa52015-04-29 16:26:171766 return results
1767
1768
agrieve7b6479d82015-10-07 14:24:221769def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1770 """Checks if MDPI assets are placed in a correct directory."""
1771 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1772 ('/res/drawable/' in f.LocalPath() or
1773 '/res/drawable-ldrtl/' in f.LocalPath()))
1774 errors = []
1775 for f in input_api.AffectedFiles(include_deletes=False,
1776 file_filter=file_filter):
1777 errors.append(' %s' % f.LocalPath())
1778
1779 results = []
1780 if errors:
1781 results.append(output_api.PresubmitError(
1782 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1783 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1784 '/res/drawable-ldrtl/.\n'
1785 'Contact [email protected] if you have questions.', errors))
1786 return results
1787
1788
agrievef32bcc72016-04-04 14:57:401789class PydepsChecker(object):
1790 def __init__(self, input_api, pydeps_files):
1791 self._file_cache = {}
1792 self._input_api = input_api
1793 self._pydeps_files = pydeps_files
1794
1795 def _LoadFile(self, path):
1796 """Returns the list of paths within a .pydeps file relative to //."""
1797 if path not in self._file_cache:
1798 with open(path) as f:
1799 self._file_cache[path] = f.read()
1800 return self._file_cache[path]
1801
1802 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1803 """Returns an interable of paths within the .pydep, relativized to //."""
1804 os_path = self._input_api.os_path
1805 pydeps_dir = os_path.dirname(pydeps_path)
1806 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1807 if not l.startswith('*'))
1808 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1809
1810 def _CreateFilesToPydepsMap(self):
1811 """Returns a map of local_path -> list_of_pydeps."""
1812 ret = {}
1813 for pydep_local_path in self._pydeps_files:
1814 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1815 ret.setdefault(path, []).append(pydep_local_path)
1816 return ret
1817
1818 def ComputeAffectedPydeps(self):
1819 """Returns an iterable of .pydeps files that might need regenerating."""
1820 affected_pydeps = set()
1821 file_to_pydeps_map = None
1822 for f in self._input_api.AffectedFiles(include_deletes=True):
1823 local_path = f.LocalPath()
1824 if local_path == 'DEPS':
1825 return self._pydeps_files
1826 elif local_path.endswith('.pydeps'):
1827 if local_path in self._pydeps_files:
1828 affected_pydeps.add(local_path)
1829 elif local_path.endswith('.py'):
1830 if file_to_pydeps_map is None:
1831 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1832 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1833 return affected_pydeps
1834
1835 def DetermineIfStale(self, pydeps_path):
1836 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411837 import difflib
agrievef32bcc72016-04-04 14:57:401838 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1839 cmd = old_pydeps_data[1][1:].strip()
1840 new_pydeps_data = self._input_api.subprocess.check_output(
1841 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411842 old_contents = old_pydeps_data[2:]
1843 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401844 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411845 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401846
1847
1848def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1849 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001850 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281851 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1852 # Mac, so skip it on other platforms.
1853 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001854 return []
agrievef32bcc72016-04-04 14:57:401855 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1856 is_android = input_api.os_path.exists('third_party/android_tools')
1857 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1858 results = []
1859 # First, check for new / deleted .pydeps.
1860 for f in input_api.AffectedFiles(include_deletes=True):
1861 if f.LocalPath().endswith('.pydeps'):
1862 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1863 results.append(output_api.PresubmitError(
1864 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1865 'remove %s' % f.LocalPath()))
1866 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1867 results.append(output_api.PresubmitError(
1868 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1869 'include %s' % f.LocalPath()))
1870
1871 if results:
1872 return results
1873
1874 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1875
1876 for pydep_path in checker.ComputeAffectedPydeps():
1877 try:
phajdan.jr0d9878552016-11-04 10:49:411878 result = checker.DetermineIfStale(pydep_path)
1879 if result:
1880 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401881 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411882 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1883 'To regenerate, run:\n\n %s' %
1884 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401885 except input_api.subprocess.CalledProcessError as error:
1886 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1887 long_text=error.output)]
1888
1889 return results
1890
1891
glidere61efad2015-02-18 17:39:431892def _CheckSingletonInHeaders(input_api, output_api):
1893 """Checks to make sure no header files have |Singleton<|."""
1894 def FileFilter(affected_file):
1895 # It's ok for base/memory/singleton.h to have |Singleton<|.
1896 black_list = (_EXCLUDED_PATHS +
1897 input_api.DEFAULT_BLACK_LIST +
1898 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1899 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1900
sergeyu34d21222015-09-16 00:11:441901 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431902 files = []
1903 for f in input_api.AffectedSourceFiles(FileFilter):
1904 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1905 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1906 contents = input_api.ReadFile(f)
1907 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241908 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431909 pattern.search(line)):
1910 files.append(f)
1911 break
1912
1913 if files:
yolandyandaabc6d2016-04-18 18:29:391914 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441915 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431916 'Please move them to an appropriate source file so that the ' +
1917 'template gets instantiated in a single compilation unit.',
1918 files) ]
1919 return []
1920
1921
dbeam37e8e7402016-02-10 22:58:201922def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1923 """Checks for old style compiled_resources.gyp files."""
1924 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1925
1926 added_compiled_resources = filter(is_compiled_resource, [
1927 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1928 ])
1929
1930 if not added_compiled_resources:
1931 return []
1932
1933 return [output_api.PresubmitError(
1934 "Found new compiled_resources.gyp files:\n%s\n\n"
1935 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551936 "please use compiled_resources2.gyp instead:\n"
1937 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1938 %
dbeam37e8e7402016-02-10 22:58:201939 "\n".join(added_compiled_resources))]
1940
1941
[email protected]fd20b902014-05-09 02:14:531942_DEPRECATED_CSS = [
1943 # Values
1944 ( "-webkit-box", "flex" ),
1945 ( "-webkit-inline-box", "inline-flex" ),
1946 ( "-webkit-flex", "flex" ),
1947 ( "-webkit-inline-flex", "inline-flex" ),
1948 ( "-webkit-min-content", "min-content" ),
1949 ( "-webkit-max-content", "max-content" ),
1950
1951 # Properties
1952 ( "-webkit-background-clip", "background-clip" ),
1953 ( "-webkit-background-origin", "background-origin" ),
1954 ( "-webkit-background-size", "background-size" ),
1955 ( "-webkit-box-shadow", "box-shadow" ),
1956
1957 # Functions
1958 ( "-webkit-gradient", "gradient" ),
1959 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1960 ( "-webkit-linear-gradient", "linear-gradient" ),
1961 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1962 ( "-webkit-radial-gradient", "radial-gradient" ),
1963 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1964]
1965
1966def _CheckNoDeprecatedCSS(input_api, output_api):
1967 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251968 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341969 documentation and iOS CSS for dom distiller
1970 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251971 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531972 results = []
dbeam070cfe62014-10-22 06:44:021973 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251974 black_list = (_EXCLUDED_PATHS +
1975 _TEST_CODE_EXCLUDED_PATHS +
1976 input_api.DEFAULT_BLACK_LIST +
1977 (r"^chrome/common/extensions/docs",
1978 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341979 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051980 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441981 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251982 r"^native_client_sdk"))
1983 file_filter = lambda f: input_api.FilterSourceFile(
1984 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531985 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1986 for line_num, line in fpath.ChangedContents():
1987 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021988 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531989 results.append(output_api.PresubmitError(
1990 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1991 (fpath.LocalPath(), line_num, deprecated_value, value)))
1992 return results
1993
mohan.reddyf21db962014-10-16 12:26:471994
dbeam070cfe62014-10-22 06:44:021995_DEPRECATED_JS = [
1996 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1997 ( "__defineGetter__", "Object.defineProperty" ),
1998 ( "__defineSetter__", "Object.defineProperty" ),
1999]
2000
2001def _CheckNoDeprecatedJS(input_api, output_api):
2002 """Make sure that we don't use deprecated JS in Chrome code."""
2003 results = []
2004 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2005 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2006 input_api.DEFAULT_BLACK_LIST)
2007 file_filter = lambda f: input_api.FilterSourceFile(
2008 f, white_list=file_inclusion_pattern, black_list=black_list)
2009 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2010 for lnum, line in fpath.ChangedContents():
2011 for (deprecated, replacement) in _DEPRECATED_JS:
2012 if deprecated in line:
2013 results.append(output_api.PresubmitError(
2014 "%s:%d: Use of deprecated JS %s, use %s instead" %
2015 (fpath.LocalPath(), lnum, deprecated, replacement)))
2016 return results
2017
2018
dgnaa68d5e2015-06-10 10:08:222019def _AndroidSpecificOnUploadChecks(input_api, output_api):
2020 """Groups checks that target android code."""
2021 results = []
dgnaa68d5e2015-06-10 10:08:222022 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222023 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292024 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222025 return results
2026
2027
[email protected]22c9bd72011-03-27 16:47:392028def _CommonChecks(input_api, output_api):
2029 """Checks common to both upload and commit."""
2030 results = []
2031 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382032 input_api, output_api,
2033 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
machenbachfbda9b72016-12-06 13:13:582034 results.extend(
2035 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192036 results.extend(
[email protected]760deea2013-12-10 19:33:492037 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542038 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182039 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522040 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222041 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442042 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592043 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062044 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122045 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182046 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222047 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492048 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272049 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032050 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492051 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442052 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272053 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542054 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442055 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392056 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552057 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042058 results.extend(
2059 input_api.canned_checks.CheckChangeHasNoTabs(
2060 input_api,
2061 output_api,
2062 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402063 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162064 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592065 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082066 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:532067 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:022068 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472069 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042070 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232071 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432072 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:202073 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402074 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152075 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172076 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232077 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502078 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242079
2080 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2081 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2082 input_api, output_api,
2083 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382084 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392085 return results
[email protected]1f7b4172010-01-28 01:17:342086
[email protected]b337cb5b2011-01-23 21:24:052087
[email protected]b8079ae4a2012-12-05 19:56:492088def _CheckPatchFiles(input_api, output_api):
2089 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2090 if f.LocalPath().endswith(('.orig', '.rej'))]
2091 if problems:
2092 return [output_api.PresubmitError(
2093 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032094 else:
2095 return []
[email protected]b8079ae4a2012-12-05 19:56:492096
2097
[email protected]b00342e7f2013-03-26 16:21:542098def _DidYouMeanOSMacro(bad_macro):
2099 try:
2100 return {'A': 'OS_ANDROID',
2101 'B': 'OS_BSD',
2102 'C': 'OS_CHROMEOS',
2103 'F': 'OS_FREEBSD',
2104 'L': 'OS_LINUX',
2105 'M': 'OS_MACOSX',
2106 'N': 'OS_NACL',
2107 'O': 'OS_OPENBSD',
2108 'P': 'OS_POSIX',
2109 'S': 'OS_SOLARIS',
2110 'W': 'OS_WIN'}[bad_macro[3].upper()]
2111 except KeyError:
2112 return ''
2113
2114
2115def _CheckForInvalidOSMacrosInFile(input_api, f):
2116 """Check for sensible looking, totally invalid OS macros."""
2117 preprocessor_statement = input_api.re.compile(r'^\s*#')
2118 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2119 results = []
2120 for lnum, line in f.ChangedContents():
2121 if preprocessor_statement.search(line):
2122 for match in os_macro.finditer(line):
2123 if not match.group(1) in _VALID_OS_MACROS:
2124 good = _DidYouMeanOSMacro(match.group(1))
2125 did_you_mean = ' (did you mean %s?)' % good if good else ''
2126 results.append(' %s:%d %s%s' % (f.LocalPath(),
2127 lnum,
2128 match.group(1),
2129 did_you_mean))
2130 return results
2131
2132
2133def _CheckForInvalidOSMacros(input_api, output_api):
2134 """Check all affected files for invalid OS macros."""
2135 bad_macros = []
2136 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472137 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542138 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2139
2140 if not bad_macros:
2141 return []
2142
2143 return [output_api.PresubmitError(
2144 'Possibly invalid OS macro[s] found. Please fix your code\n'
2145 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2146
lliabraa35bab3932014-10-01 12:16:442147
2148def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2149 """Check all affected files for invalid "if defined" macros."""
2150 ALWAYS_DEFINED_MACROS = (
2151 "TARGET_CPU_PPC",
2152 "TARGET_CPU_PPC64",
2153 "TARGET_CPU_68K",
2154 "TARGET_CPU_X86",
2155 "TARGET_CPU_ARM",
2156 "TARGET_CPU_MIPS",
2157 "TARGET_CPU_SPARC",
2158 "TARGET_CPU_ALPHA",
2159 "TARGET_IPHONE_SIMULATOR",
2160 "TARGET_OS_EMBEDDED",
2161 "TARGET_OS_IPHONE",
2162 "TARGET_OS_MAC",
2163 "TARGET_OS_UNIX",
2164 "TARGET_OS_WIN32",
2165 )
2166 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2167 results = []
2168 for lnum, line in f.ChangedContents():
2169 for match in ifdef_macro.finditer(line):
2170 if match.group(1) in ALWAYS_DEFINED_MACROS:
2171 always_defined = ' %s is always defined. ' % match.group(1)
2172 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2173 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2174 lnum,
2175 always_defined,
2176 did_you_mean))
2177 return results
2178
2179
2180def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2181 """Check all affected files for invalid "if defined" macros."""
2182 bad_macros = []
2183 for f in input_api.AffectedFiles():
2184 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2185 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2186
2187 if not bad_macros:
2188 return []
2189
2190 return [output_api.PresubmitError(
2191 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2192 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2193 bad_macros)]
2194
2195
mlamouria82272622014-09-16 18:45:042196def _CheckForIPCRules(input_api, output_api):
2197 """Check for same IPC rules described in
2198 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2199 """
2200 base_pattern = r'IPC_ENUM_TRAITS\('
2201 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2202 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2203
2204 problems = []
2205 for f in input_api.AffectedSourceFiles(None):
2206 local_path = f.LocalPath()
2207 if not local_path.endswith('.h'):
2208 continue
2209 for line_number, line in f.ChangedContents():
2210 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2211 problems.append(
2212 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2213
2214 if problems:
2215 return [output_api.PresubmitPromptWarning(
2216 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2217 else:
2218 return []
2219
[email protected]b00342e7f2013-03-26 16:21:542220
mostynbb639aca52015-01-07 20:31:232221def _CheckForWindowsLineEndings(input_api, output_api):
2222 """Check source code and known ascii text files for Windows style line
2223 endings.
2224 """
earthdok1b5e0ee2015-03-10 15:19:102225 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232226
2227 file_inclusion_pattern = (
2228 known_text_files,
2229 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2230 )
2231
2232 filter = lambda f: input_api.FilterSourceFile(
2233 f, white_list=file_inclusion_pattern, black_list=None)
2234 files = [f.LocalPath() for f in
2235 input_api.AffectedSourceFiles(filter)]
2236
2237 problems = []
2238
2239 for file in files:
2240 fp = open(file, 'r')
2241 for line in fp:
2242 if line.endswith('\r\n'):
2243 problems.append(file)
2244 break
2245 fp.close()
2246
2247 if problems:
2248 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2249 'these files to contain Windows style line endings?\n' +
2250 '\n'.join(problems))]
2251
2252 return []
2253
2254
pastarmovj89f7ee12016-09-20 14:58:132255def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2256 lint_filters=None, verbose_level=None):
2257 """Checks that all source files use SYSLOG properly."""
2258 syslog_files = []
2259 for f in input_api.AffectedSourceFiles(source_file_filter):
2260 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2261 syslog_files.append(f.LocalPath())
2262 if syslog_files:
2263 return [output_api.PresubmitPromptWarning(
2264 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2265 ' calls.\nFiles to check:\n', items=syslog_files)]
2266 return []
2267
2268
[email protected]1f7b4172010-01-28 01:17:342269def CheckChangeOnUpload(input_api, output_api):
2270 results = []
2271 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472272 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282273 results.extend(
2274 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192275 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222276 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132277 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542278 return results
[email protected]ca8d19842009-02-19 16:33:122279
2280
[email protected]1bfb8322014-04-23 01:02:412281def GetTryServerMasterForBot(bot):
2282 """Returns the Try Server master for the given bot.
2283
[email protected]0bb112362014-07-26 04:38:322284 It tries to guess the master from the bot name, but may still fail
2285 and return None. There is no longer a default master.
2286 """
2287 # Potentially ambiguous bot names are listed explicitly.
2288 master_map = {
tandriie5587792016-07-14 00:34:502289 'chromium_presubmit': 'master.tryserver.chromium.linux',
2290 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412291 }
[email protected]0bb112362014-07-26 04:38:322292 master = master_map.get(bot)
2293 if not master:
wnwen4fbaab82016-05-25 12:54:362294 if 'android' in bot:
tandriie5587792016-07-14 00:34:502295 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362296 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502297 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322298 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502299 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322300 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502301 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322302 return master
[email protected]1bfb8322014-04-23 01:02:412303
2304
Paweł Hajdan, Jr55083782014-12-19 20:32:562305def GetDefaultTryConfigs(bots):
2306 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012307 """
2308
Paweł Hajdan, Jr55083782014-12-19 20:32:562309 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412310
2311 # Build up the mapping from tryserver master to bot/test.
2312 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562313 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412314 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2315 return out
[email protected]38c6a512013-12-18 23:48:012316
2317
[email protected]ca8d19842009-02-19 16:33:122318def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542319 results = []
[email protected]1f7b4172010-01-28 01:17:342320 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542321 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272322 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342323 input_api,
2324 output_api,
[email protected]2fdd1f362013-01-16 03:56:032325 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272326
[email protected]3e4eb112011-01-18 03:29:542327 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2328 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412329 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2330 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542331 return results