blob: 92888ceb5879976b208495d36ec7982064ddcc5d [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d1982009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d1982009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
jif65398702016-10-27 10:19:48148 (
149 r"/\s+UTF8String\s*]",
150 (
151 'The use of -[NSString UTF8String] is dangerous as it can return null',
152 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
153 'Please use |SysNSStringToUTF8| instead.',
154 ),
155 True,
156 ),
[email protected]127f18ec2012-06-16 05:05:59157)
158
159
160_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20161 # Make sure that gtest's FRIEND_TEST() macro is not used; the
162 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30163 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20164 (
165 'FRIEND_TEST(',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20168 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
169 ),
170 False,
[email protected]7345da02012-11-27 14:31:49171 (),
[email protected]23e6cbc2012-06-16 18:51:20172 ),
173 (
thomasanderson4b569052016-09-14 20:15:53174 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
175 (
176 'Chrome clients wishing to select events on X windows should use',
177 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
178 'you are selecting events from the GPU process, or if you are using',
179 'an XDisplay other than gfx::GetXDisplay().',
180 ),
181 True,
182 (
183 r"^ui[\\\/]gl[\\\/].*\.cc$",
184 r"^media[\\\/]gpu[\\\/].*\.cc$",
185 r"^gpu[\\\/].*\.cc$",
186 ),
187 ),
188 (
[email protected]23e6cbc2012-06-16 18:51:20189 'ScopedAllowIO',
190 (
[email protected]e3c945502012-06-26 20:01:49191 'New code should not use ScopedAllowIO. Post a task to the blocking',
192 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20193 ),
[email protected]e3c945502012-06-26 20:01:49194 True,
[email protected]7345da02012-11-27 14:31:49195 (
nyad2c548b2015-12-09 03:22:32196 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10197 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49198 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22199 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31200 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51201 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
202 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09203 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49204 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
205 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25206 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41207 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
208 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25209 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48210 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
211 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01212 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25213 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
214 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
215 r"embedded_test_server\.cc$",
216 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
217 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54218 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53219 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
220 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45221 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
222 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
223 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
224 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
225 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49226 ),
[email protected]23e6cbc2012-06-16 18:51:20227 ),
[email protected]52657f62013-05-20 05:30:31228 (
tomhudsone2c14d552016-05-26 17:07:46229 'setMatrixClip',
230 (
231 'Overriding setMatrixClip() is prohibited; ',
232 'the base function is deprecated. ',
233 ),
234 True,
235 (),
236 ),
237 (
[email protected]52657f62013-05-20 05:30:31238 'SkRefPtr',
239 (
240 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22241 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31242 ),
243 True,
244 (),
245 ),
246 (
247 'SkAutoRef',
248 (
249 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22250 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31251 ),
252 True,
253 (),
254 ),
255 (
256 'SkAutoTUnref',
257 (
258 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22259 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31260 ),
261 True,
262 (),
263 ),
264 (
265 'SkAutoUnref',
266 (
267 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
268 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22269 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31270 ),
271 True,
272 (),
273 ),
[email protected]d89eec82013-12-03 14:10:59274 (
275 r'/HANDLE_EINTR\(.*close',
276 (
277 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
278 'descriptor will be closed, and it is incorrect to retry the close.',
279 'Either call close directly and ignore its return value, or wrap close',
280 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
281 ),
282 True,
283 (),
284 ),
285 (
286 r'/IGNORE_EINTR\((?!.*close)',
287 (
288 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
289 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
290 ),
291 True,
292 (
293 # Files that #define IGNORE_EINTR.
294 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
295 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
296 ),
297 ),
[email protected]ec5b3f02014-04-04 18:43:43298 (
299 r'/v8::Extension\(',
300 (
301 'Do not introduce new v8::Extensions into the code base, use',
302 'gin::Wrappable instead. See http://crbug.com/334679',
303 ),
304 True,
[email protected]f55c90ee62014-04-12 00:50:03305 (
joaodasilva718f87672014-08-30 09:25:49306 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03307 ),
[email protected]ec5b3f02014-04-04 18:43:43308 ),
skyostilf9469f72015-04-20 10:38:52309 (
jame2d1a952016-04-02 00:27:10310 '#pragma comment(lib,',
311 (
312 'Specify libraries to link with in build files and not in the source.',
313 ),
314 True,
315 (),
316 ),
dcheng8f0694bae2016-10-12 15:58:15317 (
avid5a337982016-10-19 23:07:15318 r'STLDeleteElements', # http://crbug.com/555865
319 (
320 'This call is obsolete with C++ 11; create a container with owning',
321 'pointers instead (e.g. std::vector<std::unique_ptr<x>> ).',
322 ),
323 True,
324 (),
325 ),
326 (
327 r'STLDeleteValues', # http://crbug.com/555865
328 (
329 'This call is obsolete with C++ 11; create a map with owning',
330 'pointers instead (e.g. std::map<std::string, std::unique_ptr<x>> ).',
331 ),
332 True,
333 (),
334 ),
[email protected]127f18ec2012-06-16 05:05:59335)
336
wnwenbdc444e2016-05-25 13:44:15337
mlamouria82272622014-09-16 18:45:04338_IPC_ENUM_TRAITS_DEPRECATED = (
339 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
340 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
341
[email protected]127f18ec2012-06-16 05:05:59342
[email protected]b00342e7f2013-03-26 16:21:54343_VALID_OS_MACROS = (
344 # Please keep sorted.
345 'OS_ANDROID',
346 'OS_BSD',
347 'OS_CAT', # For testing.
348 'OS_CHROMEOS',
349 'OS_FREEBSD',
350 'OS_IOS',
351 'OS_LINUX',
352 'OS_MACOSX',
353 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21354 'OS_NACL_NONSFI',
355 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12356 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54357 'OS_OPENBSD',
358 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37359 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54360 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54361 'OS_WIN',
362)
363
364
agrievef32bcc72016-04-04 14:57:40365_ANDROID_SPECIFIC_PYDEPS_FILES = [
366 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19367 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40368]
369
wnwenbdc444e2016-05-25 13:44:15370
agrievef32bcc72016-04-04 14:57:40371_GENERIC_PYDEPS_FILES = [
372 'build/secondary/tools/swarming_client/isolate.pydeps',
373]
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
dskiba88634f4e2015-08-14 23:03:291588def _CheckAndroidToastUsage(input_api, output_api):
1589 """Checks that code uses org.chromium.ui.widget.Toast instead of
1590 android.widget.Toast (Chromium Toast doesn't force hardware
1591 acceleration on low-end devices, saving memory).
1592 """
1593 toast_import_pattern = input_api.re.compile(
1594 r'^import android\.widget\.Toast;$')
1595
1596 errors = []
1597
1598 sources = lambda affected_file: input_api.FilterSourceFile(
1599 affected_file,
1600 black_list=(_EXCLUDED_PATHS +
1601 _TEST_CODE_EXCLUDED_PATHS +
1602 input_api.DEFAULT_BLACK_LIST +
1603 (r'^chromecast[\\\/].*',
1604 r'^remoting[\\\/].*')),
1605 white_list=(r'.*\.java$',))
1606
1607 for f in input_api.AffectedSourceFiles(sources):
1608 for line_num, line in f.ChangedContents():
1609 if toast_import_pattern.search(line):
1610 errors.append("%s:%d" % (f.LocalPath(), line_num))
1611
1612 results = []
1613
1614 if errors:
1615 results.append(output_api.PresubmitError(
1616 'android.widget.Toast usage is detected. Android toasts use hardware'
1617 ' acceleration, and can be\ncostly on low-end devices. Please use'
1618 ' org.chromium.ui.widget.Toast instead.\n'
1619 'Contact [email protected] if you have any questions.',
1620 errors))
1621
1622 return results
1623
1624
dgnaa68d5e2015-06-10 10:08:221625def _CheckAndroidCrLogUsage(input_api, output_api):
1626 """Checks that new logs using org.chromium.base.Log:
1627 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511628 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221629 """
pkotwicza1dd0b002016-05-16 14:41:041630
1631 # Do not check format of logs in //chrome/android/webapk because
1632 # //chrome/android/webapk cannot depend on //base
1633 cr_log_check_excluded_paths = [
1634 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1635 ]
1636
dgnaa68d5e2015-06-10 10:08:221637 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121638 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1639 class_in_base_pattern = input_api.re.compile(
1640 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1641 has_some_log_import_pattern = input_api.re.compile(
1642 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221643 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121644 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221645 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511646 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221647 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221648
Vincent Scheib16d7b272015-09-15 18:09:071649 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221650 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041651 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1652 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121653
dgnaa68d5e2015-06-10 10:08:221654 tag_decl_errors = []
1655 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121656 tag_errors = []
dgn38736db2015-09-18 19:20:511657 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121658 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221659
1660 for f in input_api.AffectedSourceFiles(sources):
1661 file_content = input_api.ReadFile(f)
1662 has_modified_logs = False
1663
1664 # Per line checks
dgn87d9fb62015-06-12 09:15:121665 if (cr_log_import_pattern.search(file_content) or
1666 (class_in_base_pattern.search(file_content) and
1667 not has_some_log_import_pattern.search(file_content))):
1668 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221669 for line_num, line in f.ChangedContents():
1670
1671 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121672 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221673 if match:
1674 has_modified_logs = True
1675
1676 # Make sure it uses "TAG"
1677 if not match.group('tag') == 'TAG':
1678 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121679 else:
1680 # Report non cr Log function calls in changed lines
1681 for line_num, line in f.ChangedContents():
1682 if log_call_pattern.search(line):
1683 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221684
1685 # Per file checks
1686 if has_modified_logs:
1687 # Make sure the tag is using the "cr" prefix and is not too long
1688 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511689 tag_name = match.group('name') if match else None
1690 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221691 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511692 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221693 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511694 elif '.' in tag_name:
1695 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221696
1697 results = []
1698 if tag_decl_errors:
1699 results.append(output_api.PresubmitPromptWarning(
1700 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511701 '"private static final String TAG = "<package tag>".\n'
1702 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221703 tag_decl_errors))
1704
1705 if tag_length_errors:
1706 results.append(output_api.PresubmitError(
1707 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511708 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221709 tag_length_errors))
1710
1711 if tag_errors:
1712 results.append(output_api.PresubmitPromptWarning(
1713 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1714 tag_errors))
1715
dgn87d9fb62015-06-12 09:15:121716 if util_log_errors:
dgn4401aa52015-04-29 16:26:171717 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121718 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1719 util_log_errors))
1720
dgn38736db2015-09-18 19:20:511721 if tag_with_dot_errors:
1722 results.append(output_api.PresubmitPromptWarning(
1723 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1724 tag_with_dot_errors))
1725
dgn4401aa52015-04-29 16:26:171726 return results
1727
1728
agrieve7b6479d82015-10-07 14:24:221729def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1730 """Checks if MDPI assets are placed in a correct directory."""
1731 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1732 ('/res/drawable/' in f.LocalPath() or
1733 '/res/drawable-ldrtl/' in f.LocalPath()))
1734 errors = []
1735 for f in input_api.AffectedFiles(include_deletes=False,
1736 file_filter=file_filter):
1737 errors.append(' %s' % f.LocalPath())
1738
1739 results = []
1740 if errors:
1741 results.append(output_api.PresubmitError(
1742 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1743 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1744 '/res/drawable-ldrtl/.\n'
1745 'Contact [email protected] if you have questions.', errors))
1746 return results
1747
1748
agrievef32bcc72016-04-04 14:57:401749class PydepsChecker(object):
1750 def __init__(self, input_api, pydeps_files):
1751 self._file_cache = {}
1752 self._input_api = input_api
1753 self._pydeps_files = pydeps_files
1754
1755 def _LoadFile(self, path):
1756 """Returns the list of paths within a .pydeps file relative to //."""
1757 if path not in self._file_cache:
1758 with open(path) as f:
1759 self._file_cache[path] = f.read()
1760 return self._file_cache[path]
1761
1762 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1763 """Returns an interable of paths within the .pydep, relativized to //."""
1764 os_path = self._input_api.os_path
1765 pydeps_dir = os_path.dirname(pydeps_path)
1766 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1767 if not l.startswith('*'))
1768 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1769
1770 def _CreateFilesToPydepsMap(self):
1771 """Returns a map of local_path -> list_of_pydeps."""
1772 ret = {}
1773 for pydep_local_path in self._pydeps_files:
1774 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1775 ret.setdefault(path, []).append(pydep_local_path)
1776 return ret
1777
1778 def ComputeAffectedPydeps(self):
1779 """Returns an iterable of .pydeps files that might need regenerating."""
1780 affected_pydeps = set()
1781 file_to_pydeps_map = None
1782 for f in self._input_api.AffectedFiles(include_deletes=True):
1783 local_path = f.LocalPath()
1784 if local_path == 'DEPS':
1785 return self._pydeps_files
1786 elif local_path.endswith('.pydeps'):
1787 if local_path in self._pydeps_files:
1788 affected_pydeps.add(local_path)
1789 elif local_path.endswith('.py'):
1790 if file_to_pydeps_map is None:
1791 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1792 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1793 return affected_pydeps
1794
1795 def DetermineIfStale(self, pydeps_path):
1796 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411797 import difflib
agrievef32bcc72016-04-04 14:57:401798 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1799 cmd = old_pydeps_data[1][1:].strip()
1800 new_pydeps_data = self._input_api.subprocess.check_output(
1801 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411802 old_contents = old_pydeps_data[2:]
1803 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401804 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411805 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401806
1807
1808def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1809 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001810 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281811 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1812 # Mac, so skip it on other platforms.
1813 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001814 return []
agrievef32bcc72016-04-04 14:57:401815 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1816 is_android = input_api.os_path.exists('third_party/android_tools')
1817 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1818 results = []
1819 # First, check for new / deleted .pydeps.
1820 for f in input_api.AffectedFiles(include_deletes=True):
1821 if f.LocalPath().endswith('.pydeps'):
1822 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1823 results.append(output_api.PresubmitError(
1824 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1825 'remove %s' % f.LocalPath()))
1826 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1827 results.append(output_api.PresubmitError(
1828 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1829 'include %s' % f.LocalPath()))
1830
1831 if results:
1832 return results
1833
1834 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1835
1836 for pydep_path in checker.ComputeAffectedPydeps():
1837 try:
phajdan.jr0d9878552016-11-04 10:49:411838 result = checker.DetermineIfStale(pydep_path)
1839 if result:
1840 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401841 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411842 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1843 'To regenerate, run:\n\n %s' %
1844 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401845 except input_api.subprocess.CalledProcessError as error:
1846 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1847 long_text=error.output)]
1848
1849 return results
1850
1851
glidere61efad2015-02-18 17:39:431852def _CheckSingletonInHeaders(input_api, output_api):
1853 """Checks to make sure no header files have |Singleton<|."""
1854 def FileFilter(affected_file):
1855 # It's ok for base/memory/singleton.h to have |Singleton<|.
1856 black_list = (_EXCLUDED_PATHS +
1857 input_api.DEFAULT_BLACK_LIST +
1858 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1859 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1860
sergeyu34d21222015-09-16 00:11:441861 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431862 files = []
1863 for f in input_api.AffectedSourceFiles(FileFilter):
1864 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1865 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1866 contents = input_api.ReadFile(f)
1867 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241868 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431869 pattern.search(line)):
1870 files.append(f)
1871 break
1872
1873 if files:
yolandyandaabc6d2016-04-18 18:29:391874 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441875 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431876 'Please move them to an appropriate source file so that the ' +
1877 'template gets instantiated in a single compilation unit.',
1878 files) ]
1879 return []
1880
1881
dbeam37e8e7402016-02-10 22:58:201882def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1883 """Checks for old style compiled_resources.gyp files."""
1884 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1885
1886 added_compiled_resources = filter(is_compiled_resource, [
1887 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1888 ])
1889
1890 if not added_compiled_resources:
1891 return []
1892
1893 return [output_api.PresubmitError(
1894 "Found new compiled_resources.gyp files:\n%s\n\n"
1895 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551896 "please use compiled_resources2.gyp instead:\n"
1897 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1898 %
dbeam37e8e7402016-02-10 22:58:201899 "\n".join(added_compiled_resources))]
1900
1901
[email protected]fd20b902014-05-09 02:14:531902_DEPRECATED_CSS = [
1903 # Values
1904 ( "-webkit-box", "flex" ),
1905 ( "-webkit-inline-box", "inline-flex" ),
1906 ( "-webkit-flex", "flex" ),
1907 ( "-webkit-inline-flex", "inline-flex" ),
1908 ( "-webkit-min-content", "min-content" ),
1909 ( "-webkit-max-content", "max-content" ),
1910
1911 # Properties
1912 ( "-webkit-background-clip", "background-clip" ),
1913 ( "-webkit-background-origin", "background-origin" ),
1914 ( "-webkit-background-size", "background-size" ),
1915 ( "-webkit-box-shadow", "box-shadow" ),
1916
1917 # Functions
1918 ( "-webkit-gradient", "gradient" ),
1919 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1920 ( "-webkit-linear-gradient", "linear-gradient" ),
1921 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1922 ( "-webkit-radial-gradient", "radial-gradient" ),
1923 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1924]
1925
1926def _CheckNoDeprecatedCSS(input_api, output_api):
1927 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251928 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341929 documentation and iOS CSS for dom distiller
1930 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251931 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531932 results = []
dbeam070cfe62014-10-22 06:44:021933 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251934 black_list = (_EXCLUDED_PATHS +
1935 _TEST_CODE_EXCLUDED_PATHS +
1936 input_api.DEFAULT_BLACK_LIST +
1937 (r"^chrome/common/extensions/docs",
1938 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341939 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051940 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441941 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251942 r"^native_client_sdk"))
1943 file_filter = lambda f: input_api.FilterSourceFile(
1944 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531945 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1946 for line_num, line in fpath.ChangedContents():
1947 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021948 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531949 results.append(output_api.PresubmitError(
1950 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1951 (fpath.LocalPath(), line_num, deprecated_value, value)))
1952 return results
1953
mohan.reddyf21db962014-10-16 12:26:471954
dbeam070cfe62014-10-22 06:44:021955_DEPRECATED_JS = [
1956 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1957 ( "__defineGetter__", "Object.defineProperty" ),
1958 ( "__defineSetter__", "Object.defineProperty" ),
1959]
1960
1961def _CheckNoDeprecatedJS(input_api, output_api):
1962 """Make sure that we don't use deprecated JS in Chrome code."""
1963 results = []
1964 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1965 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1966 input_api.DEFAULT_BLACK_LIST)
1967 file_filter = lambda f: input_api.FilterSourceFile(
1968 f, white_list=file_inclusion_pattern, black_list=black_list)
1969 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1970 for lnum, line in fpath.ChangedContents():
1971 for (deprecated, replacement) in _DEPRECATED_JS:
1972 if deprecated in line:
1973 results.append(output_api.PresubmitError(
1974 "%s:%d: Use of deprecated JS %s, use %s instead" %
1975 (fpath.LocalPath(), lnum, deprecated, replacement)))
1976 return results
1977
1978
dgnaa68d5e2015-06-10 10:08:221979def _AndroidSpecificOnUploadChecks(input_api, output_api):
1980 """Groups checks that target android code."""
1981 results = []
dgnaa68d5e2015-06-10 10:08:221982 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221983 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291984 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221985 return results
1986
1987
[email protected]22c9bd72011-03-27 16:47:391988def _CommonChecks(input_api, output_api):
1989 """Checks common to both upload and commit."""
1990 results = []
1991 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381992 input_api, output_api,
1993 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461994 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191995 results.extend(
[email protected]760deea2013-12-10 19:33:491996 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541997 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181998 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521999 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222000 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442001 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592002 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062003 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122004 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182005 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222006 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492007 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272008 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032009 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492010 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442011 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272012 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542013 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442014 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392015 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552016 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042017 results.extend(
2018 input_api.canned_checks.CheckChangeHasNoTabs(
2019 input_api,
2020 output_api,
2021 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402022 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162023 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592024 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082025 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:532026 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:022027 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472028 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042029 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232030 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432031 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:202032 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402033 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152034 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172035 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232036 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242037
2038 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2039 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2040 input_api, output_api,
2041 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382042 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392043 return results
[email protected]1f7b4172010-01-28 01:17:342044
[email protected]b337cb5b2011-01-23 21:24:052045
[email protected]66daa702011-05-28 14:41:462046def _CheckAuthorizedAuthor(input_api, output_api):
2047 """For non-googler/chromites committers, verify the author's email address is
2048 in AUTHORS.
2049 """
2050 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012051 if not author:
2052 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462053 return []
[email protected]c99663292011-05-31 19:46:082054 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462055 input_api.PresubmitLocalPath(), 'AUTHORS')
2056 valid_authors = (
2057 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2058 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182059 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172060 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2061 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232062 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462063 return [output_api.PresubmitPromptWarning(
2064 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2065 '\n'
2066 'http://www.chromium.org/developers/contributing-code and read the '
2067 '"Legal" section\n'
2068 'If you are a chromite, verify the contributor signed the CLA.') %
2069 author)]
2070 return []
2071
2072
[email protected]b8079ae4a2012-12-05 19:56:492073def _CheckPatchFiles(input_api, output_api):
2074 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2075 if f.LocalPath().endswith(('.orig', '.rej'))]
2076 if problems:
2077 return [output_api.PresubmitError(
2078 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032079 else:
2080 return []
[email protected]b8079ae4a2012-12-05 19:56:492081
2082
[email protected]b00342e7f2013-03-26 16:21:542083def _DidYouMeanOSMacro(bad_macro):
2084 try:
2085 return {'A': 'OS_ANDROID',
2086 'B': 'OS_BSD',
2087 'C': 'OS_CHROMEOS',
2088 'F': 'OS_FREEBSD',
2089 'L': 'OS_LINUX',
2090 'M': 'OS_MACOSX',
2091 'N': 'OS_NACL',
2092 'O': 'OS_OPENBSD',
2093 'P': 'OS_POSIX',
2094 'S': 'OS_SOLARIS',
2095 'W': 'OS_WIN'}[bad_macro[3].upper()]
2096 except KeyError:
2097 return ''
2098
2099
2100def _CheckForInvalidOSMacrosInFile(input_api, f):
2101 """Check for sensible looking, totally invalid OS macros."""
2102 preprocessor_statement = input_api.re.compile(r'^\s*#')
2103 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2104 results = []
2105 for lnum, line in f.ChangedContents():
2106 if preprocessor_statement.search(line):
2107 for match in os_macro.finditer(line):
2108 if not match.group(1) in _VALID_OS_MACROS:
2109 good = _DidYouMeanOSMacro(match.group(1))
2110 did_you_mean = ' (did you mean %s?)' % good if good else ''
2111 results.append(' %s:%d %s%s' % (f.LocalPath(),
2112 lnum,
2113 match.group(1),
2114 did_you_mean))
2115 return results
2116
2117
2118def _CheckForInvalidOSMacros(input_api, output_api):
2119 """Check all affected files for invalid OS macros."""
2120 bad_macros = []
2121 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472122 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542123 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2124
2125 if not bad_macros:
2126 return []
2127
2128 return [output_api.PresubmitError(
2129 'Possibly invalid OS macro[s] found. Please fix your code\n'
2130 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2131
lliabraa35bab3932014-10-01 12:16:442132
2133def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2134 """Check all affected files for invalid "if defined" macros."""
2135 ALWAYS_DEFINED_MACROS = (
2136 "TARGET_CPU_PPC",
2137 "TARGET_CPU_PPC64",
2138 "TARGET_CPU_68K",
2139 "TARGET_CPU_X86",
2140 "TARGET_CPU_ARM",
2141 "TARGET_CPU_MIPS",
2142 "TARGET_CPU_SPARC",
2143 "TARGET_CPU_ALPHA",
2144 "TARGET_IPHONE_SIMULATOR",
2145 "TARGET_OS_EMBEDDED",
2146 "TARGET_OS_IPHONE",
2147 "TARGET_OS_MAC",
2148 "TARGET_OS_UNIX",
2149 "TARGET_OS_WIN32",
2150 )
2151 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2152 results = []
2153 for lnum, line in f.ChangedContents():
2154 for match in ifdef_macro.finditer(line):
2155 if match.group(1) in ALWAYS_DEFINED_MACROS:
2156 always_defined = ' %s is always defined. ' % match.group(1)
2157 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2158 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2159 lnum,
2160 always_defined,
2161 did_you_mean))
2162 return results
2163
2164
2165def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2166 """Check all affected files for invalid "if defined" macros."""
2167 bad_macros = []
2168 for f in input_api.AffectedFiles():
2169 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2170 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2171
2172 if not bad_macros:
2173 return []
2174
2175 return [output_api.PresubmitError(
2176 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2177 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2178 bad_macros)]
2179
2180
mlamouria82272622014-09-16 18:45:042181def _CheckForIPCRules(input_api, output_api):
2182 """Check for same IPC rules described in
2183 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2184 """
2185 base_pattern = r'IPC_ENUM_TRAITS\('
2186 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2187 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2188
2189 problems = []
2190 for f in input_api.AffectedSourceFiles(None):
2191 local_path = f.LocalPath()
2192 if not local_path.endswith('.h'):
2193 continue
2194 for line_number, line in f.ChangedContents():
2195 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2196 problems.append(
2197 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2198
2199 if problems:
2200 return [output_api.PresubmitPromptWarning(
2201 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2202 else:
2203 return []
2204
[email protected]b00342e7f2013-03-26 16:21:542205
mostynbb639aca52015-01-07 20:31:232206def _CheckForWindowsLineEndings(input_api, output_api):
2207 """Check source code and known ascii text files for Windows style line
2208 endings.
2209 """
earthdok1b5e0ee2015-03-10 15:19:102210 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232211
2212 file_inclusion_pattern = (
2213 known_text_files,
2214 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2215 )
2216
2217 filter = lambda f: input_api.FilterSourceFile(
2218 f, white_list=file_inclusion_pattern, black_list=None)
2219 files = [f.LocalPath() for f in
2220 input_api.AffectedSourceFiles(filter)]
2221
2222 problems = []
2223
2224 for file in files:
2225 fp = open(file, 'r')
2226 for line in fp:
2227 if line.endswith('\r\n'):
2228 problems.append(file)
2229 break
2230 fp.close()
2231
2232 if problems:
2233 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2234 'these files to contain Windows style line endings?\n' +
2235 '\n'.join(problems))]
2236
2237 return []
2238
2239
pastarmovj89f7ee12016-09-20 14:58:132240def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2241 lint_filters=None, verbose_level=None):
2242 """Checks that all source files use SYSLOG properly."""
2243 syslog_files = []
2244 for f in input_api.AffectedSourceFiles(source_file_filter):
2245 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2246 syslog_files.append(f.LocalPath())
2247 if syslog_files:
2248 return [output_api.PresubmitPromptWarning(
2249 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2250 ' calls.\nFiles to check:\n', items=syslog_files)]
2251 return []
2252
2253
[email protected]1f7b4172010-01-28 01:17:342254def CheckChangeOnUpload(input_api, output_api):
2255 results = []
2256 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472257 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282258 results.extend(
2259 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192260 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222261 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132262 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542263 return results
[email protected]ca8d1982009-02-19 16:33:122264
2265
[email protected]1bfb8322014-04-23 01:02:412266def GetTryServerMasterForBot(bot):
2267 """Returns the Try Server master for the given bot.
2268
[email protected]0bb112362014-07-26 04:38:322269 It tries to guess the master from the bot name, but may still fail
2270 and return None. There is no longer a default master.
2271 """
2272 # Potentially ambiguous bot names are listed explicitly.
2273 master_map = {
tandriie5587792016-07-14 00:34:502274 'chromium_presubmit': 'master.tryserver.chromium.linux',
2275 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412276 }
[email protected]0bb112362014-07-26 04:38:322277 master = master_map.get(bot)
2278 if not master:
wnwen4fbaab82016-05-25 12:54:362279 if 'android' in bot:
tandriie5587792016-07-14 00:34:502280 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362281 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502282 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322283 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502284 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322285 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502286 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322287 return master
[email protected]1bfb8322014-04-23 01:02:412288
2289
Paweł Hajdan, Jr55083782014-12-19 20:32:562290def GetDefaultTryConfigs(bots):
2291 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012292 """
2293
Paweł Hajdan, Jr55083782014-12-19 20:32:562294 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412295
2296 # Build up the mapping from tryserver master to bot/test.
2297 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562298 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412299 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2300 return out
[email protected]38c6a512013-12-18 23:48:012301
2302
[email protected]ca8d1982009-02-19 16:33:122303def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542304 results = []
[email protected]1f7b4172010-01-28 01:17:342305 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542306 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272307 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342308 input_api,
2309 output_api,
[email protected]2fdd1f362013-01-16 03:56:032310 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272311
[email protected]3e4eb112011-01-18 03:29:542312 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2313 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412314 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2315 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542316 return results