blob: 3083e5455a90c559456b1d4a5eb31dd3eeb6381e [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 ),
[email protected]127f18ec2012-06-16 05:05:59310)
311
wnwenbdc444e2016-05-25 13:44:15312
mlamouria82272622014-09-16 18:45:04313_IPC_ENUM_TRAITS_DEPRECATED = (
314 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
315 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
316
[email protected]127f18ec2012-06-16 05:05:59317
[email protected]b00342e7f2013-03-26 16:21:54318_VALID_OS_MACROS = (
319 # Please keep sorted.
320 'OS_ANDROID',
321 'OS_BSD',
322 'OS_CAT', # For testing.
323 'OS_CHROMEOS',
324 'OS_FREEBSD',
325 'OS_IOS',
326 'OS_LINUX',
327 'OS_MACOSX',
328 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21329 'OS_NACL_NONSFI',
330 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12331 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54332 'OS_OPENBSD',
333 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37334 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54335 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54336 'OS_WIN',
337)
338
339
agrievef32bcc72016-04-04 14:57:40340_ANDROID_SPECIFIC_PYDEPS_FILES = [
341 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19342 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40343]
344
wnwenbdc444e2016-05-25 13:44:15345
agrievef32bcc72016-04-04 14:57:40346_GENERIC_PYDEPS_FILES = [
347 'build/secondary/tools/swarming_client/isolate.pydeps',
348]
349
wnwenbdc444e2016-05-25 13:44:15350
agrievef32bcc72016-04-04 14:57:40351_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
352
353
[email protected]55459852011-08-10 15:17:19354def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
355 """Attempts to prevent use of functions intended only for testing in
356 non-testing code. For now this is just a best-effort implementation
357 that ignores header files and may have some false positives. A
358 better implementation would probably need a proper C++ parser.
359 """
360 # We only scan .cc files and the like, as the declaration of
361 # for-testing functions in header files are hard to distinguish from
362 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44363 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19364
jochenc0d4808c2015-07-27 09:25:42365 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19366 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09367 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19368 exclusion_pattern = input_api.re.compile(
369 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
370 base_function_pattern, base_function_pattern))
371
372 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44373 black_list = (_EXCLUDED_PATHS +
374 _TEST_CODE_EXCLUDED_PATHS +
375 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19376 return input_api.FilterSourceFile(
377 affected_file,
378 white_list=(file_inclusion_pattern, ),
379 black_list=black_list)
380
381 problems = []
382 for f in input_api.AffectedSourceFiles(FilterFile):
383 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24384 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03385 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46386 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03387 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19388 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03389 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19390
391 if problems:
[email protected]f7051d52013-04-02 18:31:42392 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03393 else:
394 return []
[email protected]55459852011-08-10 15:17:19395
396
[email protected]10689ca2011-09-02 02:31:54397def _CheckNoIOStreamInHeaders(input_api, output_api):
398 """Checks to make sure no .h files include <iostream>."""
399 files = []
400 pattern = input_api.re.compile(r'^#include\s*<iostream>',
401 input_api.re.MULTILINE)
402 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
403 if not f.LocalPath().endswith('.h'):
404 continue
405 contents = input_api.ReadFile(f)
406 if pattern.search(contents):
407 files.append(f)
408
409 if len(files):
yolandyandaabc6d2016-04-18 18:29:39410 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06411 'Do not #include <iostream> in header files, since it inserts static '
412 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54413 '#include <ostream>. See http://crbug.com/94794',
414 files) ]
415 return []
416
417
[email protected]72df4e782012-06-21 16:28:18418def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52419 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18420 problems = []
421 for f in input_api.AffectedFiles():
422 if (not f.LocalPath().endswith(('.cc', '.mm'))):
423 continue
424
425 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04426 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18427 problems.append(' %s:%d' % (f.LocalPath(), line_num))
428
429 if not problems:
430 return []
431 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
432 '\n'.join(problems))]
433
434
danakj61c1aa22015-10-26 19:55:52435def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
436 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
437 errors = []
438 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
439 input_api.re.MULTILINE)
440 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
441 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
442 continue
443 for lnum, line in f.ChangedContents():
444 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17445 errors.append(output_api.PresubmitError(
446 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
447 'DCHECK_IS_ON()", not forgetting the braces.')
448 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52449 return errors
450
451
mcasasb7440c282015-02-04 14:52:19452def _FindHistogramNameInLine(histogram_name, line):
453 """Tries to find a histogram name or prefix in a line."""
454 if not "affected-histogram" in line:
455 return histogram_name in line
456 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
457 # the histogram_name.
458 if not '"' in line:
459 return False
460 histogram_prefix = line.split('\"')[1]
461 return histogram_prefix in histogram_name
462
463
464def _CheckUmaHistogramChanges(input_api, output_api):
465 """Check that UMA histogram names in touched lines can still be found in other
466 lines of the patch or in histograms.xml. Note that this check would not catch
467 the reverse: changes in histograms.xml not matched in the code itself."""
468 touched_histograms = []
469 histograms_xml_modifications = []
470 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
471 for f in input_api.AffectedFiles():
472 # If histograms.xml itself is modified, keep the modified lines for later.
473 if f.LocalPath().endswith(('histograms.xml')):
474 histograms_xml_modifications = f.ChangedContents()
475 continue
476 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
477 continue
478 for line_num, line in f.ChangedContents():
479 found = pattern.search(line)
480 if found:
481 touched_histograms.append([found.group(1), f, line_num])
482
483 # Search for the touched histogram names in the local modifications to
484 # histograms.xml, and, if not found, on the base histograms.xml file.
485 unmatched_histograms = []
486 for histogram_info in touched_histograms:
487 histogram_name_found = False
488 for line_num, line in histograms_xml_modifications:
489 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
490 if histogram_name_found:
491 break
492 if not histogram_name_found:
493 unmatched_histograms.append(histogram_info)
494
eromanb90c82e7e32015-04-01 15:13:49495 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19496 problems = []
497 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49498 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19499 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45500 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19501 histogram_name_found = False
502 for line in histograms_xml:
503 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
504 if histogram_name_found:
505 break
506 if not histogram_name_found:
507 problems.append(' [%s:%d] %s' %
508 (f.LocalPath(), line_num, histogram_name))
509
510 if not problems:
511 return []
512 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
513 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49514 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19515
wnwenbdc444e2016-05-25 13:44:15516
yolandyandaabc6d2016-04-18 18:29:39517def _CheckFlakyTestUsage(input_api, output_api):
518 """Check that FlakyTest annotation is our own instead of the android one"""
519 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
520 files = []
521 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
522 if f.LocalPath().endswith('Test.java'):
523 if pattern.search(input_api.ReadFile(f)):
524 files.append(f)
525 if len(files):
526 return [output_api.PresubmitError(
527 'Use org.chromium.base.test.util.FlakyTest instead of '
528 'android.test.FlakyTest',
529 files)]
530 return []
mcasasb7440c282015-02-04 14:52:19531
wnwenbdc444e2016-05-25 13:44:15532
[email protected]8ea5d4b2011-09-13 21:49:22533def _CheckNoNewWStrings(input_api, output_api):
534 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27535 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22536 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20537 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57538 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34539 '/win/' in f.LocalPath() or
540 'chrome_elf' in f.LocalPath() or
541 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20542 continue
[email protected]8ea5d4b2011-09-13 21:49:22543
[email protected]a11dbe9b2012-08-07 01:32:58544 allowWString = False
[email protected]b5c24292011-11-28 14:38:20545 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58546 if 'presubmit: allow wstring' in line:
547 allowWString = True
548 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27549 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58550 allowWString = False
551 else:
552 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22553
[email protected]55463aa62011-10-12 00:48:27554 if not problems:
555 return []
556 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58557 ' If you are calling a cross-platform API that accepts a wstring, '
558 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27559 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22560
561
[email protected]2a8ac9c2011-10-19 17:20:44562def _CheckNoDEPSGIT(input_api, output_api):
563 """Make sure .DEPS.git is never modified manually."""
564 if any(f.LocalPath().endswith('.DEPS.git') for f in
565 input_api.AffectedFiles()):
566 return [output_api.PresubmitError(
567 'Never commit changes to .DEPS.git. This file is maintained by an\n'
568 'automated system based on what\'s in DEPS and your changes will be\n'
569 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34570 '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:44571 'for more information')]
572 return []
573
574
tandriief664692014-09-23 14:51:47575def _CheckValidHostsInDEPS(input_api, output_api):
576 """Checks that DEPS file deps are from allowed_hosts."""
577 # Run only if DEPS file has been modified to annoy fewer bystanders.
578 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
579 return []
580 # Outsource work to gclient verify
581 try:
582 input_api.subprocess.check_output(['gclient', 'verify'])
583 return []
584 except input_api.subprocess.CalledProcessError, error:
585 return [output_api.PresubmitError(
586 'DEPS file must have only git dependencies.',
587 long_text=error.output)]
588
589
[email protected]127f18ec2012-06-16 05:05:59590def _CheckNoBannedFunctions(input_api, output_api):
591 """Make sure that banned functions are not used."""
592 warnings = []
593 errors = []
594
wnwenbdc444e2016-05-25 13:44:15595 def IsBlacklisted(affected_file, blacklist):
596 local_path = affected_file.LocalPath()
597 for item in blacklist:
598 if input_api.re.match(item, local_path):
599 return True
600 return False
601
602 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
603 matched = False
604 if func_name[0:1] == '/':
605 regex = func_name[1:]
606 if input_api.re.search(regex, line):
607 matched = True
608 elif func_name in line:
dchenge07de812016-06-20 19:27:17609 matched = True
wnwenbdc444e2016-05-25 13:44:15610 if matched:
dchenge07de812016-06-20 19:27:17611 problems = warnings
wnwenbdc444e2016-05-25 13:44:15612 if error:
dchenge07de812016-06-20 19:27:17613 problems = errors
wnwenbdc444e2016-05-25 13:44:15614 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
615 for message_line in message:
616 problems.append(' %s' % message_line)
617
[email protected]127f18ec2012-06-16 05:05:59618 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
619 for f in input_api.AffectedFiles(file_filter=file_filter):
620 for line_num, line in f.ChangedContents():
621 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15622 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59623
624 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
625 for f in input_api.AffectedFiles(file_filter=file_filter):
626 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49627 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49628 if IsBlacklisted(f, excluded_paths):
629 continue
wnwenbdc444e2016-05-25 13:44:15630 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59631
632 result = []
633 if (warnings):
634 result.append(output_api.PresubmitPromptWarning(
635 'Banned functions were used.\n' + '\n'.join(warnings)))
636 if (errors):
637 result.append(output_api.PresubmitError(
638 'Banned functions were used.\n' + '\n'.join(errors)))
639 return result
640
641
[email protected]6c063c62012-07-11 19:11:06642def _CheckNoPragmaOnce(input_api, output_api):
643 """Make sure that banned functions are not used."""
644 files = []
645 pattern = input_api.re.compile(r'^#pragma\s+once',
646 input_api.re.MULTILINE)
647 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
648 if not f.LocalPath().endswith('.h'):
649 continue
650 contents = input_api.ReadFile(f)
651 if pattern.search(contents):
652 files.append(f)
653
654 if files:
655 return [output_api.PresubmitError(
656 'Do not use #pragma once in header files.\n'
657 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
658 files)]
659 return []
660
[email protected]127f18ec2012-06-16 05:05:59661
[email protected]e7479052012-09-19 00:26:12662def _CheckNoTrinaryTrueFalse(input_api, output_api):
663 """Checks to make sure we don't introduce use of foo ? true : false."""
664 problems = []
665 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
666 for f in input_api.AffectedFiles():
667 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
668 continue
669
670 for line_num, line in f.ChangedContents():
671 if pattern.match(line):
672 problems.append(' %s:%d' % (f.LocalPath(), line_num))
673
674 if not problems:
675 return []
676 return [output_api.PresubmitPromptWarning(
677 'Please consider avoiding the "? true : false" pattern if possible.\n' +
678 '\n'.join(problems))]
679
680
[email protected]55f9f382012-07-31 11:02:18681def _CheckUnwantedDependencies(input_api, output_api):
682 """Runs checkdeps on #include statements added in this
683 change. Breaking - rules is an error, breaking ! rules is a
684 warning.
685 """
mohan.reddyf21db962014-10-16 12:26:47686 import sys
[email protected]55f9f382012-07-31 11:02:18687 # We need to wait until we have an input_api object and use this
688 # roundabout construct to import checkdeps because this file is
689 # eval-ed and thus doesn't have __file__.
690 original_sys_path = sys.path
691 try:
692 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47693 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18694 import checkdeps
695 from cpp_checker import CppChecker
696 from rules import Rule
697 finally:
698 # Restore sys.path to what it was before.
699 sys.path = original_sys_path
700
701 added_includes = []
702 for f in input_api.AffectedFiles():
703 if not CppChecker.IsCppFile(f.LocalPath()):
704 continue
705
706 changed_lines = [line for line_num, line in f.ChangedContents()]
707 added_includes.append([f.LocalPath(), changed_lines])
708
[email protected]26385172013-05-09 23:11:35709 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18710
711 error_descriptions = []
712 warning_descriptions = []
713 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
714 added_includes):
715 description_with_path = '%s\n %s' % (path, rule_description)
716 if rule_type == Rule.DISALLOW:
717 error_descriptions.append(description_with_path)
718 else:
719 warning_descriptions.append(description_with_path)
720
721 results = []
722 if error_descriptions:
723 results.append(output_api.PresubmitError(
724 'You added one or more #includes that violate checkdeps rules.',
725 error_descriptions))
726 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42727 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18728 'You added one or more #includes of files that are temporarily\n'
729 'allowed but being removed. Can you avoid introducing the\n'
730 '#include? See relevant DEPS file(s) for details and contacts.',
731 warning_descriptions))
732 return results
733
734
[email protected]fbcafe5a2012-08-08 15:31:22735def _CheckFilePermissions(input_api, output_api):
736 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15737 if input_api.platform == 'win32':
738 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29739 checkperms_tool = input_api.os_path.join(
740 input_api.PresubmitLocalPath(),
741 'tools', 'checkperms', 'checkperms.py')
742 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47743 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22744 for f in input_api.AffectedFiles():
745 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11746 try:
747 input_api.subprocess.check_output(args)
748 return []
749 except input_api.subprocess.CalledProcessError as error:
750 return [output_api.PresubmitError(
751 'checkperms.py failed:',
752 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22753
754
[email protected]c8278b32012-10-30 20:35:49755def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
756 """Makes sure we don't include ui/aura/window_property.h
757 in header files.
758 """
759 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
760 errors = []
761 for f in input_api.AffectedFiles():
762 if not f.LocalPath().endswith('.h'):
763 continue
764 for line_num, line in f.ChangedContents():
765 if pattern.match(line):
766 errors.append(' %s:%d' % (f.LocalPath(), line_num))
767
768 results = []
769 if errors:
770 results.append(output_api.PresubmitError(
771 'Header files should not include ui/aura/window_property.h', errors))
772 return results
773
774
[email protected]cf9b78f2012-11-14 11:40:28775def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
776 """Checks that the lines in scope occur in the right order.
777
778 1. C system files in alphabetical order
779 2. C++ system files in alphabetical order
780 3. Project's .h files
781 """
782
783 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
784 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
785 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
786
787 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
788
789 state = C_SYSTEM_INCLUDES
790
791 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57792 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28793 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55794 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28795 for line_num, line in scope:
796 if c_system_include_pattern.match(line):
797 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55798 problem_linenums.append((line_num, previous_line_num,
799 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28800 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55801 problem_linenums.append((line_num, previous_line_num,
802 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28803 elif cpp_system_include_pattern.match(line):
804 if state == C_SYSTEM_INCLUDES:
805 state = CPP_SYSTEM_INCLUDES
806 elif state == CUSTOM_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, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28811 elif custom_include_pattern.match(line):
812 if state != CUSTOM_INCLUDES:
813 state = CUSTOM_INCLUDES
814 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55815 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28816 else:
brucedawson70fadb02015-06-30 17:47:55817 problem_linenums.append((line_num, previous_line_num,
818 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28819 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57820 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28821
822 warnings = []
brucedawson70fadb02015-06-30 17:47:55823 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57824 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55825 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28826 return warnings
827
828
[email protected]ac294a12012-12-06 16:38:43829def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28830 """Checks the #include order for the given file f."""
831
[email protected]2299dcf2012-11-15 19:56:24832 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30833 # Exclude the following includes from the check:
834 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
835 # specific order.
836 # 2) <atlbase.h>, "build/build_config.h"
837 excluded_include_pattern = input_api.re.compile(
838 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24839 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33840 # Match the final or penultimate token if it is xxxtest so we can ignore it
841 # when considering the special first include.
842 test_file_tag_pattern = input_api.re.compile(
843 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11844 if_pattern = input_api.re.compile(
845 r'\s*#\s*(if|elif|else|endif|define|undef).*')
846 # Some files need specialized order of includes; exclude such files from this
847 # check.
848 uncheckable_includes_pattern = input_api.re.compile(
849 r'\s*#include '
850 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28851
852 contents = f.NewContents()
853 warnings = []
854 line_num = 0
855
[email protected]ac294a12012-12-06 16:38:43856 # Handle the special first include. If the first include file is
857 # some/path/file.h, the corresponding including file can be some/path/file.cc,
858 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
859 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33860 # If the included file is some/path/file_platform.h the including file could
861 # also be some/path/file_xxxtest_platform.h.
862 including_file_base_name = test_file_tag_pattern.sub(
863 '', input_api.os_path.basename(f.LocalPath()))
864
[email protected]ac294a12012-12-06 16:38:43865 for line in contents:
866 line_num += 1
867 if system_include_pattern.match(line):
868 # No special first include -> process the line again along with normal
869 # includes.
870 line_num -= 1
871 break
872 match = custom_include_pattern.match(line)
873 if match:
874 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33875 header_basename = test_file_tag_pattern.sub(
876 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
877
878 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24879 # No special first include -> process the line again along with normal
880 # includes.
881 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43882 break
[email protected]cf9b78f2012-11-14 11:40:28883
884 # Split into scopes: Each region between #if and #endif is its own scope.
885 scopes = []
886 current_scope = []
887 for line in contents[line_num:]:
888 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11889 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54890 continue
[email protected]2309b0fa02012-11-16 12:18:27891 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28892 scopes.append(current_scope)
893 current_scope = []
[email protected]962f117e2012-11-22 18:11:56894 elif ((system_include_pattern.match(line) or
895 custom_include_pattern.match(line)) and
896 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28897 current_scope.append((line_num, line))
898 scopes.append(current_scope)
899
900 for scope in scopes:
901 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
902 changed_linenums))
903 return warnings
904
905
906def _CheckIncludeOrder(input_api, output_api):
907 """Checks that the #include order is correct.
908
909 1. The corresponding header for source files.
910 2. C system files in alphabetical order
911 3. C++ system files in alphabetical order
912 4. Project's .h files in alphabetical order
913
[email protected]ac294a12012-12-06 16:38:43914 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
915 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28916 """
[email protected]e120b012014-08-15 19:08:35917 def FileFilterIncludeOrder(affected_file):
918 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
919 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28920
921 warnings = []
[email protected]e120b012014-08-15 19:08:35922 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08923 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43924 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
925 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28926
927 results = []
928 if warnings:
[email protected]f7051d52013-04-02 18:31:42929 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53930 warnings))
[email protected]cf9b78f2012-11-14 11:40:28931 return results
932
933
[email protected]70ca77752012-11-20 03:45:03934def _CheckForVersionControlConflictsInFile(input_api, f):
935 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
936 errors = []
937 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23938 if f.LocalPath().endswith('.md'):
939 # First-level headers in markdown look a lot like version control
940 # conflict markers. http://daringfireball.net/projects/markdown/basics
941 continue
[email protected]70ca77752012-11-20 03:45:03942 if pattern.match(line):
943 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
944 return errors
945
946
947def _CheckForVersionControlConflicts(input_api, output_api):
948 """Usually this is not intentional and will cause a compile failure."""
949 errors = []
950 for f in input_api.AffectedFiles():
951 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
952
953 results = []
954 if errors:
955 results.append(output_api.PresubmitError(
956 'Version control conflict markers found, please resolve.', errors))
957 return results
958
959
[email protected]06e6d0ff2012-12-11 01:36:44960def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
961 def FilterFile(affected_file):
962 """Filter function for use with input_api.AffectedSourceFiles,
963 below. This filters out everything except non-test files from
964 top-level directories that generally speaking should not hard-code
965 service URLs (e.g. src/android_webview/, src/content/ and others).
966 """
967 return input_api.FilterSourceFile(
968 affected_file,
[email protected]78bb39d62012-12-11 15:11:56969 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44970 black_list=(_EXCLUDED_PATHS +
971 _TEST_CODE_EXCLUDED_PATHS +
972 input_api.DEFAULT_BLACK_LIST))
973
reillyi38965732015-11-16 18:27:33974 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
975 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46976 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
977 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44978 problems = [] # items are (filename, line_number, line)
979 for f in input_api.AffectedSourceFiles(FilterFile):
980 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46981 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44982 problems.append((f.LocalPath(), line_num, line))
983
984 if problems:
[email protected]f7051d52013-04-02 18:31:42985 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44986 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58987 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44988 [' %s:%d: %s' % (
989 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03990 else:
991 return []
[email protected]06e6d0ff2012-12-11 01:36:44992
993
[email protected]d2530012013-01-25 16:39:27994def _CheckNoAbbreviationInPngFileName(input_api, output_api):
995 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31996 The native_client_sdk directory is excluded because it has auto-generated PNG
997 files for documentation.
[email protected]d2530012013-01-25 16:39:27998 """
[email protected]d2530012013-01-25 16:39:27999 errors = []
binji0dcdf342014-12-12 18:32:311000 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1001 black_list = (r'^native_client_sdk[\\\/]',)
1002 file_filter = lambda f: input_api.FilterSourceFile(
1003 f, white_list=white_list, black_list=black_list)
1004 for f in input_api.AffectedFiles(include_deletes=False,
1005 file_filter=file_filter):
1006 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271007
1008 results = []
1009 if errors:
1010 results.append(output_api.PresubmitError(
1011 'The name of PNG files should not have abbreviations. \n'
1012 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1013 'Contact [email protected] if you have questions.', errors))
1014 return results
1015
1016
[email protected]14a6131c2014-01-08 01:15:411017def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081018 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411019 a set of DEPS entries that we should look up.
1020
1021 For a directory (rather than a specific filename) we fake a path to
1022 a specific filename by adding /DEPS. This is chosen as a file that
1023 will seldom or never be subject to per-file include_rules.
1024 """
[email protected]2b438d62013-11-14 17:54:141025 # We ignore deps entries on auto-generated directories.
1026 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081027
1028 # This pattern grabs the path without basename in the first
1029 # parentheses, and the basename (if present) in the second. It
1030 # relies on the simple heuristic that if there is a basename it will
1031 # be a header file ending in ".h".
1032 pattern = re.compile(
1033 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141034 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081035 for changed_line in changed_lines:
1036 m = pattern.match(changed_line)
1037 if m:
1038 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141039 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411040 if m.group(2):
1041 results.add('%s%s' % (path, m.group(2)))
1042 else:
1043 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081044 return results
1045
1046
[email protected]e871964c2013-05-13 14:14:551047def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1048 """When a dependency prefixed with + is added to a DEPS file, we
1049 want to make sure that the change is reviewed by an OWNER of the
1050 target file or directory, to avoid layering violations from being
1051 introduced. This check verifies that this happens.
1052 """
1053 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241054
1055 file_filter = lambda f: not input_api.re.match(
1056 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1057 for f in input_api.AffectedFiles(include_deletes=False,
1058 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551059 filename = input_api.os_path.basename(f.LocalPath())
1060 if filename == 'DEPS':
1061 changed_lines |= set(line.strip()
1062 for line_num, line
1063 in f.ChangedContents())
1064 if not changed_lines:
1065 return []
1066
[email protected]14a6131c2014-01-08 01:15:411067 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1068 changed_lines)
[email protected]e871964c2013-05-13 14:14:551069 if not virtual_depended_on_files:
1070 return []
1071
1072 if input_api.is_committing:
1073 if input_api.tbr:
1074 return [output_api.PresubmitNotifyResult(
1075 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271076 if input_api.dry_run:
1077 return [output_api.PresubmitNotifyResult(
1078 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551079 if not input_api.change.issue:
1080 return [output_api.PresubmitError(
1081 "DEPS approval by OWNERS check failed: this change has "
1082 "no Rietveld issue number, so we can't check it for approvals.")]
1083 output = output_api.PresubmitError
1084 else:
1085 output = output_api.PresubmitNotifyResult
1086
1087 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501088 owner_email, reviewers = (
1089 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1090 input_api,
1091 owners_db.email_regexp,
1092 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551093
1094 owner_email = owner_email or input_api.change.author_email
1095
[email protected]de4f7d22013-05-23 14:27:461096 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511097 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461098 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551099 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1100 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411101
1102 # We strip the /DEPS part that was added by
1103 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1104 # directory.
1105 def StripDeps(path):
1106 start_deps = path.rfind('/DEPS')
1107 if start_deps != -1:
1108 return path[:start_deps]
1109 else:
1110 return path
1111 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551112 for path in missing_files]
1113
1114 if unapproved_dependencies:
1115 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151116 output('You need LGTM from owners of depends-on paths in DEPS that were '
1117 'modified in this CL:\n %s' %
1118 '\n '.join(sorted(unapproved_dependencies)))]
1119 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1120 output_list.append(output(
1121 'Suggested missing target path OWNERS:\n %s' %
1122 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551123 return output_list
1124
1125 return []
1126
1127
[email protected]85218562013-11-22 07:41:401128def _CheckSpamLogging(input_api, output_api):
1129 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1130 black_list = (_EXCLUDED_PATHS +
1131 _TEST_CODE_EXCLUDED_PATHS +
1132 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501133 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191134 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481135 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461136 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121137 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1138 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581139 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161140 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031141 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151142 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1143 r"^chromecast[\\\/]",
1144 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311145 r"^components[\\\/]html_viewer[\\\/]"
1146 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461147 # TODO(peter): Remove this exception. https://crbug.com/534537
1148 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1149 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251150 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1151 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241152 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111153 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151154 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111155 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521156 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501157 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361158 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311159 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131160 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441161 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451162 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021163 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441164 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401165 source_file_filter = lambda x: input_api.FilterSourceFile(
1166 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1167
1168 log_info = []
1169 printf = []
1170
1171 for f in input_api.AffectedSourceFiles(source_file_filter):
1172 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471173 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401174 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471175 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131176 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371177
mohan.reddyf21db962014-10-16 12:26:471178 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371179 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471180 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401181 printf.append(f.LocalPath())
1182
1183 if log_info:
1184 return [output_api.PresubmitError(
1185 'These files spam the console log with LOG(INFO):',
1186 items=log_info)]
1187 if printf:
1188 return [output_api.PresubmitError(
1189 'These files spam the console log with printf/fprintf:',
1190 items=printf)]
1191 return []
1192
1193
[email protected]49aa76a2013-12-04 06:59:161194def _CheckForAnonymousVariables(input_api, output_api):
1195 """These types are all expected to hold locks while in scope and
1196 so should never be anonymous (which causes them to be immediately
1197 destroyed)."""
1198 they_who_must_be_named = [
1199 'base::AutoLock',
1200 'base::AutoReset',
1201 'base::AutoUnlock',
1202 'SkAutoAlphaRestore',
1203 'SkAutoBitmapShaderInstall',
1204 'SkAutoBlitterChoose',
1205 'SkAutoBounderCommit',
1206 'SkAutoCallProc',
1207 'SkAutoCanvasRestore',
1208 'SkAutoCommentBlock',
1209 'SkAutoDescriptor',
1210 'SkAutoDisableDirectionCheck',
1211 'SkAutoDisableOvalCheck',
1212 'SkAutoFree',
1213 'SkAutoGlyphCache',
1214 'SkAutoHDC',
1215 'SkAutoLockColors',
1216 'SkAutoLockPixels',
1217 'SkAutoMalloc',
1218 'SkAutoMaskFreeImage',
1219 'SkAutoMutexAcquire',
1220 'SkAutoPathBoundsUpdate',
1221 'SkAutoPDFRelease',
1222 'SkAutoRasterClipValidate',
1223 'SkAutoRef',
1224 'SkAutoTime',
1225 'SkAutoTrace',
1226 'SkAutoUnref',
1227 ]
1228 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1229 # bad: base::AutoLock(lock.get());
1230 # not bad: base::AutoLock lock(lock.get());
1231 bad_pattern = input_api.re.compile(anonymous)
1232 # good: new base::AutoLock(lock.get())
1233 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1234 errors = []
1235
1236 for f in input_api.AffectedFiles():
1237 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1238 continue
1239 for linenum, line in f.ChangedContents():
1240 if bad_pattern.search(line) and not good_pattern.search(line):
1241 errors.append('%s:%d' % (f.LocalPath(), linenum))
1242
1243 if errors:
1244 return [output_api.PresubmitError(
1245 'These lines create anonymous variables that need to be named:',
1246 items=errors)]
1247 return []
1248
1249
[email protected]5fe0f8742013-11-29 01:04:591250def _CheckCygwinShell(input_api, output_api):
1251 source_file_filter = lambda x: input_api.FilterSourceFile(
1252 x, white_list=(r'.+\.(gyp|gypi)$',))
1253 cygwin_shell = []
1254
1255 for f in input_api.AffectedSourceFiles(source_file_filter):
1256 for linenum, line in f.ChangedContents():
1257 if 'msvs_cygwin_shell' in line:
1258 cygwin_shell.append(f.LocalPath())
1259 break
1260
1261 if cygwin_shell:
1262 return [output_api.PresubmitError(
1263 'These files should not use msvs_cygwin_shell (the default is 0):',
1264 items=cygwin_shell)]
1265 return []
1266
[email protected]85218562013-11-22 07:41:401267
[email protected]999261d2014-03-03 20:08:081268def _CheckUserActionUpdate(input_api, output_api):
1269 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521270 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081271 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521272 # If actions.xml is already included in the changelist, the PRESUBMIT
1273 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081274 return []
1275
[email protected]999261d2014-03-03 20:08:081276 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1277 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521278 current_actions = None
[email protected]999261d2014-03-03 20:08:081279 for f in input_api.AffectedFiles(file_filter=file_filter):
1280 for line_num, line in f.ChangedContents():
1281 match = input_api.re.search(action_re, line)
1282 if match:
[email protected]2f92dec2014-03-07 19:21:521283 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1284 # loaded only once.
1285 if not current_actions:
1286 with open('tools/metrics/actions/actions.xml') as actions_f:
1287 current_actions = actions_f.read()
1288 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081289 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521290 action = 'name="{0}"'.format(action_name)
1291 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081292 return [output_api.PresubmitPromptWarning(
1293 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521294 'tools/metrics/actions/actions.xml. Please run '
1295 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081296 % (f.LocalPath(), line_num, action_name))]
1297 return []
1298
1299
[email protected]99171a92014-06-03 08:44:471300def _GetJSONParseError(input_api, filename, eat_comments=True):
1301 try:
1302 contents = input_api.ReadFile(filename)
1303 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131304 import sys
1305 original_sys_path = sys.path
1306 try:
1307 sys.path = sys.path + [input_api.os_path.join(
1308 input_api.PresubmitLocalPath(),
1309 'tools', 'json_comment_eater')]
1310 import json_comment_eater
1311 finally:
1312 sys.path = original_sys_path
1313 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471314
1315 input_api.json.loads(contents)
1316 except ValueError as e:
1317 return e
1318 return None
1319
1320
1321def _GetIDLParseError(input_api, filename):
1322 try:
1323 contents = input_api.ReadFile(filename)
1324 idl_schema = input_api.os_path.join(
1325 input_api.PresubmitLocalPath(),
1326 'tools', 'json_schema_compiler', 'idl_schema.py')
1327 process = input_api.subprocess.Popen(
1328 [input_api.python_executable, idl_schema],
1329 stdin=input_api.subprocess.PIPE,
1330 stdout=input_api.subprocess.PIPE,
1331 stderr=input_api.subprocess.PIPE,
1332 universal_newlines=True)
1333 (_, error) = process.communicate(input=contents)
1334 return error or None
1335 except ValueError as e:
1336 return e
1337
1338
1339def _CheckParseErrors(input_api, output_api):
1340 """Check that IDL and JSON files do not contain syntax errors."""
1341 actions = {
1342 '.idl': _GetIDLParseError,
1343 '.json': _GetJSONParseError,
1344 }
1345 # These paths contain test data and other known invalid JSON files.
1346 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491347 r'test[\\\/]data[\\\/]',
1348 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471349 ]
1350 # Most JSON files are preprocessed and support comments, but these do not.
1351 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491352 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471353 ]
1354 # Only run IDL checker on files in these directories.
1355 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491356 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1357 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471358 ]
1359
1360 def get_action(affected_file):
1361 filename = affected_file.LocalPath()
1362 return actions.get(input_api.os_path.splitext(filename)[1])
1363
1364 def MatchesFile(patterns, path):
1365 for pattern in patterns:
1366 if input_api.re.search(pattern, path):
1367 return True
1368 return False
1369
1370 def FilterFile(affected_file):
1371 action = get_action(affected_file)
1372 if not action:
1373 return False
1374 path = affected_file.LocalPath()
1375
1376 if MatchesFile(excluded_patterns, path):
1377 return False
1378
1379 if (action == _GetIDLParseError and
1380 not MatchesFile(idl_included_patterns, path)):
1381 return False
1382 return True
1383
1384 results = []
1385 for affected_file in input_api.AffectedFiles(
1386 file_filter=FilterFile, include_deletes=False):
1387 action = get_action(affected_file)
1388 kwargs = {}
1389 if (action == _GetJSONParseError and
1390 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1391 kwargs['eat_comments'] = False
1392 parse_error = action(input_api,
1393 affected_file.AbsoluteLocalPath(),
1394 **kwargs)
1395 if parse_error:
1396 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1397 (affected_file.LocalPath(), parse_error)))
1398 return results
1399
1400
[email protected]760deea2013-12-10 19:33:491401def _CheckJavaStyle(input_api, output_api):
1402 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471403 import sys
[email protected]760deea2013-12-10 19:33:491404 original_sys_path = sys.path
1405 try:
1406 sys.path = sys.path + [input_api.os_path.join(
1407 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1408 import checkstyle
1409 finally:
1410 # Restore sys.path to what it was before.
1411 sys.path = original_sys_path
1412
1413 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091414 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511415 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491416
1417
dchenge07de812016-06-20 19:27:171418def _CheckIpcOwners(input_api, output_api):
1419 """Checks that affected files involving IPC have an IPC OWNERS rule.
1420
1421 Whether or not a file affects IPC is determined by a simple whitelist of
1422 filename patterns."""
1423 file_patterns = [
1424 '*_messages.cc',
1425 '*_messages*.h',
1426 '*_param_traits*.*',
1427 '*.mojom',
1428 '*_struct_traits*.*',
1429 '*_type_converter*.*',
1430 # Blink uses a different file naming convention
1431 '*StructTraits*.*',
1432 '*TypeConverter*.*',
1433 ]
1434
1435 # Dictionary mapping an OWNERS file path to Patterns.
1436 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1437 # rules ) to a PatternEntry.
1438 # PatternEntry is a dictionary with two keys:
1439 # - 'files': the files that are matched by this pattern
1440 # - 'rules': the per-file rules needed for this pattern
1441 # For example, if we expect OWNERS file to contain rules for *.mojom and
1442 # *_struct_traits*.*, Patterns might look like this:
1443 # {
1444 # '*.mojom': {
1445 # 'files': ...,
1446 # 'rules': [
1447 # 'per-file *.mojom=set noparent',
1448 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1449 # ],
1450 # },
1451 # '*_struct_traits*.*': {
1452 # 'files': ...,
1453 # 'rules': [
1454 # 'per-file *_struct_traits*.*=set noparent',
1455 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1456 # ],
1457 # },
1458 # }
1459 to_check = {}
1460
1461 # Iterate through the affected files to see what we actually need to check
1462 # for. We should only nag patch authors about per-file rules if a file in that
1463 # directory would match that pattern. If a directory only contains *.mojom
1464 # files and no *_messages*.h files, we should only nag about rules for
1465 # *.mojom files.
rockot51249332016-06-23 16:32:251466 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171467 for pattern in file_patterns:
1468 if input_api.fnmatch.fnmatch(
1469 input_api.os_path.basename(f.LocalPath()), pattern):
1470 owners_file = input_api.os_path.join(
1471 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1472 if owners_file not in to_check:
1473 to_check[owners_file] = {}
1474 if pattern not in to_check[owners_file]:
1475 to_check[owners_file][pattern] = {
1476 'files': [],
1477 'rules': [
1478 'per-file %s=set noparent' % pattern,
1479 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1480 ]
1481 }
1482 to_check[owners_file][pattern]['files'].append(f)
1483 break
1484
1485 # Now go through the OWNERS files we collected, filtering out rules that are
1486 # already present in that OWNERS file.
1487 for owners_file, patterns in to_check.iteritems():
1488 try:
1489 with file(owners_file) as f:
1490 lines = set(f.read().splitlines())
1491 for entry in patterns.itervalues():
1492 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1493 ]
1494 except IOError:
1495 # No OWNERS file, so all the rules are definitely missing.
1496 continue
1497
1498 # All the remaining lines weren't found in OWNERS files, so emit an error.
1499 errors = []
1500 for owners_file, patterns in to_check.iteritems():
1501 missing_lines = []
1502 files = []
1503 for pattern, entry in patterns.iteritems():
1504 missing_lines.extend(entry['rules'])
1505 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1506 if missing_lines:
1507 errors.append(
1508 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1509 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1510
1511 results = []
1512 if errors:
vabrf5ce3bf92016-07-11 14:52:411513 if input_api.is_committing:
1514 output = output_api.PresubmitError
1515 else:
1516 output = output_api.PresubmitPromptWarning
1517 results.append(output(
dchenge07de812016-06-20 19:27:171518 'Found changes to IPC files without a security OWNER!',
1519 long_text='\n\n'.join(errors)))
1520
1521 return results
1522
1523
yzshend99f726a2016-07-25 21:44:231524def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1525 """Checks to make sure that all newly added mojom targets map array/map/string
1526 to STL (for chromium) or WTF (for blink) types.
1527 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1528 """
1529 files = []
1530 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1531 input_api.re.MULTILINE)
1532
1533 for f in input_api.AffectedFiles():
1534 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1535 continue
1536
1537 for _, line in f.ChangedContents():
1538 if pattern.search(line):
1539 files.append(f)
1540 break
1541
1542 if len(files):
1543 return [output_api.PresubmitError(
1544 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1545 'false. The mode is deprecated and will be removed soon.',
1546 files)]
1547 return []
1548
1549
dskiba88634f4e2015-08-14 23:03:291550def _CheckAndroidToastUsage(input_api, output_api):
1551 """Checks that code uses org.chromium.ui.widget.Toast instead of
1552 android.widget.Toast (Chromium Toast doesn't force hardware
1553 acceleration on low-end devices, saving memory).
1554 """
1555 toast_import_pattern = input_api.re.compile(
1556 r'^import android\.widget\.Toast;$')
1557
1558 errors = []
1559
1560 sources = lambda affected_file: input_api.FilterSourceFile(
1561 affected_file,
1562 black_list=(_EXCLUDED_PATHS +
1563 _TEST_CODE_EXCLUDED_PATHS +
1564 input_api.DEFAULT_BLACK_LIST +
1565 (r'^chromecast[\\\/].*',
1566 r'^remoting[\\\/].*')),
1567 white_list=(r'.*\.java$',))
1568
1569 for f in input_api.AffectedSourceFiles(sources):
1570 for line_num, line in f.ChangedContents():
1571 if toast_import_pattern.search(line):
1572 errors.append("%s:%d" % (f.LocalPath(), line_num))
1573
1574 results = []
1575
1576 if errors:
1577 results.append(output_api.PresubmitError(
1578 'android.widget.Toast usage is detected. Android toasts use hardware'
1579 ' acceleration, and can be\ncostly on low-end devices. Please use'
1580 ' org.chromium.ui.widget.Toast instead.\n'
1581 'Contact [email protected] if you have any questions.',
1582 errors))
1583
1584 return results
1585
1586
dgnaa68d5e2015-06-10 10:08:221587def _CheckAndroidCrLogUsage(input_api, output_api):
1588 """Checks that new logs using org.chromium.base.Log:
1589 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511590 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221591 """
pkotwicza1dd0b002016-05-16 14:41:041592
1593 # Do not check format of logs in //chrome/android/webapk because
1594 # //chrome/android/webapk cannot depend on //base
1595 cr_log_check_excluded_paths = [
1596 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1597 ]
1598
dgnaa68d5e2015-06-10 10:08:221599 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121600 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1601 class_in_base_pattern = input_api.re.compile(
1602 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1603 has_some_log_import_pattern = input_api.re.compile(
1604 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221605 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121606 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221607 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511608 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221609 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221610
Vincent Scheib16d7b272015-09-15 18:09:071611 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221612 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041613 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1614 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121615
dgnaa68d5e2015-06-10 10:08:221616 tag_decl_errors = []
1617 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121618 tag_errors = []
dgn38736db2015-09-18 19:20:511619 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121620 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221621
1622 for f in input_api.AffectedSourceFiles(sources):
1623 file_content = input_api.ReadFile(f)
1624 has_modified_logs = False
1625
1626 # Per line checks
dgn87d9fb62015-06-12 09:15:121627 if (cr_log_import_pattern.search(file_content) or
1628 (class_in_base_pattern.search(file_content) and
1629 not has_some_log_import_pattern.search(file_content))):
1630 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221631 for line_num, line in f.ChangedContents():
1632
1633 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121634 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221635 if match:
1636 has_modified_logs = True
1637
1638 # Make sure it uses "TAG"
1639 if not match.group('tag') == 'TAG':
1640 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121641 else:
1642 # Report non cr Log function calls in changed lines
1643 for line_num, line in f.ChangedContents():
1644 if log_call_pattern.search(line):
1645 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221646
1647 # Per file checks
1648 if has_modified_logs:
1649 # Make sure the tag is using the "cr" prefix and is not too long
1650 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511651 tag_name = match.group('name') if match else None
1652 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221653 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511654 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221655 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511656 elif '.' in tag_name:
1657 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221658
1659 results = []
1660 if tag_decl_errors:
1661 results.append(output_api.PresubmitPromptWarning(
1662 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511663 '"private static final String TAG = "<package tag>".\n'
1664 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221665 tag_decl_errors))
1666
1667 if tag_length_errors:
1668 results.append(output_api.PresubmitError(
1669 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511670 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221671 tag_length_errors))
1672
1673 if tag_errors:
1674 results.append(output_api.PresubmitPromptWarning(
1675 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1676 tag_errors))
1677
dgn87d9fb62015-06-12 09:15:121678 if util_log_errors:
dgn4401aa52015-04-29 16:26:171679 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121680 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1681 util_log_errors))
1682
dgn38736db2015-09-18 19:20:511683 if tag_with_dot_errors:
1684 results.append(output_api.PresubmitPromptWarning(
1685 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1686 tag_with_dot_errors))
1687
dgn4401aa52015-04-29 16:26:171688 return results
1689
1690
agrieve7b6479d82015-10-07 14:24:221691def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1692 """Checks if MDPI assets are placed in a correct directory."""
1693 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1694 ('/res/drawable/' in f.LocalPath() or
1695 '/res/drawable-ldrtl/' in f.LocalPath()))
1696 errors = []
1697 for f in input_api.AffectedFiles(include_deletes=False,
1698 file_filter=file_filter):
1699 errors.append(' %s' % f.LocalPath())
1700
1701 results = []
1702 if errors:
1703 results.append(output_api.PresubmitError(
1704 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1705 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1706 '/res/drawable-ldrtl/.\n'
1707 'Contact [email protected] if you have questions.', errors))
1708 return results
1709
1710
agrievef32bcc72016-04-04 14:57:401711class PydepsChecker(object):
1712 def __init__(self, input_api, pydeps_files):
1713 self._file_cache = {}
1714 self._input_api = input_api
1715 self._pydeps_files = pydeps_files
1716
1717 def _LoadFile(self, path):
1718 """Returns the list of paths within a .pydeps file relative to //."""
1719 if path not in self._file_cache:
1720 with open(path) as f:
1721 self._file_cache[path] = f.read()
1722 return self._file_cache[path]
1723
1724 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1725 """Returns an interable of paths within the .pydep, relativized to //."""
1726 os_path = self._input_api.os_path
1727 pydeps_dir = os_path.dirname(pydeps_path)
1728 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1729 if not l.startswith('*'))
1730 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1731
1732 def _CreateFilesToPydepsMap(self):
1733 """Returns a map of local_path -> list_of_pydeps."""
1734 ret = {}
1735 for pydep_local_path in self._pydeps_files:
1736 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1737 ret.setdefault(path, []).append(pydep_local_path)
1738 return ret
1739
1740 def ComputeAffectedPydeps(self):
1741 """Returns an iterable of .pydeps files that might need regenerating."""
1742 affected_pydeps = set()
1743 file_to_pydeps_map = None
1744 for f in self._input_api.AffectedFiles(include_deletes=True):
1745 local_path = f.LocalPath()
1746 if local_path == 'DEPS':
1747 return self._pydeps_files
1748 elif local_path.endswith('.pydeps'):
1749 if local_path in self._pydeps_files:
1750 affected_pydeps.add(local_path)
1751 elif local_path.endswith('.py'):
1752 if file_to_pydeps_map is None:
1753 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1754 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1755 return affected_pydeps
1756
1757 def DetermineIfStale(self, pydeps_path):
1758 """Runs print_python_deps.py to see if the files is stale."""
1759 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1760 cmd = old_pydeps_data[1][1:].strip()
1761 new_pydeps_data = self._input_api.subprocess.check_output(
1762 cmd + ' --output ""', shell=True)
1763 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1764 return cmd
1765
1766
1767def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1768 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001769 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281770 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1771 # Mac, so skip it on other platforms.
1772 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001773 return []
agrievef32bcc72016-04-04 14:57:401774 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1775 is_android = input_api.os_path.exists('third_party/android_tools')
1776 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1777 results = []
1778 # First, check for new / deleted .pydeps.
1779 for f in input_api.AffectedFiles(include_deletes=True):
1780 if f.LocalPath().endswith('.pydeps'):
1781 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1782 results.append(output_api.PresubmitError(
1783 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1784 'remove %s' % f.LocalPath()))
1785 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1786 results.append(output_api.PresubmitError(
1787 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1788 'include %s' % f.LocalPath()))
1789
1790 if results:
1791 return results
1792
1793 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1794
1795 for pydep_path in checker.ComputeAffectedPydeps():
1796 try:
1797 cmd = checker.DetermineIfStale(pydep_path)
1798 if cmd:
1799 results.append(output_api.PresubmitError(
1800 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1801 (pydep_path, cmd)))
1802 except input_api.subprocess.CalledProcessError as error:
1803 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1804 long_text=error.output)]
1805
1806 return results
1807
1808
glidere61efad2015-02-18 17:39:431809def _CheckSingletonInHeaders(input_api, output_api):
1810 """Checks to make sure no header files have |Singleton<|."""
1811 def FileFilter(affected_file):
1812 # It's ok for base/memory/singleton.h to have |Singleton<|.
1813 black_list = (_EXCLUDED_PATHS +
1814 input_api.DEFAULT_BLACK_LIST +
1815 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1816 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1817
sergeyu34d21222015-09-16 00:11:441818 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431819 files = []
1820 for f in input_api.AffectedSourceFiles(FileFilter):
1821 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1822 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1823 contents = input_api.ReadFile(f)
1824 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241825 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431826 pattern.search(line)):
1827 files.append(f)
1828 break
1829
1830 if files:
yolandyandaabc6d2016-04-18 18:29:391831 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441832 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431833 'Please move them to an appropriate source file so that the ' +
1834 'template gets instantiated in a single compilation unit.',
1835 files) ]
1836 return []
1837
1838
dbeam37e8e7402016-02-10 22:58:201839def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1840 """Checks for old style compiled_resources.gyp files."""
1841 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1842
1843 added_compiled_resources = filter(is_compiled_resource, [
1844 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1845 ])
1846
1847 if not added_compiled_resources:
1848 return []
1849
1850 return [output_api.PresubmitError(
1851 "Found new compiled_resources.gyp files:\n%s\n\n"
1852 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551853 "please use compiled_resources2.gyp instead:\n"
1854 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1855 %
dbeam37e8e7402016-02-10 22:58:201856 "\n".join(added_compiled_resources))]
1857
1858
[email protected]fd20b902014-05-09 02:14:531859_DEPRECATED_CSS = [
1860 # Values
1861 ( "-webkit-box", "flex" ),
1862 ( "-webkit-inline-box", "inline-flex" ),
1863 ( "-webkit-flex", "flex" ),
1864 ( "-webkit-inline-flex", "inline-flex" ),
1865 ( "-webkit-min-content", "min-content" ),
1866 ( "-webkit-max-content", "max-content" ),
1867
1868 # Properties
1869 ( "-webkit-background-clip", "background-clip" ),
1870 ( "-webkit-background-origin", "background-origin" ),
1871 ( "-webkit-background-size", "background-size" ),
1872 ( "-webkit-box-shadow", "box-shadow" ),
1873
1874 # Functions
1875 ( "-webkit-gradient", "gradient" ),
1876 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1877 ( "-webkit-linear-gradient", "linear-gradient" ),
1878 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1879 ( "-webkit-radial-gradient", "radial-gradient" ),
1880 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1881]
1882
1883def _CheckNoDeprecatedCSS(input_api, output_api):
1884 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251885 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341886 documentation and iOS CSS for dom distiller
1887 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251888 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531889 results = []
dbeam070cfe62014-10-22 06:44:021890 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251891 black_list = (_EXCLUDED_PATHS +
1892 _TEST_CODE_EXCLUDED_PATHS +
1893 input_api.DEFAULT_BLACK_LIST +
1894 (r"^chrome/common/extensions/docs",
1895 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341896 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051897 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441898 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251899 r"^native_client_sdk"))
1900 file_filter = lambda f: input_api.FilterSourceFile(
1901 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531902 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1903 for line_num, line in fpath.ChangedContents():
1904 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021905 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531906 results.append(output_api.PresubmitError(
1907 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1908 (fpath.LocalPath(), line_num, deprecated_value, value)))
1909 return results
1910
mohan.reddyf21db962014-10-16 12:26:471911
dbeam070cfe62014-10-22 06:44:021912_DEPRECATED_JS = [
1913 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1914 ( "__defineGetter__", "Object.defineProperty" ),
1915 ( "__defineSetter__", "Object.defineProperty" ),
1916]
1917
1918def _CheckNoDeprecatedJS(input_api, output_api):
1919 """Make sure that we don't use deprecated JS in Chrome code."""
1920 results = []
1921 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1922 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1923 input_api.DEFAULT_BLACK_LIST)
1924 file_filter = lambda f: input_api.FilterSourceFile(
1925 f, white_list=file_inclusion_pattern, black_list=black_list)
1926 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1927 for lnum, line in fpath.ChangedContents():
1928 for (deprecated, replacement) in _DEPRECATED_JS:
1929 if deprecated in line:
1930 results.append(output_api.PresubmitError(
1931 "%s:%d: Use of deprecated JS %s, use %s instead" %
1932 (fpath.LocalPath(), lnum, deprecated, replacement)))
1933 return results
1934
1935
dgnaa68d5e2015-06-10 10:08:221936def _AndroidSpecificOnUploadChecks(input_api, output_api):
1937 """Groups checks that target android code."""
1938 results = []
dgnaa68d5e2015-06-10 10:08:221939 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221940 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291941 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221942 return results
1943
1944
[email protected]22c9bd72011-03-27 16:47:391945def _CommonChecks(input_api, output_api):
1946 """Checks common to both upload and commit."""
1947 results = []
1948 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381949 input_api, output_api,
1950 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461951 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191952 results.extend(
[email protected]760deea2013-12-10 19:33:491953 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541954 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181955 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521956 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221957 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441958 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591959 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061960 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121961 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181962 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221963 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491964 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271965 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031966 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491967 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441968 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271969 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541970 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441971 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391972 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551973 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041974 results.extend(
1975 input_api.canned_checks.CheckChangeHasNoTabs(
1976 input_api,
1977 output_api,
1978 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401979 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161980 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591981 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081982 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531983 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021984 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471985 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041986 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231987 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431988 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201989 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401990 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:151991 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:171992 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:231993 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241994
1995 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1996 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1997 input_api, output_api,
1998 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381999 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392000 return results
[email protected]1f7b4172010-01-28 01:17:342001
[email protected]b337cb5b2011-01-23 21:24:052002
[email protected]66daa702011-05-28 14:41:462003def _CheckAuthorizedAuthor(input_api, output_api):
2004 """For non-googler/chromites committers, verify the author's email address is
2005 in AUTHORS.
2006 """
2007 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012008 if not author:
2009 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462010 return []
[email protected]c99663292011-05-31 19:46:082011 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462012 input_api.PresubmitLocalPath(), 'AUTHORS')
2013 valid_authors = (
2014 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2015 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182016 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172017 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2018 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232019 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462020 return [output_api.PresubmitPromptWarning(
2021 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2022 '\n'
2023 'http://www.chromium.org/developers/contributing-code and read the '
2024 '"Legal" section\n'
2025 'If you are a chromite, verify the contributor signed the CLA.') %
2026 author)]
2027 return []
2028
2029
[email protected]b8079ae4a2012-12-05 19:56:492030def _CheckPatchFiles(input_api, output_api):
2031 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2032 if f.LocalPath().endswith(('.orig', '.rej'))]
2033 if problems:
2034 return [output_api.PresubmitError(
2035 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032036 else:
2037 return []
[email protected]b8079ae4a2012-12-05 19:56:492038
2039
[email protected]b00342e7f2013-03-26 16:21:542040def _DidYouMeanOSMacro(bad_macro):
2041 try:
2042 return {'A': 'OS_ANDROID',
2043 'B': 'OS_BSD',
2044 'C': 'OS_CHROMEOS',
2045 'F': 'OS_FREEBSD',
2046 'L': 'OS_LINUX',
2047 'M': 'OS_MACOSX',
2048 'N': 'OS_NACL',
2049 'O': 'OS_OPENBSD',
2050 'P': 'OS_POSIX',
2051 'S': 'OS_SOLARIS',
2052 'W': 'OS_WIN'}[bad_macro[3].upper()]
2053 except KeyError:
2054 return ''
2055
2056
2057def _CheckForInvalidOSMacrosInFile(input_api, f):
2058 """Check for sensible looking, totally invalid OS macros."""
2059 preprocessor_statement = input_api.re.compile(r'^\s*#')
2060 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2061 results = []
2062 for lnum, line in f.ChangedContents():
2063 if preprocessor_statement.search(line):
2064 for match in os_macro.finditer(line):
2065 if not match.group(1) in _VALID_OS_MACROS:
2066 good = _DidYouMeanOSMacro(match.group(1))
2067 did_you_mean = ' (did you mean %s?)' % good if good else ''
2068 results.append(' %s:%d %s%s' % (f.LocalPath(),
2069 lnum,
2070 match.group(1),
2071 did_you_mean))
2072 return results
2073
2074
2075def _CheckForInvalidOSMacros(input_api, output_api):
2076 """Check all affected files for invalid OS macros."""
2077 bad_macros = []
2078 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472079 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542080 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2081
2082 if not bad_macros:
2083 return []
2084
2085 return [output_api.PresubmitError(
2086 'Possibly invalid OS macro[s] found. Please fix your code\n'
2087 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2088
lliabraa35bab3932014-10-01 12:16:442089
2090def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2091 """Check all affected files for invalid "if defined" macros."""
2092 ALWAYS_DEFINED_MACROS = (
2093 "TARGET_CPU_PPC",
2094 "TARGET_CPU_PPC64",
2095 "TARGET_CPU_68K",
2096 "TARGET_CPU_X86",
2097 "TARGET_CPU_ARM",
2098 "TARGET_CPU_MIPS",
2099 "TARGET_CPU_SPARC",
2100 "TARGET_CPU_ALPHA",
2101 "TARGET_IPHONE_SIMULATOR",
2102 "TARGET_OS_EMBEDDED",
2103 "TARGET_OS_IPHONE",
2104 "TARGET_OS_MAC",
2105 "TARGET_OS_UNIX",
2106 "TARGET_OS_WIN32",
2107 )
2108 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2109 results = []
2110 for lnum, line in f.ChangedContents():
2111 for match in ifdef_macro.finditer(line):
2112 if match.group(1) in ALWAYS_DEFINED_MACROS:
2113 always_defined = ' %s is always defined. ' % match.group(1)
2114 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2115 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2116 lnum,
2117 always_defined,
2118 did_you_mean))
2119 return results
2120
2121
2122def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2123 """Check all affected files for invalid "if defined" macros."""
2124 bad_macros = []
2125 for f in input_api.AffectedFiles():
2126 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2127 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2128
2129 if not bad_macros:
2130 return []
2131
2132 return [output_api.PresubmitError(
2133 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2134 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2135 bad_macros)]
2136
2137
mlamouria82272622014-09-16 18:45:042138def _CheckForIPCRules(input_api, output_api):
2139 """Check for same IPC rules described in
2140 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2141 """
2142 base_pattern = r'IPC_ENUM_TRAITS\('
2143 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2144 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2145
2146 problems = []
2147 for f in input_api.AffectedSourceFiles(None):
2148 local_path = f.LocalPath()
2149 if not local_path.endswith('.h'):
2150 continue
2151 for line_number, line in f.ChangedContents():
2152 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2153 problems.append(
2154 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2155
2156 if problems:
2157 return [output_api.PresubmitPromptWarning(
2158 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2159 else:
2160 return []
2161
[email protected]b00342e7f2013-03-26 16:21:542162
mostynbb639aca52015-01-07 20:31:232163def _CheckForWindowsLineEndings(input_api, output_api):
2164 """Check source code and known ascii text files for Windows style line
2165 endings.
2166 """
earthdok1b5e0ee2015-03-10 15:19:102167 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232168
2169 file_inclusion_pattern = (
2170 known_text_files,
2171 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2172 )
2173
2174 filter = lambda f: input_api.FilterSourceFile(
2175 f, white_list=file_inclusion_pattern, black_list=None)
2176 files = [f.LocalPath() for f in
2177 input_api.AffectedSourceFiles(filter)]
2178
2179 problems = []
2180
2181 for file in files:
2182 fp = open(file, 'r')
2183 for line in fp:
2184 if line.endswith('\r\n'):
2185 problems.append(file)
2186 break
2187 fp.close()
2188
2189 if problems:
2190 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2191 'these files to contain Windows style line endings?\n' +
2192 '\n'.join(problems))]
2193
2194 return []
2195
2196
pastarmovj89f7ee12016-09-20 14:58:132197def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2198 lint_filters=None, verbose_level=None):
2199 """Checks that all source files use SYSLOG properly."""
2200 syslog_files = []
2201 for f in input_api.AffectedSourceFiles(source_file_filter):
2202 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2203 syslog_files.append(f.LocalPath())
2204 if syslog_files:
2205 return [output_api.PresubmitPromptWarning(
2206 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2207 ' calls.\nFiles to check:\n', items=syslog_files)]
2208 return []
2209
2210
[email protected]1f7b4172010-01-28 01:17:342211def CheckChangeOnUpload(input_api, output_api):
2212 results = []
2213 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472214 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282215 results.extend(
2216 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192217 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222218 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132219 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542220 return results
[email protected]ca8d19842009-02-19 16:33:122221
2222
[email protected]1bfb8322014-04-23 01:02:412223def GetTryServerMasterForBot(bot):
2224 """Returns the Try Server master for the given bot.
2225
[email protected]0bb112362014-07-26 04:38:322226 It tries to guess the master from the bot name, but may still fail
2227 and return None. There is no longer a default master.
2228 """
2229 # Potentially ambiguous bot names are listed explicitly.
2230 master_map = {
tandriie5587792016-07-14 00:34:502231 'chromium_presubmit': 'master.tryserver.chromium.linux',
2232 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412233 }
[email protected]0bb112362014-07-26 04:38:322234 master = master_map.get(bot)
2235 if not master:
wnwen4fbaab82016-05-25 12:54:362236 if 'android' in bot:
tandriie5587792016-07-14 00:34:502237 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362238 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502239 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322240 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502241 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322242 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502243 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322244 return master
[email protected]1bfb8322014-04-23 01:02:412245
2246
Paweł Hajdan, Jr55083782014-12-19 20:32:562247def GetDefaultTryConfigs(bots):
2248 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012249 """
2250
Paweł Hajdan, Jr55083782014-12-19 20:32:562251 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412252
2253 # Build up the mapping from tryserver master to bot/test.
2254 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562255 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412256 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2257 return out
[email protected]38c6a512013-12-18 23:48:012258
2259
[email protected]ca8d19842009-02-19 16:33:122260def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542261 results = []
[email protected]1f7b4172010-01-28 01:17:342262 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542263 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272264 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342265 input_api,
2266 output_api,
[email protected]2fdd1f362013-01-16 03:56:032267 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272268
[email protected]3e4eb112011-01-18 03:29:542269 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2270 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412271 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2272 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542273 return results