blob: da46670970c7c4a7bb7c5b42566b0d60a6491044 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d1982009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d1982009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
jif65398702016-10-27 10:19:48148 (
149 r"/\s+UTF8String\s*]",
150 (
151 'The use of -[NSString UTF8String] is dangerous as it can return null',
152 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
153 'Please use |SysNSStringToUTF8| instead.',
154 ),
155 True,
156 ),
[email protected]127f18ec2012-06-16 05:05:59157)
158
159
160_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20161 # Make sure that gtest's FRIEND_TEST() macro is not used; the
162 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30163 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20164 (
165 'FRIEND_TEST(',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20168 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
169 ),
170 False,
[email protected]7345da02012-11-27 14:31:49171 (),
[email protected]23e6cbc2012-06-16 18:51:20172 ),
173 (
thomasanderson4b569052016-09-14 20:15:53174 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
175 (
176 'Chrome clients wishing to select events on X windows should use',
177 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
178 'you are selecting events from the GPU process, or if you are using',
179 'an XDisplay other than gfx::GetXDisplay().',
180 ),
181 True,
182 (
183 r"^ui[\\\/]gl[\\\/].*\.cc$",
184 r"^media[\\\/]gpu[\\\/].*\.cc$",
185 r"^gpu[\\\/].*\.cc$",
186 ),
187 ),
188 (
[email protected]23e6cbc2012-06-16 18:51:20189 'ScopedAllowIO',
190 (
[email protected]e3c945502012-06-26 20:01:49191 'New code should not use ScopedAllowIO. Post a task to the blocking',
192 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20193 ),
[email protected]e3c945502012-06-26 20:01:49194 True,
[email protected]7345da02012-11-27 14:31:49195 (
nyad2c548b2015-12-09 03:22:32196 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10197 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49198 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22199 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31200 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51201 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
202 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09203 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49204 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
205 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25206 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41207 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
208 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25209 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48210 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
211 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01212 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25213 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
214 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
215 r"embedded_test_server\.cc$",
216 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
217 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54218 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
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):
jbriance2c51e821a2016-12-12 08:24:311589 """Checks that added or removed lines in non third party affected
1590 header files do not lead to new useless class or struct forward
1591 declaration.
jbriance9e12f162016-11-25 07:57:501592 """
1593 results = []
1594 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1595 input_api.re.MULTILINE)
1596 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1597 input_api.re.MULTILINE)
1598 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311599 if (f.LocalPath().startswith('third_party') and
1600 not f.LocalPath().startswith('third_party/WebKit') and
1601 not f.LocalPath().startswith('third_party\\WebKit')):
1602 continue
1603
jbriance9e12f162016-11-25 07:57:501604 if not f.LocalPath().endswith('.h'):
1605 continue
1606
1607 contents = input_api.ReadFile(f)
1608 fwd_decls = input_api.re.findall(class_pattern, contents)
1609 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1610
1611 useless_fwd_decls = []
1612 for decl in fwd_decls:
1613 count = sum(1 for _ in input_api.re.finditer(
1614 r'\b%s\b' % input_api.re.escape(decl), contents))
1615 if count == 1:
1616 useless_fwd_decls.append(decl)
1617
1618 if not useless_fwd_decls:
1619 continue
1620
1621 for line in f.GenerateScmDiff().splitlines():
1622 if (line.startswith('-') and not line.startswith('--') or
1623 line.startswith('+') and not line.startswith('++')):
1624 for decl in useless_fwd_decls:
1625 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1626 results.append(output_api.PresubmitPromptWarning(
1627 '%s: %s forward declaration is becoming useless' %
1628 (f.LocalPath(), decl)))
1629 useless_fwd_decls.remove(decl)
1630
1631 return results
1632
1633
dskiba88634f4e2015-08-14 23:03:291634def _CheckAndroidToastUsage(input_api, output_api):
1635 """Checks that code uses org.chromium.ui.widget.Toast instead of
1636 android.widget.Toast (Chromium Toast doesn't force hardware
1637 acceleration on low-end devices, saving memory).
1638 """
1639 toast_import_pattern = input_api.re.compile(
1640 r'^import android\.widget\.Toast;$')
1641
1642 errors = []
1643
1644 sources = lambda affected_file: input_api.FilterSourceFile(
1645 affected_file,
1646 black_list=(_EXCLUDED_PATHS +
1647 _TEST_CODE_EXCLUDED_PATHS +
1648 input_api.DEFAULT_BLACK_LIST +
1649 (r'^chromecast[\\\/].*',
1650 r'^remoting[\\\/].*')),
1651 white_list=(r'.*\.java$',))
1652
1653 for f in input_api.AffectedSourceFiles(sources):
1654 for line_num, line in f.ChangedContents():
1655 if toast_import_pattern.search(line):
1656 errors.append("%s:%d" % (f.LocalPath(), line_num))
1657
1658 results = []
1659
1660 if errors:
1661 results.append(output_api.PresubmitError(
1662 'android.widget.Toast usage is detected. Android toasts use hardware'
1663 ' acceleration, and can be\ncostly on low-end devices. Please use'
1664 ' org.chromium.ui.widget.Toast instead.\n'
1665 'Contact [email protected] if you have any questions.',
1666 errors))
1667
1668 return results
1669
1670
dgnaa68d5e2015-06-10 10:08:221671def _CheckAndroidCrLogUsage(input_api, output_api):
1672 """Checks that new logs using org.chromium.base.Log:
1673 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511674 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221675 """
pkotwicza1dd0b002016-05-16 14:41:041676
1677 # Do not check format of logs in //chrome/android/webapk because
1678 # //chrome/android/webapk cannot depend on //base
1679 cr_log_check_excluded_paths = [
1680 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1681 ]
1682
dgnaa68d5e2015-06-10 10:08:221683 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121684 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1685 class_in_base_pattern = input_api.re.compile(
1686 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1687 has_some_log_import_pattern = input_api.re.compile(
1688 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221689 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121690 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221691 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511692 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221693 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221694
Vincent Scheib16d7b272015-09-15 18:09:071695 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221696 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041697 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1698 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121699
dgnaa68d5e2015-06-10 10:08:221700 tag_decl_errors = []
1701 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121702 tag_errors = []
dgn38736db2015-09-18 19:20:511703 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121704 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221705
1706 for f in input_api.AffectedSourceFiles(sources):
1707 file_content = input_api.ReadFile(f)
1708 has_modified_logs = False
1709
1710 # Per line checks
dgn87d9fb62015-06-12 09:15:121711 if (cr_log_import_pattern.search(file_content) or
1712 (class_in_base_pattern.search(file_content) and
1713 not has_some_log_import_pattern.search(file_content))):
1714 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221715 for line_num, line in f.ChangedContents():
1716
1717 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121718 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221719 if match:
1720 has_modified_logs = True
1721
1722 # Make sure it uses "TAG"
1723 if not match.group('tag') == 'TAG':
1724 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121725 else:
1726 # Report non cr Log function calls in changed lines
1727 for line_num, line in f.ChangedContents():
1728 if log_call_pattern.search(line):
1729 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221730
1731 # Per file checks
1732 if has_modified_logs:
1733 # Make sure the tag is using the "cr" prefix and is not too long
1734 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511735 tag_name = match.group('name') if match else None
1736 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221737 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511738 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221739 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511740 elif '.' in tag_name:
1741 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221742
1743 results = []
1744 if tag_decl_errors:
1745 results.append(output_api.PresubmitPromptWarning(
1746 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511747 '"private static final String TAG = "<package tag>".\n'
1748 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221749 tag_decl_errors))
1750
1751 if tag_length_errors:
1752 results.append(output_api.PresubmitError(
1753 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511754 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221755 tag_length_errors))
1756
1757 if tag_errors:
1758 results.append(output_api.PresubmitPromptWarning(
1759 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1760 tag_errors))
1761
dgn87d9fb62015-06-12 09:15:121762 if util_log_errors:
dgn4401aa52015-04-29 16:26:171763 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121764 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1765 util_log_errors))
1766
dgn38736db2015-09-18 19:20:511767 if tag_with_dot_errors:
1768 results.append(output_api.PresubmitPromptWarning(
1769 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1770 tag_with_dot_errors))
1771
dgn4401aa52015-04-29 16:26:171772 return results
1773
1774
agrieve7b6479d82015-10-07 14:24:221775def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1776 """Checks if MDPI assets are placed in a correct directory."""
1777 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1778 ('/res/drawable/' in f.LocalPath() or
1779 '/res/drawable-ldrtl/' in f.LocalPath()))
1780 errors = []
1781 for f in input_api.AffectedFiles(include_deletes=False,
1782 file_filter=file_filter):
1783 errors.append(' %s' % f.LocalPath())
1784
1785 results = []
1786 if errors:
1787 results.append(output_api.PresubmitError(
1788 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1789 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1790 '/res/drawable-ldrtl/.\n'
1791 'Contact [email protected] if you have questions.', errors))
1792 return results
1793
1794
agrievef32bcc72016-04-04 14:57:401795class PydepsChecker(object):
1796 def __init__(self, input_api, pydeps_files):
1797 self._file_cache = {}
1798 self._input_api = input_api
1799 self._pydeps_files = pydeps_files
1800
1801 def _LoadFile(self, path):
1802 """Returns the list of paths within a .pydeps file relative to //."""
1803 if path not in self._file_cache:
1804 with open(path) as f:
1805 self._file_cache[path] = f.read()
1806 return self._file_cache[path]
1807
1808 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1809 """Returns an interable of paths within the .pydep, relativized to //."""
1810 os_path = self._input_api.os_path
1811 pydeps_dir = os_path.dirname(pydeps_path)
1812 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1813 if not l.startswith('*'))
1814 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1815
1816 def _CreateFilesToPydepsMap(self):
1817 """Returns a map of local_path -> list_of_pydeps."""
1818 ret = {}
1819 for pydep_local_path in self._pydeps_files:
1820 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1821 ret.setdefault(path, []).append(pydep_local_path)
1822 return ret
1823
1824 def ComputeAffectedPydeps(self):
1825 """Returns an iterable of .pydeps files that might need regenerating."""
1826 affected_pydeps = set()
1827 file_to_pydeps_map = None
1828 for f in self._input_api.AffectedFiles(include_deletes=True):
1829 local_path = f.LocalPath()
1830 if local_path == 'DEPS':
1831 return self._pydeps_files
1832 elif local_path.endswith('.pydeps'):
1833 if local_path in self._pydeps_files:
1834 affected_pydeps.add(local_path)
1835 elif local_path.endswith('.py'):
1836 if file_to_pydeps_map is None:
1837 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1838 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1839 return affected_pydeps
1840
1841 def DetermineIfStale(self, pydeps_path):
1842 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411843 import difflib
agrievef32bcc72016-04-04 14:57:401844 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1845 cmd = old_pydeps_data[1][1:].strip()
1846 new_pydeps_data = self._input_api.subprocess.check_output(
1847 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411848 old_contents = old_pydeps_data[2:]
1849 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401850 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411851 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401852
1853
1854def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1855 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001856 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281857 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1858 # Mac, so skip it on other platforms.
1859 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001860 return []
agrievef32bcc72016-04-04 14:57:401861 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1862 is_android = input_api.os_path.exists('third_party/android_tools')
1863 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1864 results = []
1865 # First, check for new / deleted .pydeps.
1866 for f in input_api.AffectedFiles(include_deletes=True):
1867 if f.LocalPath().endswith('.pydeps'):
1868 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1869 results.append(output_api.PresubmitError(
1870 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1871 'remove %s' % f.LocalPath()))
1872 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1873 results.append(output_api.PresubmitError(
1874 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1875 'include %s' % f.LocalPath()))
1876
1877 if results:
1878 return results
1879
1880 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1881
1882 for pydep_path in checker.ComputeAffectedPydeps():
1883 try:
phajdan.jr0d9878552016-11-04 10:49:411884 result = checker.DetermineIfStale(pydep_path)
1885 if result:
1886 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401887 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411888 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1889 'To regenerate, run:\n\n %s' %
1890 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401891 except input_api.subprocess.CalledProcessError as error:
1892 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1893 long_text=error.output)]
1894
1895 return results
1896
1897
glidere61efad2015-02-18 17:39:431898def _CheckSingletonInHeaders(input_api, output_api):
1899 """Checks to make sure no header files have |Singleton<|."""
1900 def FileFilter(affected_file):
1901 # It's ok for base/memory/singleton.h to have |Singleton<|.
1902 black_list = (_EXCLUDED_PATHS +
1903 input_api.DEFAULT_BLACK_LIST +
1904 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1905 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1906
sergeyu34d21222015-09-16 00:11:441907 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431908 files = []
1909 for f in input_api.AffectedSourceFiles(FileFilter):
1910 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1911 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1912 contents = input_api.ReadFile(f)
1913 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241914 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431915 pattern.search(line)):
1916 files.append(f)
1917 break
1918
1919 if files:
yolandyandaabc6d2016-04-18 18:29:391920 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441921 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431922 'Please move them to an appropriate source file so that the ' +
1923 'template gets instantiated in a single compilation unit.',
1924 files) ]
1925 return []
1926
1927
dbeam37e8e7402016-02-10 22:58:201928def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1929 """Checks for old style compiled_resources.gyp files."""
1930 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1931
1932 added_compiled_resources = filter(is_compiled_resource, [
1933 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1934 ])
1935
1936 if not added_compiled_resources:
1937 return []
1938
1939 return [output_api.PresubmitError(
1940 "Found new compiled_resources.gyp files:\n%s\n\n"
1941 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551942 "please use compiled_resources2.gyp instead:\n"
1943 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1944 %
dbeam37e8e7402016-02-10 22:58:201945 "\n".join(added_compiled_resources))]
1946
1947
[email protected]fd20b902014-05-09 02:14:531948_DEPRECATED_CSS = [
1949 # Values
1950 ( "-webkit-box", "flex" ),
1951 ( "-webkit-inline-box", "inline-flex" ),
1952 ( "-webkit-flex", "flex" ),
1953 ( "-webkit-inline-flex", "inline-flex" ),
1954 ( "-webkit-min-content", "min-content" ),
1955 ( "-webkit-max-content", "max-content" ),
1956
1957 # Properties
1958 ( "-webkit-background-clip", "background-clip" ),
1959 ( "-webkit-background-origin", "background-origin" ),
1960 ( "-webkit-background-size", "background-size" ),
1961 ( "-webkit-box-shadow", "box-shadow" ),
1962
1963 # Functions
1964 ( "-webkit-gradient", "gradient" ),
1965 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1966 ( "-webkit-linear-gradient", "linear-gradient" ),
1967 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1968 ( "-webkit-radial-gradient", "radial-gradient" ),
1969 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1970]
1971
1972def _CheckNoDeprecatedCSS(input_api, output_api):
1973 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251974 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341975 documentation and iOS CSS for dom distiller
1976 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251977 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531978 results = []
dbeam070cfe62014-10-22 06:44:021979 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251980 black_list = (_EXCLUDED_PATHS +
1981 _TEST_CODE_EXCLUDED_PATHS +
1982 input_api.DEFAULT_BLACK_LIST +
1983 (r"^chrome/common/extensions/docs",
1984 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341985 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051986 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441987 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251988 r"^native_client_sdk"))
1989 file_filter = lambda f: input_api.FilterSourceFile(
1990 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531991 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1992 for line_num, line in fpath.ChangedContents():
1993 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021994 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531995 results.append(output_api.PresubmitError(
1996 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1997 (fpath.LocalPath(), line_num, deprecated_value, value)))
1998 return results
1999
mohan.reddyf21db962014-10-16 12:26:472000
dbeam070cfe62014-10-22 06:44:022001_DEPRECATED_JS = [
2002 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
2003 ( "__defineGetter__", "Object.defineProperty" ),
2004 ( "__defineSetter__", "Object.defineProperty" ),
2005]
2006
2007def _CheckNoDeprecatedJS(input_api, output_api):
2008 """Make sure that we don't use deprecated JS in Chrome code."""
2009 results = []
2010 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
2011 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
2012 input_api.DEFAULT_BLACK_LIST)
2013 file_filter = lambda f: input_api.FilterSourceFile(
2014 f, white_list=file_inclusion_pattern, black_list=black_list)
2015 for fpath in input_api.AffectedFiles(file_filter=file_filter):
2016 for lnum, line in fpath.ChangedContents():
2017 for (deprecated, replacement) in _DEPRECATED_JS:
2018 if deprecated in line:
2019 results.append(output_api.PresubmitError(
2020 "%s:%d: Use of deprecated JS %s, use %s instead" %
2021 (fpath.LocalPath(), lnum, deprecated, replacement)))
2022 return results
2023
2024
dgnaa68d5e2015-06-10 10:08:222025def _AndroidSpecificOnUploadChecks(input_api, output_api):
2026 """Groups checks that target android code."""
2027 results = []
dgnaa68d5e2015-06-10 10:08:222028 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:222029 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292030 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222031 return results
2032
2033
[email protected]22c9bd72011-03-27 16:47:392034def _CommonChecks(input_api, output_api):
2035 """Checks common to both upload and commit."""
2036 results = []
2037 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382038 input_api, output_api,
2039 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
machenbachfbda9b72016-12-06 13:13:582040 results.extend(
2041 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192042 results.extend(
[email protected]760deea2013-12-10 19:33:492043 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542044 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182045 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522046 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222047 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442048 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592049 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062050 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122051 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182052 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222053 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492054 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272055 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032056 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492057 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442058 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272059 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542060 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442061 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392062 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552063 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042064 results.extend(
2065 input_api.canned_checks.CheckChangeHasNoTabs(
2066 input_api,
2067 output_api,
2068 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402069 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162070 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592071 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082072 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:532073 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:022074 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472075 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042076 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232077 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432078 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:202079 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402080 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152081 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172082 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232083 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502084 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242085
2086 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2087 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2088 input_api, output_api,
2089 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382090 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392091 return results
[email protected]1f7b4172010-01-28 01:17:342092
[email protected]b337cb5b2011-01-23 21:24:052093
[email protected]b8079ae4a2012-12-05 19:56:492094def _CheckPatchFiles(input_api, output_api):
2095 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2096 if f.LocalPath().endswith(('.orig', '.rej'))]
2097 if problems:
2098 return [output_api.PresubmitError(
2099 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032100 else:
2101 return []
[email protected]b8079ae4a2012-12-05 19:56:492102
2103
[email protected]b00342e7f2013-03-26 16:21:542104def _DidYouMeanOSMacro(bad_macro):
2105 try:
2106 return {'A': 'OS_ANDROID',
2107 'B': 'OS_BSD',
2108 'C': 'OS_CHROMEOS',
2109 'F': 'OS_FREEBSD',
2110 'L': 'OS_LINUX',
2111 'M': 'OS_MACOSX',
2112 'N': 'OS_NACL',
2113 'O': 'OS_OPENBSD',
2114 'P': 'OS_POSIX',
2115 'S': 'OS_SOLARIS',
2116 'W': 'OS_WIN'}[bad_macro[3].upper()]
2117 except KeyError:
2118 return ''
2119
2120
2121def _CheckForInvalidOSMacrosInFile(input_api, f):
2122 """Check for sensible looking, totally invalid OS macros."""
2123 preprocessor_statement = input_api.re.compile(r'^\s*#')
2124 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2125 results = []
2126 for lnum, line in f.ChangedContents():
2127 if preprocessor_statement.search(line):
2128 for match in os_macro.finditer(line):
2129 if not match.group(1) in _VALID_OS_MACROS:
2130 good = _DidYouMeanOSMacro(match.group(1))
2131 did_you_mean = ' (did you mean %s?)' % good if good else ''
2132 results.append(' %s:%d %s%s' % (f.LocalPath(),
2133 lnum,
2134 match.group(1),
2135 did_you_mean))
2136 return results
2137
2138
2139def _CheckForInvalidOSMacros(input_api, output_api):
2140 """Check all affected files for invalid OS macros."""
2141 bad_macros = []
2142 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472143 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542144 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2145
2146 if not bad_macros:
2147 return []
2148
2149 return [output_api.PresubmitError(
2150 'Possibly invalid OS macro[s] found. Please fix your code\n'
2151 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2152
lliabraa35bab3932014-10-01 12:16:442153
2154def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2155 """Check all affected files for invalid "if defined" macros."""
2156 ALWAYS_DEFINED_MACROS = (
2157 "TARGET_CPU_PPC",
2158 "TARGET_CPU_PPC64",
2159 "TARGET_CPU_68K",
2160 "TARGET_CPU_X86",
2161 "TARGET_CPU_ARM",
2162 "TARGET_CPU_MIPS",
2163 "TARGET_CPU_SPARC",
2164 "TARGET_CPU_ALPHA",
2165 "TARGET_IPHONE_SIMULATOR",
2166 "TARGET_OS_EMBEDDED",
2167 "TARGET_OS_IPHONE",
2168 "TARGET_OS_MAC",
2169 "TARGET_OS_UNIX",
2170 "TARGET_OS_WIN32",
2171 )
2172 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2173 results = []
2174 for lnum, line in f.ChangedContents():
2175 for match in ifdef_macro.finditer(line):
2176 if match.group(1) in ALWAYS_DEFINED_MACROS:
2177 always_defined = ' %s is always defined. ' % match.group(1)
2178 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2179 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2180 lnum,
2181 always_defined,
2182 did_you_mean))
2183 return results
2184
2185
2186def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2187 """Check all affected files for invalid "if defined" macros."""
2188 bad_macros = []
2189 for f in input_api.AffectedFiles():
2190 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2191 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2192
2193 if not bad_macros:
2194 return []
2195
2196 return [output_api.PresubmitError(
2197 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2198 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2199 bad_macros)]
2200
2201
mlamouria82272622014-09-16 18:45:042202def _CheckForIPCRules(input_api, output_api):
2203 """Check for same IPC rules described in
2204 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2205 """
2206 base_pattern = r'IPC_ENUM_TRAITS\('
2207 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2208 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2209
2210 problems = []
2211 for f in input_api.AffectedSourceFiles(None):
2212 local_path = f.LocalPath()
2213 if not local_path.endswith('.h'):
2214 continue
2215 for line_number, line in f.ChangedContents():
2216 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2217 problems.append(
2218 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2219
2220 if problems:
2221 return [output_api.PresubmitPromptWarning(
2222 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2223 else:
2224 return []
2225
[email protected]b00342e7f2013-03-26 16:21:542226
mostynbb639aca52015-01-07 20:31:232227def _CheckForWindowsLineEndings(input_api, output_api):
2228 """Check source code and known ascii text files for Windows style line
2229 endings.
2230 """
earthdok1b5e0ee2015-03-10 15:19:102231 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232232
2233 file_inclusion_pattern = (
2234 known_text_files,
2235 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2236 )
2237
2238 filter = lambda f: input_api.FilterSourceFile(
2239 f, white_list=file_inclusion_pattern, black_list=None)
2240 files = [f.LocalPath() for f in
2241 input_api.AffectedSourceFiles(filter)]
2242
2243 problems = []
2244
2245 for file in files:
2246 fp = open(file, 'r')
2247 for line in fp:
2248 if line.endswith('\r\n'):
2249 problems.append(file)
2250 break
2251 fp.close()
2252
2253 if problems:
2254 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2255 'these files to contain Windows style line endings?\n' +
2256 '\n'.join(problems))]
2257
2258 return []
2259
2260
pastarmovj89f7ee12016-09-20 14:58:132261def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2262 lint_filters=None, verbose_level=None):
2263 """Checks that all source files use SYSLOG properly."""
2264 syslog_files = []
2265 for f in input_api.AffectedSourceFiles(source_file_filter):
2266 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2267 syslog_files.append(f.LocalPath())
2268 if syslog_files:
2269 return [output_api.PresubmitPromptWarning(
2270 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2271 ' calls.\nFiles to check:\n', items=syslog_files)]
2272 return []
2273
2274
[email protected]1f7b4172010-01-28 01:17:342275def CheckChangeOnUpload(input_api, output_api):
2276 results = []
2277 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472278 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282279 results.extend(
2280 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192281 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222282 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132283 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542284 return results
[email protected]ca8d1982009-02-19 16:33:122285
2286
[email protected]1bfb8322014-04-23 01:02:412287def GetTryServerMasterForBot(bot):
2288 """Returns the Try Server master for the given bot.
2289
[email protected]0bb112362014-07-26 04:38:322290 It tries to guess the master from the bot name, but may still fail
2291 and return None. There is no longer a default master.
2292 """
2293 # Potentially ambiguous bot names are listed explicitly.
2294 master_map = {
tandriie5587792016-07-14 00:34:502295 'chromium_presubmit': 'master.tryserver.chromium.linux',
2296 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412297 }
[email protected]0bb112362014-07-26 04:38:322298 master = master_map.get(bot)
2299 if not master:
wnwen4fbaab82016-05-25 12:54:362300 if 'android' in bot:
tandriie5587792016-07-14 00:34:502301 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362302 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502303 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322304 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502305 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322306 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502307 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322308 return master
[email protected]1bfb8322014-04-23 01:02:412309
2310
Paweł Hajdan, Jr55083782014-12-19 20:32:562311def GetDefaultTryConfigs(bots):
2312 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012313 """
2314
Paweł Hajdan, Jr55083782014-12-19 20:32:562315 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412316
2317 # Build up the mapping from tryserver master to bot/test.
2318 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562319 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412320 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2321 return out
[email protected]38c6a512013-12-18 23:48:012322
2323
[email protected]ca8d1982009-02-19 16:33:122324def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542325 results = []
[email protected]1f7b4172010-01-28 01:17:342326 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542327 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272328 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342329 input_api,
2330 output_api,
[email protected]2fdd1f362013-01-16 03:56:032331 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272332
[email protected]3e4eb112011-01-18 03:29:542333 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2334 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412335 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2336 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542337 return results