blob: 5786edb16b88842e115e5f88d60a9b4b4217a6ff [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d19842009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
jochen9ea8fdbc2014-09-25 13:21:3531# The NetscapePlugIn library is excluded from pan-project as it will soon
32# be deleted together with the rest of the NPAPI and it's not worthwhile to
33# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3834_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3235 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3836)
37
wnwenbdc444e2016-05-25 13:44:1538
[email protected]06e6d0ff2012-12-11 01:36:4439# Fragment of a regular expression that matches C++ and Objective-C++
40# implementation files.
41_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
42
wnwenbdc444e2016-05-25 13:44:1543
[email protected]06e6d0ff2012-12-11 01:36:4444# Regular expression that matches code only used for test binaries
45# (best effort).
46_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4448 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3249 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1250 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4451 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4952 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0553 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4954 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4455 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4956 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4757 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4958 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0859 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4960 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4461)
[email protected]ca8d19842009-02-19 16:33:1262
wnwenbdc444e2016-05-25 13:44:1563
[email protected]eea609a2011-11-18 13:10:1264_TEST_ONLY_WARNING = (
65 'You might be calling functions intended only for testing from\n'
66 'production code. It is OK to ignore this warning if you know what\n'
67 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5868 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1269
70
[email protected]cf9b78f2012-11-14 11:40:2871_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4072 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2173 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
74 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2875
wnwenbdc444e2016-05-25 13:44:1576
[email protected]127f18ec2012-06-16 05:05:5977_BANNED_OBJC_FUNCTIONS = (
78 (
79 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2080 (
81 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5982 'prohibited. Please use CrTrackingArea instead.',
83 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
84 ),
85 False,
86 ),
87 (
[email protected]eaae1972014-04-16 04:17:2688 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2089 (
90 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5991 'instead.',
92 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
93 ),
94 False,
95 ),
96 (
97 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2098 (
99 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59100 'Please use |convertPoint:(point) fromView:nil| instead.',
101 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
102 ),
103 True,
104 ),
105 (
106 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20107 (
108 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59109 'Please use |convertPoint:(point) toView:nil| instead.',
110 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
111 ),
112 True,
113 ),
114 (
115 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20116 (
117 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59118 'Please use |convertRect:(point) fromView:nil| instead.',
119 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
120 ),
121 True,
122 ),
123 (
124 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20125 (
126 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59127 'Please use |convertRect:(point) toView:nil| instead.',
128 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
129 ),
130 True,
131 ),
132 (
133 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20134 (
135 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59136 'Please use |convertSize:(point) fromView:nil| instead.',
137 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
138 ),
139 True,
140 ),
141 (
142 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20143 (
144 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59145 'Please use |convertSize:(point) toView:nil| instead.',
146 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
147 ),
148 True,
149 ),
150)
151
152
153_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20154 # Make sure that gtest's FRIEND_TEST() macro is not used; the
155 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30156 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20157 (
158 'FRIEND_TEST(',
159 (
[email protected]e3c945502012-06-26 20:01:49160 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20161 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
162 ),
163 False,
[email protected]7345da02012-11-27 14:31:49164 (),
[email protected]23e6cbc2012-06-16 18:51:20165 ),
166 (
thomasanderson4b569052016-09-14 20:15:53167 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
168 (
169 'Chrome clients wishing to select events on X windows should use',
170 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
171 'you are selecting events from the GPU process, or if you are using',
172 'an XDisplay other than gfx::GetXDisplay().',
173 ),
174 True,
175 (
176 r"^ui[\\\/]gl[\\\/].*\.cc$",
177 r"^media[\\\/]gpu[\\\/].*\.cc$",
178 r"^gpu[\\\/].*\.cc$",
179 ),
180 ),
181 (
[email protected]23e6cbc2012-06-16 18:51:20182 'ScopedAllowIO',
183 (
[email protected]e3c945502012-06-26 20:01:49184 'New code should not use ScopedAllowIO. Post a task to the blocking',
185 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20186 ),
[email protected]e3c945502012-06-26 20:01:49187 True,
[email protected]7345da02012-11-27 14:31:49188 (
nyad2c548b2015-12-09 03:22:32189 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10190 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49191 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22192 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31193 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51194 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
195 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09196 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49197 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
198 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25199 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41200 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
201 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25202 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48203 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
204 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01205 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25206 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
207 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
208 r"embedded_test_server\.cc$",
209 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
210 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54211 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53212 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
213 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45214 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
215 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
216 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
217 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
218 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49219 ),
[email protected]23e6cbc2012-06-16 18:51:20220 ),
[email protected]52657f62013-05-20 05:30:31221 (
tomhudsone2c14d552016-05-26 17:07:46222 'setMatrixClip',
223 (
224 'Overriding setMatrixClip() is prohibited; ',
225 'the base function is deprecated. ',
226 ),
227 True,
228 (),
229 ),
230 (
[email protected]52657f62013-05-20 05:30:31231 'SkRefPtr',
232 (
233 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22234 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31235 ),
236 True,
237 (),
238 ),
239 (
240 'SkAutoRef',
241 (
242 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22243 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31244 ),
245 True,
246 (),
247 ),
248 (
249 'SkAutoTUnref',
250 (
251 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22252 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31253 ),
254 True,
255 (),
256 ),
257 (
258 'SkAutoUnref',
259 (
260 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
261 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22262 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31263 ),
264 True,
265 (),
266 ),
[email protected]d89eec82013-12-03 14:10:59267 (
268 r'/HANDLE_EINTR\(.*close',
269 (
270 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
271 'descriptor will be closed, and it is incorrect to retry the close.',
272 'Either call close directly and ignore its return value, or wrap close',
273 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
274 ),
275 True,
276 (),
277 ),
278 (
279 r'/IGNORE_EINTR\((?!.*close)',
280 (
281 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
282 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
283 ),
284 True,
285 (
286 # Files that #define IGNORE_EINTR.
287 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
288 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
289 ),
290 ),
[email protected]ec5b3f02014-04-04 18:43:43291 (
292 r'/v8::Extension\(',
293 (
294 'Do not introduce new v8::Extensions into the code base, use',
295 'gin::Wrappable instead. See http://crbug.com/334679',
296 ),
297 True,
[email protected]f55c90ee62014-04-12 00:50:03298 (
joaodasilva718f87672014-08-30 09:25:49299 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03300 ),
[email protected]ec5b3f02014-04-04 18:43:43301 ),
skyostilf9469f72015-04-20 10:38:52302 (
jame2d1a952016-04-02 00:27:10303 '#pragma comment(lib,',
304 (
305 'Specify libraries to link with in build files and not in the source.',
306 ),
307 True,
308 (),
309 ),
dcheng8f0694bae2016-10-12 15:58:15310 (
311 r'FOR_EACH_OBSERVER(',
312 (
313 'Use range-based for loops to iterate through base::ObserverList, e.g.',
314 ' for (auto& observer : observers) { observer.Observe(); }',
315 ),
316 True,
317 (),
318 ),
[email protected]127f18ec2012-06-16 05:05:59319)
320
wnwenbdc444e2016-05-25 13:44:15321
mlamouria82272622014-09-16 18:45:04322_IPC_ENUM_TRAITS_DEPRECATED = (
323 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
324 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
325
[email protected]127f18ec2012-06-16 05:05:59326
[email protected]b00342e7f2013-03-26 16:21:54327_VALID_OS_MACROS = (
328 # Please keep sorted.
329 'OS_ANDROID',
330 'OS_BSD',
331 'OS_CAT', # For testing.
332 'OS_CHROMEOS',
333 'OS_FREEBSD',
334 'OS_IOS',
335 'OS_LINUX',
336 'OS_MACOSX',
337 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21338 'OS_NACL_NONSFI',
339 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12340 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54341 'OS_OPENBSD',
342 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37343 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54344 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54345 'OS_WIN',
346)
347
348
agrievef32bcc72016-04-04 14:57:40349_ANDROID_SPECIFIC_PYDEPS_FILES = [
350 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19351 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40352]
353
wnwenbdc444e2016-05-25 13:44:15354
agrievef32bcc72016-04-04 14:57:40355_GENERIC_PYDEPS_FILES = [
356 'build/secondary/tools/swarming_client/isolate.pydeps',
357]
358
wnwenbdc444e2016-05-25 13:44:15359
agrievef32bcc72016-04-04 14:57:40360_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
361
362
[email protected]55459852011-08-10 15:17:19363def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
364 """Attempts to prevent use of functions intended only for testing in
365 non-testing code. For now this is just a best-effort implementation
366 that ignores header files and may have some false positives. A
367 better implementation would probably need a proper C++ parser.
368 """
369 # We only scan .cc files and the like, as the declaration of
370 # for-testing functions in header files are hard to distinguish from
371 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44372 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19373
jochenc0d4808c2015-07-27 09:25:42374 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19375 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09376 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19377 exclusion_pattern = input_api.re.compile(
378 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
379 base_function_pattern, base_function_pattern))
380
381 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44382 black_list = (_EXCLUDED_PATHS +
383 _TEST_CODE_EXCLUDED_PATHS +
384 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19385 return input_api.FilterSourceFile(
386 affected_file,
387 white_list=(file_inclusion_pattern, ),
388 black_list=black_list)
389
390 problems = []
391 for f in input_api.AffectedSourceFiles(FilterFile):
392 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24393 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03394 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46395 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03396 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19397 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03398 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19399
400 if problems:
[email protected]f7051d52013-04-02 18:31:42401 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03402 else:
403 return []
[email protected]55459852011-08-10 15:17:19404
405
[email protected]10689ca2011-09-02 02:31:54406def _CheckNoIOStreamInHeaders(input_api, output_api):
407 """Checks to make sure no .h files include <iostream>."""
408 files = []
409 pattern = input_api.re.compile(r'^#include\s*<iostream>',
410 input_api.re.MULTILINE)
411 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
412 if not f.LocalPath().endswith('.h'):
413 continue
414 contents = input_api.ReadFile(f)
415 if pattern.search(contents):
416 files.append(f)
417
418 if len(files):
yolandyandaabc6d2016-04-18 18:29:39419 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06420 'Do not #include <iostream> in header files, since it inserts static '
421 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54422 '#include <ostream>. See http://crbug.com/94794',
423 files) ]
424 return []
425
426
[email protected]72df4e782012-06-21 16:28:18427def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52428 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18429 problems = []
430 for f in input_api.AffectedFiles():
431 if (not f.LocalPath().endswith(('.cc', '.mm'))):
432 continue
433
434 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04435 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18436 problems.append(' %s:%d' % (f.LocalPath(), line_num))
437
438 if not problems:
439 return []
440 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
441 '\n'.join(problems))]
442
443
danakj61c1aa22015-10-26 19:55:52444def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
445 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
446 errors = []
447 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
448 input_api.re.MULTILINE)
449 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
450 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
451 continue
452 for lnum, line in f.ChangedContents():
453 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17454 errors.append(output_api.PresubmitError(
455 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
456 'DCHECK_IS_ON()", not forgetting the braces.')
457 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52458 return errors
459
460
mcasasb7440c282015-02-04 14:52:19461def _FindHistogramNameInLine(histogram_name, line):
462 """Tries to find a histogram name or prefix in a line."""
463 if not "affected-histogram" in line:
464 return histogram_name in line
465 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
466 # the histogram_name.
467 if not '"' in line:
468 return False
469 histogram_prefix = line.split('\"')[1]
470 return histogram_prefix in histogram_name
471
472
473def _CheckUmaHistogramChanges(input_api, output_api):
474 """Check that UMA histogram names in touched lines can still be found in other
475 lines of the patch or in histograms.xml. Note that this check would not catch
476 the reverse: changes in histograms.xml not matched in the code itself."""
477 touched_histograms = []
478 histograms_xml_modifications = []
479 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
480 for f in input_api.AffectedFiles():
481 # If histograms.xml itself is modified, keep the modified lines for later.
482 if f.LocalPath().endswith(('histograms.xml')):
483 histograms_xml_modifications = f.ChangedContents()
484 continue
485 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
486 continue
487 for line_num, line in f.ChangedContents():
488 found = pattern.search(line)
489 if found:
490 touched_histograms.append([found.group(1), f, line_num])
491
492 # Search for the touched histogram names in the local modifications to
493 # histograms.xml, and, if not found, on the base histograms.xml file.
494 unmatched_histograms = []
495 for histogram_info in touched_histograms:
496 histogram_name_found = False
497 for line_num, line in histograms_xml_modifications:
498 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
499 if histogram_name_found:
500 break
501 if not histogram_name_found:
502 unmatched_histograms.append(histogram_info)
503
eromanb90c82e7e32015-04-01 15:13:49504 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19505 problems = []
506 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49507 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19508 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45509 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19510 histogram_name_found = False
511 for line in histograms_xml:
512 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
513 if histogram_name_found:
514 break
515 if not histogram_name_found:
516 problems.append(' [%s:%d] %s' %
517 (f.LocalPath(), line_num, histogram_name))
518
519 if not problems:
520 return []
521 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
522 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49523 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19524
wnwenbdc444e2016-05-25 13:44:15525
yolandyandaabc6d2016-04-18 18:29:39526def _CheckFlakyTestUsage(input_api, output_api):
527 """Check that FlakyTest annotation is our own instead of the android one"""
528 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
529 files = []
530 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
531 if f.LocalPath().endswith('Test.java'):
532 if pattern.search(input_api.ReadFile(f)):
533 files.append(f)
534 if len(files):
535 return [output_api.PresubmitError(
536 'Use org.chromium.base.test.util.FlakyTest instead of '
537 'android.test.FlakyTest',
538 files)]
539 return []
mcasasb7440c282015-02-04 14:52:19540
wnwenbdc444e2016-05-25 13:44:15541
[email protected]8ea5d4b2011-09-13 21:49:22542def _CheckNoNewWStrings(input_api, output_api):
543 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27544 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22545 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20546 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57547 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34548 '/win/' in f.LocalPath() or
549 'chrome_elf' in f.LocalPath() or
550 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20551 continue
[email protected]8ea5d4b2011-09-13 21:49:22552
[email protected]a11dbe9b2012-08-07 01:32:58553 allowWString = False
[email protected]b5c24292011-11-28 14:38:20554 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58555 if 'presubmit: allow wstring' in line:
556 allowWString = True
557 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27558 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58559 allowWString = False
560 else:
561 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22562
[email protected]55463aa62011-10-12 00:48:27563 if not problems:
564 return []
565 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58566 ' If you are calling a cross-platform API that accepts a wstring, '
567 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27568 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22569
570
[email protected]2a8ac9c2011-10-19 17:20:44571def _CheckNoDEPSGIT(input_api, output_api):
572 """Make sure .DEPS.git is never modified manually."""
573 if any(f.LocalPath().endswith('.DEPS.git') for f in
574 input_api.AffectedFiles()):
575 return [output_api.PresubmitError(
576 'Never commit changes to .DEPS.git. This file is maintained by an\n'
577 'automated system based on what\'s in DEPS and your changes will be\n'
578 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34579 '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:44580 'for more information')]
581 return []
582
583
tandriief664692014-09-23 14:51:47584def _CheckValidHostsInDEPS(input_api, output_api):
585 """Checks that DEPS file deps are from allowed_hosts."""
586 # Run only if DEPS file has been modified to annoy fewer bystanders.
587 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
588 return []
589 # Outsource work to gclient verify
590 try:
591 input_api.subprocess.check_output(['gclient', 'verify'])
592 return []
593 except input_api.subprocess.CalledProcessError, error:
594 return [output_api.PresubmitError(
595 'DEPS file must have only git dependencies.',
596 long_text=error.output)]
597
598
[email protected]127f18ec2012-06-16 05:05:59599def _CheckNoBannedFunctions(input_api, output_api):
600 """Make sure that banned functions are not used."""
601 warnings = []
602 errors = []
603
wnwenbdc444e2016-05-25 13:44:15604 def IsBlacklisted(affected_file, blacklist):
605 local_path = affected_file.LocalPath()
606 for item in blacklist:
607 if input_api.re.match(item, local_path):
608 return True
609 return False
610
611 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
612 matched = False
613 if func_name[0:1] == '/':
614 regex = func_name[1:]
615 if input_api.re.search(regex, line):
616 matched = True
617 elif func_name in line:
dchenge07de812016-06-20 19:27:17618 matched = True
wnwenbdc444e2016-05-25 13:44:15619 if matched:
dchenge07de812016-06-20 19:27:17620 problems = warnings
wnwenbdc444e2016-05-25 13:44:15621 if error:
dchenge07de812016-06-20 19:27:17622 problems = errors
wnwenbdc444e2016-05-25 13:44:15623 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
624 for message_line in message:
625 problems.append(' %s' % message_line)
626
[email protected]127f18ec2012-06-16 05:05:59627 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
628 for f in input_api.AffectedFiles(file_filter=file_filter):
629 for line_num, line in f.ChangedContents():
630 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15631 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59632
633 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
634 for f in input_api.AffectedFiles(file_filter=file_filter):
635 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49636 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49637 if IsBlacklisted(f, excluded_paths):
638 continue
wnwenbdc444e2016-05-25 13:44:15639 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59640
641 result = []
642 if (warnings):
643 result.append(output_api.PresubmitPromptWarning(
644 'Banned functions were used.\n' + '\n'.join(warnings)))
645 if (errors):
646 result.append(output_api.PresubmitError(
647 'Banned functions were used.\n' + '\n'.join(errors)))
648 return result
649
650
[email protected]6c063c62012-07-11 19:11:06651def _CheckNoPragmaOnce(input_api, output_api):
652 """Make sure that banned functions are not used."""
653 files = []
654 pattern = input_api.re.compile(r'^#pragma\s+once',
655 input_api.re.MULTILINE)
656 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
657 if not f.LocalPath().endswith('.h'):
658 continue
659 contents = input_api.ReadFile(f)
660 if pattern.search(contents):
661 files.append(f)
662
663 if files:
664 return [output_api.PresubmitError(
665 'Do not use #pragma once in header files.\n'
666 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
667 files)]
668 return []
669
[email protected]127f18ec2012-06-16 05:05:59670
[email protected]e7479052012-09-19 00:26:12671def _CheckNoTrinaryTrueFalse(input_api, output_api):
672 """Checks to make sure we don't introduce use of foo ? true : false."""
673 problems = []
674 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
675 for f in input_api.AffectedFiles():
676 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
677 continue
678
679 for line_num, line in f.ChangedContents():
680 if pattern.match(line):
681 problems.append(' %s:%d' % (f.LocalPath(), line_num))
682
683 if not problems:
684 return []
685 return [output_api.PresubmitPromptWarning(
686 'Please consider avoiding the "? true : false" pattern if possible.\n' +
687 '\n'.join(problems))]
688
689
[email protected]55f9f382012-07-31 11:02:18690def _CheckUnwantedDependencies(input_api, output_api):
691 """Runs checkdeps on #include statements added in this
692 change. Breaking - rules is an error, breaking ! rules is a
693 warning.
694 """
mohan.reddyf21db962014-10-16 12:26:47695 import sys
[email protected]55f9f382012-07-31 11:02:18696 # We need to wait until we have an input_api object and use this
697 # roundabout construct to import checkdeps because this file is
698 # eval-ed and thus doesn't have __file__.
699 original_sys_path = sys.path
700 try:
701 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47702 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18703 import checkdeps
704 from cpp_checker import CppChecker
705 from rules import Rule
706 finally:
707 # Restore sys.path to what it was before.
708 sys.path = original_sys_path
709
710 added_includes = []
711 for f in input_api.AffectedFiles():
712 if not CppChecker.IsCppFile(f.LocalPath()):
713 continue
714
715 changed_lines = [line for line_num, line in f.ChangedContents()]
716 added_includes.append([f.LocalPath(), changed_lines])
717
[email protected]26385172013-05-09 23:11:35718 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18719
720 error_descriptions = []
721 warning_descriptions = []
722 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
723 added_includes):
724 description_with_path = '%s\n %s' % (path, rule_description)
725 if rule_type == Rule.DISALLOW:
726 error_descriptions.append(description_with_path)
727 else:
728 warning_descriptions.append(description_with_path)
729
730 results = []
731 if error_descriptions:
732 results.append(output_api.PresubmitError(
733 'You added one or more #includes that violate checkdeps rules.',
734 error_descriptions))
735 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42736 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18737 'You added one or more #includes of files that are temporarily\n'
738 'allowed but being removed. Can you avoid introducing the\n'
739 '#include? See relevant DEPS file(s) for details and contacts.',
740 warning_descriptions))
741 return results
742
743
[email protected]fbcafe5a2012-08-08 15:31:22744def _CheckFilePermissions(input_api, output_api):
745 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15746 if input_api.platform == 'win32':
747 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29748 checkperms_tool = input_api.os_path.join(
749 input_api.PresubmitLocalPath(),
750 'tools', 'checkperms', 'checkperms.py')
751 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47752 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22753 for f in input_api.AffectedFiles():
754 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11755 try:
756 input_api.subprocess.check_output(args)
757 return []
758 except input_api.subprocess.CalledProcessError as error:
759 return [output_api.PresubmitError(
760 'checkperms.py failed:',
761 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22762
763
[email protected]c8278b32012-10-30 20:35:49764def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
765 """Makes sure we don't include ui/aura/window_property.h
766 in header files.
767 """
768 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
769 errors = []
770 for f in input_api.AffectedFiles():
771 if not f.LocalPath().endswith('.h'):
772 continue
773 for line_num, line in f.ChangedContents():
774 if pattern.match(line):
775 errors.append(' %s:%d' % (f.LocalPath(), line_num))
776
777 results = []
778 if errors:
779 results.append(output_api.PresubmitError(
780 'Header files should not include ui/aura/window_property.h', errors))
781 return results
782
783
[email protected]cf9b78f2012-11-14 11:40:28784def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
785 """Checks that the lines in scope occur in the right order.
786
787 1. C system files in alphabetical order
788 2. C++ system files in alphabetical order
789 3. Project's .h files
790 """
791
792 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
793 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
794 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
795
796 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
797
798 state = C_SYSTEM_INCLUDES
799
800 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57801 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28802 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55803 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28804 for line_num, line in scope:
805 if c_system_include_pattern.match(line):
806 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55807 problem_linenums.append((line_num, previous_line_num,
808 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28809 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55810 problem_linenums.append((line_num, previous_line_num,
811 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28812 elif cpp_system_include_pattern.match(line):
813 if state == C_SYSTEM_INCLUDES:
814 state = CPP_SYSTEM_INCLUDES
815 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55816 problem_linenums.append((line_num, previous_line_num,
817 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28818 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55819 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28820 elif custom_include_pattern.match(line):
821 if state != CUSTOM_INCLUDES:
822 state = CUSTOM_INCLUDES
823 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55824 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28825 else:
brucedawson70fadb02015-06-30 17:47:55826 problem_linenums.append((line_num, previous_line_num,
827 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28828 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57829 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28830
831 warnings = []
brucedawson70fadb02015-06-30 17:47:55832 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57833 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55834 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28835 return warnings
836
837
[email protected]ac294a12012-12-06 16:38:43838def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28839 """Checks the #include order for the given file f."""
840
[email protected]2299dcf2012-11-15 19:56:24841 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30842 # Exclude the following includes from the check:
843 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
844 # specific order.
845 # 2) <atlbase.h>, "build/build_config.h"
846 excluded_include_pattern = input_api.re.compile(
847 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24848 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33849 # Match the final or penultimate token if it is xxxtest so we can ignore it
850 # when considering the special first include.
851 test_file_tag_pattern = input_api.re.compile(
852 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11853 if_pattern = input_api.re.compile(
854 r'\s*#\s*(if|elif|else|endif|define|undef).*')
855 # Some files need specialized order of includes; exclude such files from this
856 # check.
857 uncheckable_includes_pattern = input_api.re.compile(
858 r'\s*#include '
859 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28860
861 contents = f.NewContents()
862 warnings = []
863 line_num = 0
864
[email protected]ac294a12012-12-06 16:38:43865 # Handle the special first include. If the first include file is
866 # some/path/file.h, the corresponding including file can be some/path/file.cc,
867 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
868 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33869 # If the included file is some/path/file_platform.h the including file could
870 # also be some/path/file_xxxtest_platform.h.
871 including_file_base_name = test_file_tag_pattern.sub(
872 '', input_api.os_path.basename(f.LocalPath()))
873
[email protected]ac294a12012-12-06 16:38:43874 for line in contents:
875 line_num += 1
876 if system_include_pattern.match(line):
877 # No special first include -> process the line again along with normal
878 # includes.
879 line_num -= 1
880 break
881 match = custom_include_pattern.match(line)
882 if match:
883 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33884 header_basename = test_file_tag_pattern.sub(
885 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
886
887 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24888 # No special first include -> process the line again along with normal
889 # includes.
890 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43891 break
[email protected]cf9b78f2012-11-14 11:40:28892
893 # Split into scopes: Each region between #if and #endif is its own scope.
894 scopes = []
895 current_scope = []
896 for line in contents[line_num:]:
897 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11898 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54899 continue
[email protected]2309b0fa02012-11-16 12:18:27900 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28901 scopes.append(current_scope)
902 current_scope = []
[email protected]962f117e2012-11-22 18:11:56903 elif ((system_include_pattern.match(line) or
904 custom_include_pattern.match(line)) and
905 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28906 current_scope.append((line_num, line))
907 scopes.append(current_scope)
908
909 for scope in scopes:
910 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
911 changed_linenums))
912 return warnings
913
914
915def _CheckIncludeOrder(input_api, output_api):
916 """Checks that the #include order is correct.
917
918 1. The corresponding header for source files.
919 2. C system files in alphabetical order
920 3. C++ system files in alphabetical order
921 4. Project's .h files in alphabetical order
922
[email protected]ac294a12012-12-06 16:38:43923 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
924 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28925 """
[email protected]e120b012014-08-15 19:08:35926 def FileFilterIncludeOrder(affected_file):
927 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
928 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28929
930 warnings = []
[email protected]e120b012014-08-15 19:08:35931 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08932 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43933 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
934 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28935
936 results = []
937 if warnings:
[email protected]f7051d52013-04-02 18:31:42938 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53939 warnings))
[email protected]cf9b78f2012-11-14 11:40:28940 return results
941
942
[email protected]70ca77752012-11-20 03:45:03943def _CheckForVersionControlConflictsInFile(input_api, f):
944 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
945 errors = []
946 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23947 if f.LocalPath().endswith('.md'):
948 # First-level headers in markdown look a lot like version control
949 # conflict markers. http://daringfireball.net/projects/markdown/basics
950 continue
[email protected]70ca77752012-11-20 03:45:03951 if pattern.match(line):
952 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
953 return errors
954
955
956def _CheckForVersionControlConflicts(input_api, output_api):
957 """Usually this is not intentional and will cause a compile failure."""
958 errors = []
959 for f in input_api.AffectedFiles():
960 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
961
962 results = []
963 if errors:
964 results.append(output_api.PresubmitError(
965 'Version control conflict markers found, please resolve.', errors))
966 return results
967
968
[email protected]06e6d0ff2012-12-11 01:36:44969def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
970 def FilterFile(affected_file):
971 """Filter function for use with input_api.AffectedSourceFiles,
972 below. This filters out everything except non-test files from
973 top-level directories that generally speaking should not hard-code
974 service URLs (e.g. src/android_webview/, src/content/ and others).
975 """
976 return input_api.FilterSourceFile(
977 affected_file,
[email protected]78bb39d62012-12-11 15:11:56978 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44979 black_list=(_EXCLUDED_PATHS +
980 _TEST_CODE_EXCLUDED_PATHS +
981 input_api.DEFAULT_BLACK_LIST))
982
reillyi38965732015-11-16 18:27:33983 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
984 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46985 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
986 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44987 problems = [] # items are (filename, line_number, line)
988 for f in input_api.AffectedSourceFiles(FilterFile):
989 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46990 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44991 problems.append((f.LocalPath(), line_num, line))
992
993 if problems:
[email protected]f7051d52013-04-02 18:31:42994 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44995 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58996 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44997 [' %s:%d: %s' % (
998 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03999 else:
1000 return []
[email protected]06e6d0ff2012-12-11 01:36:441001
1002
[email protected]d2530012013-01-25 16:39:271003def _CheckNoAbbreviationInPngFileName(input_api, output_api):
1004 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:311005 The native_client_sdk directory is excluded because it has auto-generated PNG
1006 files for documentation.
[email protected]d2530012013-01-25 16:39:271007 """
[email protected]d2530012013-01-25 16:39:271008 errors = []
binji0dcdf342014-12-12 18:32:311009 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1010 black_list = (r'^native_client_sdk[\\\/]',)
1011 file_filter = lambda f: input_api.FilterSourceFile(
1012 f, white_list=white_list, black_list=black_list)
1013 for f in input_api.AffectedFiles(include_deletes=False,
1014 file_filter=file_filter):
1015 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271016
1017 results = []
1018 if errors:
1019 results.append(output_api.PresubmitError(
1020 'The name of PNG files should not have abbreviations. \n'
1021 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1022 'Contact [email protected] if you have questions.', errors))
1023 return results
1024
1025
[email protected]14a6131c2014-01-08 01:15:411026def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081027 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411028 a set of DEPS entries that we should look up.
1029
1030 For a directory (rather than a specific filename) we fake a path to
1031 a specific filename by adding /DEPS. This is chosen as a file that
1032 will seldom or never be subject to per-file include_rules.
1033 """
[email protected]2b438d62013-11-14 17:54:141034 # We ignore deps entries on auto-generated directories.
1035 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081036
1037 # This pattern grabs the path without basename in the first
1038 # parentheses, and the basename (if present) in the second. It
1039 # relies on the simple heuristic that if there is a basename it will
1040 # be a header file ending in ".h".
1041 pattern = re.compile(
1042 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141043 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081044 for changed_line in changed_lines:
1045 m = pattern.match(changed_line)
1046 if m:
1047 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141048 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411049 if m.group(2):
1050 results.add('%s%s' % (path, m.group(2)))
1051 else:
1052 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081053 return results
1054
1055
[email protected]e871964c2013-05-13 14:14:551056def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1057 """When a dependency prefixed with + is added to a DEPS file, we
1058 want to make sure that the change is reviewed by an OWNER of the
1059 target file or directory, to avoid layering violations from being
1060 introduced. This check verifies that this happens.
1061 """
1062 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241063
1064 file_filter = lambda f: not input_api.re.match(
1065 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1066 for f in input_api.AffectedFiles(include_deletes=False,
1067 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551068 filename = input_api.os_path.basename(f.LocalPath())
1069 if filename == 'DEPS':
1070 changed_lines |= set(line.strip()
1071 for line_num, line
1072 in f.ChangedContents())
1073 if not changed_lines:
1074 return []
1075
[email protected]14a6131c2014-01-08 01:15:411076 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1077 changed_lines)
[email protected]e871964c2013-05-13 14:14:551078 if not virtual_depended_on_files:
1079 return []
1080
1081 if input_api.is_committing:
1082 if input_api.tbr:
1083 return [output_api.PresubmitNotifyResult(
1084 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271085 if input_api.dry_run:
1086 return [output_api.PresubmitNotifyResult(
1087 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551088 if not input_api.change.issue:
1089 return [output_api.PresubmitError(
1090 "DEPS approval by OWNERS check failed: this change has "
1091 "no Rietveld issue number, so we can't check it for approvals.")]
1092 output = output_api.PresubmitError
1093 else:
1094 output = output_api.PresubmitNotifyResult
1095
1096 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501097 owner_email, reviewers = (
1098 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1099 input_api,
1100 owners_db.email_regexp,
1101 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551102
1103 owner_email = owner_email or input_api.change.author_email
1104
[email protected]de4f7d22013-05-23 14:27:461105 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511106 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461107 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551108 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1109 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411110
1111 # We strip the /DEPS part that was added by
1112 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1113 # directory.
1114 def StripDeps(path):
1115 start_deps = path.rfind('/DEPS')
1116 if start_deps != -1:
1117 return path[:start_deps]
1118 else:
1119 return path
1120 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551121 for path in missing_files]
1122
1123 if unapproved_dependencies:
1124 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151125 output('You need LGTM from owners of depends-on paths in DEPS that were '
1126 'modified in this CL:\n %s' %
1127 '\n '.join(sorted(unapproved_dependencies)))]
1128 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1129 output_list.append(output(
1130 'Suggested missing target path OWNERS:\n %s' %
1131 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551132 return output_list
1133
1134 return []
1135
1136
[email protected]85218562013-11-22 07:41:401137def _CheckSpamLogging(input_api, output_api):
1138 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1139 black_list = (_EXCLUDED_PATHS +
1140 _TEST_CODE_EXCLUDED_PATHS +
1141 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501142 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191143 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481144 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461145 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121146 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1147 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581148 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161149 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031150 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151151 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1152 r"^chromecast[\\\/]",
1153 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311154 r"^components[\\\/]html_viewer[\\\/]"
1155 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461156 # TODO(peter): Remove this exception. https://crbug.com/534537
1157 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1158 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251159 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1160 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241161 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111162 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151163 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111164 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521165 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501166 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361167 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311168 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131169 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441170 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451171 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021172 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441173 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401174 source_file_filter = lambda x: input_api.FilterSourceFile(
1175 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1176
1177 log_info = []
1178 printf = []
1179
1180 for f in input_api.AffectedSourceFiles(source_file_filter):
1181 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471182 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401183 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471184 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131185 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371186
mohan.reddyf21db962014-10-16 12:26:471187 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371188 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471189 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401190 printf.append(f.LocalPath())
1191
1192 if log_info:
1193 return [output_api.PresubmitError(
1194 'These files spam the console log with LOG(INFO):',
1195 items=log_info)]
1196 if printf:
1197 return [output_api.PresubmitError(
1198 'These files spam the console log with printf/fprintf:',
1199 items=printf)]
1200 return []
1201
1202
[email protected]49aa76a2013-12-04 06:59:161203def _CheckForAnonymousVariables(input_api, output_api):
1204 """These types are all expected to hold locks while in scope and
1205 so should never be anonymous (which causes them to be immediately
1206 destroyed)."""
1207 they_who_must_be_named = [
1208 'base::AutoLock',
1209 'base::AutoReset',
1210 'base::AutoUnlock',
1211 'SkAutoAlphaRestore',
1212 'SkAutoBitmapShaderInstall',
1213 'SkAutoBlitterChoose',
1214 'SkAutoBounderCommit',
1215 'SkAutoCallProc',
1216 'SkAutoCanvasRestore',
1217 'SkAutoCommentBlock',
1218 'SkAutoDescriptor',
1219 'SkAutoDisableDirectionCheck',
1220 'SkAutoDisableOvalCheck',
1221 'SkAutoFree',
1222 'SkAutoGlyphCache',
1223 'SkAutoHDC',
1224 'SkAutoLockColors',
1225 'SkAutoLockPixels',
1226 'SkAutoMalloc',
1227 'SkAutoMaskFreeImage',
1228 'SkAutoMutexAcquire',
1229 'SkAutoPathBoundsUpdate',
1230 'SkAutoPDFRelease',
1231 'SkAutoRasterClipValidate',
1232 'SkAutoRef',
1233 'SkAutoTime',
1234 'SkAutoTrace',
1235 'SkAutoUnref',
1236 ]
1237 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1238 # bad: base::AutoLock(lock.get());
1239 # not bad: base::AutoLock lock(lock.get());
1240 bad_pattern = input_api.re.compile(anonymous)
1241 # good: new base::AutoLock(lock.get())
1242 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1243 errors = []
1244
1245 for f in input_api.AffectedFiles():
1246 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1247 continue
1248 for linenum, line in f.ChangedContents():
1249 if bad_pattern.search(line) and not good_pattern.search(line):
1250 errors.append('%s:%d' % (f.LocalPath(), linenum))
1251
1252 if errors:
1253 return [output_api.PresubmitError(
1254 'These lines create anonymous variables that need to be named:',
1255 items=errors)]
1256 return []
1257
1258
[email protected]5fe0f8742013-11-29 01:04:591259def _CheckCygwinShell(input_api, output_api):
1260 source_file_filter = lambda x: input_api.FilterSourceFile(
1261 x, white_list=(r'.+\.(gyp|gypi)$',))
1262 cygwin_shell = []
1263
1264 for f in input_api.AffectedSourceFiles(source_file_filter):
1265 for linenum, line in f.ChangedContents():
1266 if 'msvs_cygwin_shell' in line:
1267 cygwin_shell.append(f.LocalPath())
1268 break
1269
1270 if cygwin_shell:
1271 return [output_api.PresubmitError(
1272 'These files should not use msvs_cygwin_shell (the default is 0):',
1273 items=cygwin_shell)]
1274 return []
1275
[email protected]85218562013-11-22 07:41:401276
[email protected]999261d2014-03-03 20:08:081277def _CheckUserActionUpdate(input_api, output_api):
1278 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521279 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081280 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521281 # If actions.xml is already included in the changelist, the PRESUBMIT
1282 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081283 return []
1284
[email protected]999261d2014-03-03 20:08:081285 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1286 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521287 current_actions = None
[email protected]999261d2014-03-03 20:08:081288 for f in input_api.AffectedFiles(file_filter=file_filter):
1289 for line_num, line in f.ChangedContents():
1290 match = input_api.re.search(action_re, line)
1291 if match:
[email protected]2f92dec2014-03-07 19:21:521292 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1293 # loaded only once.
1294 if not current_actions:
1295 with open('tools/metrics/actions/actions.xml') as actions_f:
1296 current_actions = actions_f.read()
1297 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081298 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521299 action = 'name="{0}"'.format(action_name)
1300 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081301 return [output_api.PresubmitPromptWarning(
1302 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521303 'tools/metrics/actions/actions.xml. Please run '
1304 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081305 % (f.LocalPath(), line_num, action_name))]
1306 return []
1307
1308
[email protected]99171a92014-06-03 08:44:471309def _GetJSONParseError(input_api, filename, eat_comments=True):
1310 try:
1311 contents = input_api.ReadFile(filename)
1312 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131313 import sys
1314 original_sys_path = sys.path
1315 try:
1316 sys.path = sys.path + [input_api.os_path.join(
1317 input_api.PresubmitLocalPath(),
1318 'tools', 'json_comment_eater')]
1319 import json_comment_eater
1320 finally:
1321 sys.path = original_sys_path
1322 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471323
1324 input_api.json.loads(contents)
1325 except ValueError as e:
1326 return e
1327 return None
1328
1329
1330def _GetIDLParseError(input_api, filename):
1331 try:
1332 contents = input_api.ReadFile(filename)
1333 idl_schema = input_api.os_path.join(
1334 input_api.PresubmitLocalPath(),
1335 'tools', 'json_schema_compiler', 'idl_schema.py')
1336 process = input_api.subprocess.Popen(
1337 [input_api.python_executable, idl_schema],
1338 stdin=input_api.subprocess.PIPE,
1339 stdout=input_api.subprocess.PIPE,
1340 stderr=input_api.subprocess.PIPE,
1341 universal_newlines=True)
1342 (_, error) = process.communicate(input=contents)
1343 return error or None
1344 except ValueError as e:
1345 return e
1346
1347
1348def _CheckParseErrors(input_api, output_api):
1349 """Check that IDL and JSON files do not contain syntax errors."""
1350 actions = {
1351 '.idl': _GetIDLParseError,
1352 '.json': _GetJSONParseError,
1353 }
1354 # These paths contain test data and other known invalid JSON files.
1355 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491356 r'test[\\\/]data[\\\/]',
1357 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471358 ]
1359 # Most JSON files are preprocessed and support comments, but these do not.
1360 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491361 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471362 ]
1363 # Only run IDL checker on files in these directories.
1364 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491365 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1366 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471367 ]
1368
1369 def get_action(affected_file):
1370 filename = affected_file.LocalPath()
1371 return actions.get(input_api.os_path.splitext(filename)[1])
1372
1373 def MatchesFile(patterns, path):
1374 for pattern in patterns:
1375 if input_api.re.search(pattern, path):
1376 return True
1377 return False
1378
1379 def FilterFile(affected_file):
1380 action = get_action(affected_file)
1381 if not action:
1382 return False
1383 path = affected_file.LocalPath()
1384
1385 if MatchesFile(excluded_patterns, path):
1386 return False
1387
1388 if (action == _GetIDLParseError and
1389 not MatchesFile(idl_included_patterns, path)):
1390 return False
1391 return True
1392
1393 results = []
1394 for affected_file in input_api.AffectedFiles(
1395 file_filter=FilterFile, include_deletes=False):
1396 action = get_action(affected_file)
1397 kwargs = {}
1398 if (action == _GetJSONParseError and
1399 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1400 kwargs['eat_comments'] = False
1401 parse_error = action(input_api,
1402 affected_file.AbsoluteLocalPath(),
1403 **kwargs)
1404 if parse_error:
1405 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1406 (affected_file.LocalPath(), parse_error)))
1407 return results
1408
1409
[email protected]760deea2013-12-10 19:33:491410def _CheckJavaStyle(input_api, output_api):
1411 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471412 import sys
[email protected]760deea2013-12-10 19:33:491413 original_sys_path = sys.path
1414 try:
1415 sys.path = sys.path + [input_api.os_path.join(
1416 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1417 import checkstyle
1418 finally:
1419 # Restore sys.path to what it was before.
1420 sys.path = original_sys_path
1421
1422 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091423 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511424 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491425
1426
dchenge07de812016-06-20 19:27:171427def _CheckIpcOwners(input_api, output_api):
1428 """Checks that affected files involving IPC have an IPC OWNERS rule.
1429
1430 Whether or not a file affects IPC is determined by a simple whitelist of
1431 filename patterns."""
1432 file_patterns = [
1433 '*_messages.cc',
1434 '*_messages*.h',
1435 '*_param_traits*.*',
1436 '*.mojom',
1437 '*_struct_traits*.*',
1438 '*_type_converter*.*',
1439 # Blink uses a different file naming convention
1440 '*StructTraits*.*',
1441 '*TypeConverter*.*',
1442 ]
1443
1444 # Dictionary mapping an OWNERS file path to Patterns.
1445 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1446 # rules ) to a PatternEntry.
1447 # PatternEntry is a dictionary with two keys:
1448 # - 'files': the files that are matched by this pattern
1449 # - 'rules': the per-file rules needed for this pattern
1450 # For example, if we expect OWNERS file to contain rules for *.mojom and
1451 # *_struct_traits*.*, Patterns might look like this:
1452 # {
1453 # '*.mojom': {
1454 # 'files': ...,
1455 # 'rules': [
1456 # 'per-file *.mojom=set noparent',
1457 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1458 # ],
1459 # },
1460 # '*_struct_traits*.*': {
1461 # 'files': ...,
1462 # 'rules': [
1463 # 'per-file *_struct_traits*.*=set noparent',
1464 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1465 # ],
1466 # },
1467 # }
1468 to_check = {}
1469
1470 # Iterate through the affected files to see what we actually need to check
1471 # for. We should only nag patch authors about per-file rules if a file in that
1472 # directory would match that pattern. If a directory only contains *.mojom
1473 # files and no *_messages*.h files, we should only nag about rules for
1474 # *.mojom files.
rockot51249332016-06-23 16:32:251475 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171476 for pattern in file_patterns:
1477 if input_api.fnmatch.fnmatch(
1478 input_api.os_path.basename(f.LocalPath()), pattern):
1479 owners_file = input_api.os_path.join(
1480 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1481 if owners_file not in to_check:
1482 to_check[owners_file] = {}
1483 if pattern not in to_check[owners_file]:
1484 to_check[owners_file][pattern] = {
1485 'files': [],
1486 'rules': [
1487 'per-file %s=set noparent' % pattern,
1488 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1489 ]
1490 }
1491 to_check[owners_file][pattern]['files'].append(f)
1492 break
1493
1494 # Now go through the OWNERS files we collected, filtering out rules that are
1495 # already present in that OWNERS file.
1496 for owners_file, patterns in to_check.iteritems():
1497 try:
1498 with file(owners_file) as f:
1499 lines = set(f.read().splitlines())
1500 for entry in patterns.itervalues():
1501 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1502 ]
1503 except IOError:
1504 # No OWNERS file, so all the rules are definitely missing.
1505 continue
1506
1507 # All the remaining lines weren't found in OWNERS files, so emit an error.
1508 errors = []
1509 for owners_file, patterns in to_check.iteritems():
1510 missing_lines = []
1511 files = []
1512 for pattern, entry in patterns.iteritems():
1513 missing_lines.extend(entry['rules'])
1514 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1515 if missing_lines:
1516 errors.append(
1517 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1518 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1519
1520 results = []
1521 if errors:
vabrf5ce3bf92016-07-11 14:52:411522 if input_api.is_committing:
1523 output = output_api.PresubmitError
1524 else:
1525 output = output_api.PresubmitPromptWarning
1526 results.append(output(
dchenge07de812016-06-20 19:27:171527 'Found changes to IPC files without a security OWNER!',
1528 long_text='\n\n'.join(errors)))
1529
1530 return results
1531
1532
yzshend99f726a2016-07-25 21:44:231533def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1534 """Checks to make sure that all newly added mojom targets map array/map/string
1535 to STL (for chromium) or WTF (for blink) types.
1536 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1537 """
1538 files = []
1539 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1540 input_api.re.MULTILINE)
1541
1542 for f in input_api.AffectedFiles():
1543 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1544 continue
1545
1546 for _, line in f.ChangedContents():
1547 if pattern.search(line):
1548 files.append(f)
1549 break
1550
1551 if len(files):
1552 return [output_api.PresubmitError(
1553 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1554 'false. The mode is deprecated and will be removed soon.',
1555 files)]
1556 return []
1557
1558
dskiba88634f4e2015-08-14 23:03:291559def _CheckAndroidToastUsage(input_api, output_api):
1560 """Checks that code uses org.chromium.ui.widget.Toast instead of
1561 android.widget.Toast (Chromium Toast doesn't force hardware
1562 acceleration on low-end devices, saving memory).
1563 """
1564 toast_import_pattern = input_api.re.compile(
1565 r'^import android\.widget\.Toast;$')
1566
1567 errors = []
1568
1569 sources = lambda affected_file: input_api.FilterSourceFile(
1570 affected_file,
1571 black_list=(_EXCLUDED_PATHS +
1572 _TEST_CODE_EXCLUDED_PATHS +
1573 input_api.DEFAULT_BLACK_LIST +
1574 (r'^chromecast[\\\/].*',
1575 r'^remoting[\\\/].*')),
1576 white_list=(r'.*\.java$',))
1577
1578 for f in input_api.AffectedSourceFiles(sources):
1579 for line_num, line in f.ChangedContents():
1580 if toast_import_pattern.search(line):
1581 errors.append("%s:%d" % (f.LocalPath(), line_num))
1582
1583 results = []
1584
1585 if errors:
1586 results.append(output_api.PresubmitError(
1587 'android.widget.Toast usage is detected. Android toasts use hardware'
1588 ' acceleration, and can be\ncostly on low-end devices. Please use'
1589 ' org.chromium.ui.widget.Toast instead.\n'
1590 'Contact [email protected] if you have any questions.',
1591 errors))
1592
1593 return results
1594
1595
dgnaa68d5e2015-06-10 10:08:221596def _CheckAndroidCrLogUsage(input_api, output_api):
1597 """Checks that new logs using org.chromium.base.Log:
1598 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511599 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221600 """
pkotwicza1dd0b002016-05-16 14:41:041601
1602 # Do not check format of logs in //chrome/android/webapk because
1603 # //chrome/android/webapk cannot depend on //base
1604 cr_log_check_excluded_paths = [
1605 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1606 ]
1607
dgnaa68d5e2015-06-10 10:08:221608 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121609 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1610 class_in_base_pattern = input_api.re.compile(
1611 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1612 has_some_log_import_pattern = input_api.re.compile(
1613 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221614 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121615 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221616 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511617 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221618 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221619
Vincent Scheib16d7b272015-09-15 18:09:071620 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221621 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041622 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1623 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121624
dgnaa68d5e2015-06-10 10:08:221625 tag_decl_errors = []
1626 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121627 tag_errors = []
dgn38736db2015-09-18 19:20:511628 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121629 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221630
1631 for f in input_api.AffectedSourceFiles(sources):
1632 file_content = input_api.ReadFile(f)
1633 has_modified_logs = False
1634
1635 # Per line checks
dgn87d9fb62015-06-12 09:15:121636 if (cr_log_import_pattern.search(file_content) or
1637 (class_in_base_pattern.search(file_content) and
1638 not has_some_log_import_pattern.search(file_content))):
1639 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221640 for line_num, line in f.ChangedContents():
1641
1642 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121643 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221644 if match:
1645 has_modified_logs = True
1646
1647 # Make sure it uses "TAG"
1648 if not match.group('tag') == 'TAG':
1649 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121650 else:
1651 # Report non cr Log function calls in changed lines
1652 for line_num, line in f.ChangedContents():
1653 if log_call_pattern.search(line):
1654 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221655
1656 # Per file checks
1657 if has_modified_logs:
1658 # Make sure the tag is using the "cr" prefix and is not too long
1659 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511660 tag_name = match.group('name') if match else None
1661 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221662 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511663 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221664 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511665 elif '.' in tag_name:
1666 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221667
1668 results = []
1669 if tag_decl_errors:
1670 results.append(output_api.PresubmitPromptWarning(
1671 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511672 '"private static final String TAG = "<package tag>".\n'
1673 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221674 tag_decl_errors))
1675
1676 if tag_length_errors:
1677 results.append(output_api.PresubmitError(
1678 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511679 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221680 tag_length_errors))
1681
1682 if tag_errors:
1683 results.append(output_api.PresubmitPromptWarning(
1684 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1685 tag_errors))
1686
dgn87d9fb62015-06-12 09:15:121687 if util_log_errors:
dgn4401aa52015-04-29 16:26:171688 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121689 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1690 util_log_errors))
1691
dgn38736db2015-09-18 19:20:511692 if tag_with_dot_errors:
1693 results.append(output_api.PresubmitPromptWarning(
1694 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1695 tag_with_dot_errors))
1696
dgn4401aa52015-04-29 16:26:171697 return results
1698
1699
agrieve7b6479d82015-10-07 14:24:221700def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1701 """Checks if MDPI assets are placed in a correct directory."""
1702 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1703 ('/res/drawable/' in f.LocalPath() or
1704 '/res/drawable-ldrtl/' in f.LocalPath()))
1705 errors = []
1706 for f in input_api.AffectedFiles(include_deletes=False,
1707 file_filter=file_filter):
1708 errors.append(' %s' % f.LocalPath())
1709
1710 results = []
1711 if errors:
1712 results.append(output_api.PresubmitError(
1713 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1714 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1715 '/res/drawable-ldrtl/.\n'
1716 'Contact [email protected] if you have questions.', errors))
1717 return results
1718
1719
agrievef32bcc72016-04-04 14:57:401720class PydepsChecker(object):
1721 def __init__(self, input_api, pydeps_files):
1722 self._file_cache = {}
1723 self._input_api = input_api
1724 self._pydeps_files = pydeps_files
1725
1726 def _LoadFile(self, path):
1727 """Returns the list of paths within a .pydeps file relative to //."""
1728 if path not in self._file_cache:
1729 with open(path) as f:
1730 self._file_cache[path] = f.read()
1731 return self._file_cache[path]
1732
1733 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1734 """Returns an interable of paths within the .pydep, relativized to //."""
1735 os_path = self._input_api.os_path
1736 pydeps_dir = os_path.dirname(pydeps_path)
1737 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1738 if not l.startswith('*'))
1739 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1740
1741 def _CreateFilesToPydepsMap(self):
1742 """Returns a map of local_path -> list_of_pydeps."""
1743 ret = {}
1744 for pydep_local_path in self._pydeps_files:
1745 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1746 ret.setdefault(path, []).append(pydep_local_path)
1747 return ret
1748
1749 def ComputeAffectedPydeps(self):
1750 """Returns an iterable of .pydeps files that might need regenerating."""
1751 affected_pydeps = set()
1752 file_to_pydeps_map = None
1753 for f in self._input_api.AffectedFiles(include_deletes=True):
1754 local_path = f.LocalPath()
1755 if local_path == 'DEPS':
1756 return self._pydeps_files
1757 elif local_path.endswith('.pydeps'):
1758 if local_path in self._pydeps_files:
1759 affected_pydeps.add(local_path)
1760 elif local_path.endswith('.py'):
1761 if file_to_pydeps_map is None:
1762 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1763 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1764 return affected_pydeps
1765
1766 def DetermineIfStale(self, pydeps_path):
1767 """Runs print_python_deps.py to see if the files is stale."""
1768 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1769 cmd = old_pydeps_data[1][1:].strip()
1770 new_pydeps_data = self._input_api.subprocess.check_output(
1771 cmd + ' --output ""', shell=True)
1772 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1773 return cmd
1774
1775
1776def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1777 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001778 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281779 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1780 # Mac, so skip it on other platforms.
1781 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001782 return []
agrievef32bcc72016-04-04 14:57:401783 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1784 is_android = input_api.os_path.exists('third_party/android_tools')
1785 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1786 results = []
1787 # First, check for new / deleted .pydeps.
1788 for f in input_api.AffectedFiles(include_deletes=True):
1789 if f.LocalPath().endswith('.pydeps'):
1790 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1791 results.append(output_api.PresubmitError(
1792 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1793 'remove %s' % f.LocalPath()))
1794 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1795 results.append(output_api.PresubmitError(
1796 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1797 'include %s' % f.LocalPath()))
1798
1799 if results:
1800 return results
1801
1802 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1803
1804 for pydep_path in checker.ComputeAffectedPydeps():
1805 try:
1806 cmd = checker.DetermineIfStale(pydep_path)
1807 if cmd:
1808 results.append(output_api.PresubmitError(
1809 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1810 (pydep_path, cmd)))
1811 except input_api.subprocess.CalledProcessError as error:
1812 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1813 long_text=error.output)]
1814
1815 return results
1816
1817
glidere61efad2015-02-18 17:39:431818def _CheckSingletonInHeaders(input_api, output_api):
1819 """Checks to make sure no header files have |Singleton<|."""
1820 def FileFilter(affected_file):
1821 # It's ok for base/memory/singleton.h to have |Singleton<|.
1822 black_list = (_EXCLUDED_PATHS +
1823 input_api.DEFAULT_BLACK_LIST +
1824 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1825 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1826
sergeyu34d21222015-09-16 00:11:441827 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431828 files = []
1829 for f in input_api.AffectedSourceFiles(FileFilter):
1830 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1831 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1832 contents = input_api.ReadFile(f)
1833 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241834 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431835 pattern.search(line)):
1836 files.append(f)
1837 break
1838
1839 if files:
yolandyandaabc6d2016-04-18 18:29:391840 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441841 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431842 'Please move them to an appropriate source file so that the ' +
1843 'template gets instantiated in a single compilation unit.',
1844 files) ]
1845 return []
1846
1847
dbeam37e8e7402016-02-10 22:58:201848def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1849 """Checks for old style compiled_resources.gyp files."""
1850 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1851
1852 added_compiled_resources = filter(is_compiled_resource, [
1853 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1854 ])
1855
1856 if not added_compiled_resources:
1857 return []
1858
1859 return [output_api.PresubmitError(
1860 "Found new compiled_resources.gyp files:\n%s\n\n"
1861 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551862 "please use compiled_resources2.gyp instead:\n"
1863 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1864 %
dbeam37e8e7402016-02-10 22:58:201865 "\n".join(added_compiled_resources))]
1866
1867
[email protected]fd20b902014-05-09 02:14:531868_DEPRECATED_CSS = [
1869 # Values
1870 ( "-webkit-box", "flex" ),
1871 ( "-webkit-inline-box", "inline-flex" ),
1872 ( "-webkit-flex", "flex" ),
1873 ( "-webkit-inline-flex", "inline-flex" ),
1874 ( "-webkit-min-content", "min-content" ),
1875 ( "-webkit-max-content", "max-content" ),
1876
1877 # Properties
1878 ( "-webkit-background-clip", "background-clip" ),
1879 ( "-webkit-background-origin", "background-origin" ),
1880 ( "-webkit-background-size", "background-size" ),
1881 ( "-webkit-box-shadow", "box-shadow" ),
1882
1883 # Functions
1884 ( "-webkit-gradient", "gradient" ),
1885 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1886 ( "-webkit-linear-gradient", "linear-gradient" ),
1887 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1888 ( "-webkit-radial-gradient", "radial-gradient" ),
1889 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1890]
1891
1892def _CheckNoDeprecatedCSS(input_api, output_api):
1893 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251894 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341895 documentation and iOS CSS for dom distiller
1896 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251897 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531898 results = []
dbeam070cfe62014-10-22 06:44:021899 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251900 black_list = (_EXCLUDED_PATHS +
1901 _TEST_CODE_EXCLUDED_PATHS +
1902 input_api.DEFAULT_BLACK_LIST +
1903 (r"^chrome/common/extensions/docs",
1904 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341905 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051906 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441907 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251908 r"^native_client_sdk"))
1909 file_filter = lambda f: input_api.FilterSourceFile(
1910 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531911 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1912 for line_num, line in fpath.ChangedContents():
1913 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021914 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531915 results.append(output_api.PresubmitError(
1916 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1917 (fpath.LocalPath(), line_num, deprecated_value, value)))
1918 return results
1919
mohan.reddyf21db962014-10-16 12:26:471920
dbeam070cfe62014-10-22 06:44:021921_DEPRECATED_JS = [
1922 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1923 ( "__defineGetter__", "Object.defineProperty" ),
1924 ( "__defineSetter__", "Object.defineProperty" ),
1925]
1926
1927def _CheckNoDeprecatedJS(input_api, output_api):
1928 """Make sure that we don't use deprecated JS in Chrome code."""
1929 results = []
1930 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1931 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1932 input_api.DEFAULT_BLACK_LIST)
1933 file_filter = lambda f: input_api.FilterSourceFile(
1934 f, white_list=file_inclusion_pattern, black_list=black_list)
1935 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1936 for lnum, line in fpath.ChangedContents():
1937 for (deprecated, replacement) in _DEPRECATED_JS:
1938 if deprecated in line:
1939 results.append(output_api.PresubmitError(
1940 "%s:%d: Use of deprecated JS %s, use %s instead" %
1941 (fpath.LocalPath(), lnum, deprecated, replacement)))
1942 return results
1943
1944
dgnaa68d5e2015-06-10 10:08:221945def _AndroidSpecificOnUploadChecks(input_api, output_api):
1946 """Groups checks that target android code."""
1947 results = []
dgnaa68d5e2015-06-10 10:08:221948 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221949 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291950 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221951 return results
1952
1953
[email protected]22c9bd72011-03-27 16:47:391954def _CommonChecks(input_api, output_api):
1955 """Checks common to both upload and commit."""
1956 results = []
1957 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381958 input_api, output_api,
1959 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461960 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191961 results.extend(
[email protected]760deea2013-12-10 19:33:491962 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541963 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181964 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521965 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221966 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441967 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591968 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061969 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121970 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181971 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221972 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491973 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271974 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031975 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491976 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441977 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271978 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541979 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441980 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391981 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551982 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041983 results.extend(
1984 input_api.canned_checks.CheckChangeHasNoTabs(
1985 input_api,
1986 output_api,
1987 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401988 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161989 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591990 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081991 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531992 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021993 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471994 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041995 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231996 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431997 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201998 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401999 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152000 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172001 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:232002 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242003
2004 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2005 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2006 input_api, output_api,
2007 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382008 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392009 return results
[email protected]1f7b4172010-01-28 01:17:342010
[email protected]b337cb5b2011-01-23 21:24:052011
[email protected]66daa702011-05-28 14:41:462012def _CheckAuthorizedAuthor(input_api, output_api):
2013 """For non-googler/chromites committers, verify the author's email address is
2014 in AUTHORS.
2015 """
2016 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012017 if not author:
2018 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462019 return []
[email protected]c99663292011-05-31 19:46:082020 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462021 input_api.PresubmitLocalPath(), 'AUTHORS')
2022 valid_authors = (
2023 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2024 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182025 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172026 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2027 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232028 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462029 return [output_api.PresubmitPromptWarning(
2030 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2031 '\n'
2032 'http://www.chromium.org/developers/contributing-code and read the '
2033 '"Legal" section\n'
2034 'If you are a chromite, verify the contributor signed the CLA.') %
2035 author)]
2036 return []
2037
2038
[email protected]b8079ae4a2012-12-05 19:56:492039def _CheckPatchFiles(input_api, output_api):
2040 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2041 if f.LocalPath().endswith(('.orig', '.rej'))]
2042 if problems:
2043 return [output_api.PresubmitError(
2044 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032045 else:
2046 return []
[email protected]b8079ae4a2012-12-05 19:56:492047
2048
[email protected]b00342e7f2013-03-26 16:21:542049def _DidYouMeanOSMacro(bad_macro):
2050 try:
2051 return {'A': 'OS_ANDROID',
2052 'B': 'OS_BSD',
2053 'C': 'OS_CHROMEOS',
2054 'F': 'OS_FREEBSD',
2055 'L': 'OS_LINUX',
2056 'M': 'OS_MACOSX',
2057 'N': 'OS_NACL',
2058 'O': 'OS_OPENBSD',
2059 'P': 'OS_POSIX',
2060 'S': 'OS_SOLARIS',
2061 'W': 'OS_WIN'}[bad_macro[3].upper()]
2062 except KeyError:
2063 return ''
2064
2065
2066def _CheckForInvalidOSMacrosInFile(input_api, f):
2067 """Check for sensible looking, totally invalid OS macros."""
2068 preprocessor_statement = input_api.re.compile(r'^\s*#')
2069 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2070 results = []
2071 for lnum, line in f.ChangedContents():
2072 if preprocessor_statement.search(line):
2073 for match in os_macro.finditer(line):
2074 if not match.group(1) in _VALID_OS_MACROS:
2075 good = _DidYouMeanOSMacro(match.group(1))
2076 did_you_mean = ' (did you mean %s?)' % good if good else ''
2077 results.append(' %s:%d %s%s' % (f.LocalPath(),
2078 lnum,
2079 match.group(1),
2080 did_you_mean))
2081 return results
2082
2083
2084def _CheckForInvalidOSMacros(input_api, output_api):
2085 """Check all affected files for invalid OS macros."""
2086 bad_macros = []
2087 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472088 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542089 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2090
2091 if not bad_macros:
2092 return []
2093
2094 return [output_api.PresubmitError(
2095 'Possibly invalid OS macro[s] found. Please fix your code\n'
2096 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2097
lliabraa35bab3932014-10-01 12:16:442098
2099def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2100 """Check all affected files for invalid "if defined" macros."""
2101 ALWAYS_DEFINED_MACROS = (
2102 "TARGET_CPU_PPC",
2103 "TARGET_CPU_PPC64",
2104 "TARGET_CPU_68K",
2105 "TARGET_CPU_X86",
2106 "TARGET_CPU_ARM",
2107 "TARGET_CPU_MIPS",
2108 "TARGET_CPU_SPARC",
2109 "TARGET_CPU_ALPHA",
2110 "TARGET_IPHONE_SIMULATOR",
2111 "TARGET_OS_EMBEDDED",
2112 "TARGET_OS_IPHONE",
2113 "TARGET_OS_MAC",
2114 "TARGET_OS_UNIX",
2115 "TARGET_OS_WIN32",
2116 )
2117 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2118 results = []
2119 for lnum, line in f.ChangedContents():
2120 for match in ifdef_macro.finditer(line):
2121 if match.group(1) in ALWAYS_DEFINED_MACROS:
2122 always_defined = ' %s is always defined. ' % match.group(1)
2123 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2124 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2125 lnum,
2126 always_defined,
2127 did_you_mean))
2128 return results
2129
2130
2131def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2132 """Check all affected files for invalid "if defined" macros."""
2133 bad_macros = []
2134 for f in input_api.AffectedFiles():
2135 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2136 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2137
2138 if not bad_macros:
2139 return []
2140
2141 return [output_api.PresubmitError(
2142 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2143 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2144 bad_macros)]
2145
2146
mlamouria82272622014-09-16 18:45:042147def _CheckForIPCRules(input_api, output_api):
2148 """Check for same IPC rules described in
2149 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2150 """
2151 base_pattern = r'IPC_ENUM_TRAITS\('
2152 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2153 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2154
2155 problems = []
2156 for f in input_api.AffectedSourceFiles(None):
2157 local_path = f.LocalPath()
2158 if not local_path.endswith('.h'):
2159 continue
2160 for line_number, line in f.ChangedContents():
2161 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2162 problems.append(
2163 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2164
2165 if problems:
2166 return [output_api.PresubmitPromptWarning(
2167 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2168 else:
2169 return []
2170
[email protected]b00342e7f2013-03-26 16:21:542171
mostynbb639aca52015-01-07 20:31:232172def _CheckForWindowsLineEndings(input_api, output_api):
2173 """Check source code and known ascii text files for Windows style line
2174 endings.
2175 """
earthdok1b5e0ee2015-03-10 15:19:102176 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232177
2178 file_inclusion_pattern = (
2179 known_text_files,
2180 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2181 )
2182
2183 filter = lambda f: input_api.FilterSourceFile(
2184 f, white_list=file_inclusion_pattern, black_list=None)
2185 files = [f.LocalPath() for f in
2186 input_api.AffectedSourceFiles(filter)]
2187
2188 problems = []
2189
2190 for file in files:
2191 fp = open(file, 'r')
2192 for line in fp:
2193 if line.endswith('\r\n'):
2194 problems.append(file)
2195 break
2196 fp.close()
2197
2198 if problems:
2199 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2200 'these files to contain Windows style line endings?\n' +
2201 '\n'.join(problems))]
2202
2203 return []
2204
2205
pastarmovj89f7ee12016-09-20 14:58:132206def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2207 lint_filters=None, verbose_level=None):
2208 """Checks that all source files use SYSLOG properly."""
2209 syslog_files = []
2210 for f in input_api.AffectedSourceFiles(source_file_filter):
2211 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2212 syslog_files.append(f.LocalPath())
2213 if syslog_files:
2214 return [output_api.PresubmitPromptWarning(
2215 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2216 ' calls.\nFiles to check:\n', items=syslog_files)]
2217 return []
2218
2219
[email protected]1f7b4172010-01-28 01:17:342220def CheckChangeOnUpload(input_api, output_api):
2221 results = []
2222 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472223 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282224 results.extend(
2225 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192226 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222227 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132228 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542229 return results
[email protected]ca8d19842009-02-19 16:33:122230
2231
[email protected]1bfb8322014-04-23 01:02:412232def GetTryServerMasterForBot(bot):
2233 """Returns the Try Server master for the given bot.
2234
[email protected]0bb112362014-07-26 04:38:322235 It tries to guess the master from the bot name, but may still fail
2236 and return None. There is no longer a default master.
2237 """
2238 # Potentially ambiguous bot names are listed explicitly.
2239 master_map = {
tandriie5587792016-07-14 00:34:502240 'chromium_presubmit': 'master.tryserver.chromium.linux',
2241 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412242 }
[email protected]0bb112362014-07-26 04:38:322243 master = master_map.get(bot)
2244 if not master:
wnwen4fbaab82016-05-25 12:54:362245 if 'android' in bot:
tandriie5587792016-07-14 00:34:502246 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362247 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502248 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322249 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502250 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322251 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502252 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322253 return master
[email protected]1bfb8322014-04-23 01:02:412254
2255
Paweł Hajdan, Jr55083782014-12-19 20:32:562256def GetDefaultTryConfigs(bots):
2257 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012258 """
2259
Paweł Hajdan, Jr55083782014-12-19 20:32:562260 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412261
2262 # Build up the mapping from tryserver master to bot/test.
2263 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562264 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412265 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2266 return out
[email protected]38c6a512013-12-18 23:48:012267
2268
[email protected]ca8d19842009-02-19 16:33:122269def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542270 results = []
[email protected]1f7b4172010-01-28 01:17:342271 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542272 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272273 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342274 input_api,
2275 output_api,
[email protected]2fdd1f362013-01-16 03:56:032276 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272277
[email protected]3e4eb112011-01-18 03:29:542278 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2279 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412280 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2281 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542282 return results