blob: 7d8c4a762fa178d1871a212610cae17588379f72 [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",
[email protected]4306417642009-06-11 00:33:4026)
[email protected]ca8d19842009-02-19 16:33:1227
wnwenbdc444e2016-05-25 13:44:1528
jochen9ea8fdbc2014-09-25 13:21:3529# The NetscapePlugIn library is excluded from pan-project as it will soon
30# be deleted together with the rest of the NPAPI and it's not worthwhile to
31# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3832_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3233 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3834)
35
wnwenbdc444e2016-05-25 13:44:1536
[email protected]06e6d0ff2012-12-11 01:36:4437# Fragment of a regular expression that matches C++ and Objective-C++
38# implementation files.
39_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
40
wnwenbdc444e2016-05-25 13:44:1541
[email protected]06e6d0ff2012-12-11 01:36:4442# Regular expression that matches code only used for test binaries
43# (best effort).
44_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4945 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3247 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1248 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4449 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4950 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0551 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4952 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4453 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4954 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4755 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4956 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0857 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4958 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4459)
[email protected]ca8d19842009-02-19 16:33:1260
wnwenbdc444e2016-05-25 13:44:1561
[email protected]eea609a2011-11-18 13:10:1262_TEST_ONLY_WARNING = (
63 'You might be calling functions intended only for testing from\n'
64 'production code. It is OK to ignore this warning if you know what\n'
65 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5866 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1267
68
[email protected]cf9b78f2012-11-14 11:40:2869_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4070 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2171 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
72 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2873
wnwenbdc444e2016-05-25 13:44:1574
[email protected]127f18ec2012-06-16 05:05:5975_BANNED_OBJC_FUNCTIONS = (
76 (
77 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2078 (
79 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5980 'prohibited. Please use CrTrackingArea instead.',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
82 ),
83 False,
84 ),
85 (
[email protected]eaae1972014-04-16 04:17:2686 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2087 (
88 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5989 'instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
91 ),
92 False,
93 ),
94 (
95 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2096 (
97 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5998 'Please use |convertPoint:(point) fromView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
100 ),
101 True,
102 ),
103 (
104 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20105 (
106 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59107 'Please use |convertPoint:(point) toView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
109 ),
110 True,
111 ),
112 (
113 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20114 (
115 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59116 'Please use |convertRect:(point) fromView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
118 ),
119 True,
120 ),
121 (
122 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20123 (
124 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59125 'Please use |convertRect:(point) toView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
127 ),
128 True,
129 ),
130 (
131 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20132 (
133 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59134 'Please use |convertSize:(point) fromView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
136 ),
137 True,
138 ),
139 (
140 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20141 (
142 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59143 'Please use |convertSize:(point) toView:nil| instead.',
144 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
145 ),
146 True,
147 ),
148)
149
150
151_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20152 # Make sure that gtest's FRIEND_TEST() macro is not used; the
153 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30154 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20155 (
156 'FRIEND_TEST(',
157 (
[email protected]e3c945502012-06-26 20:01:49158 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20159 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
160 ),
161 False,
[email protected]7345da02012-11-27 14:31:49162 (),
[email protected]23e6cbc2012-06-16 18:51:20163 ),
164 (
165 'ScopedAllowIO',
166 (
[email protected]e3c945502012-06-26 20:01:49167 'New code should not use ScopedAllowIO. Post a task to the blocking',
168 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20169 ),
[email protected]e3c945502012-06-26 20:01:49170 True,
[email protected]7345da02012-11-27 14:31:49171 (
nyad2c548b2015-12-09 03:22:32172 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10173 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49174 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22175 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31176 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51177 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
178 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09179 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49180 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
181 r"test_info_extractor\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41182 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
183 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
jamesra03ae492014-10-03 04:26:48184 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
185 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01186 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]1f52a572014-05-12 23:21:54187 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53188 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
189 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45190 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
191 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
192 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
193 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
194 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49195 ),
[email protected]23e6cbc2012-06-16 18:51:20196 ),
[email protected]52657f62013-05-20 05:30:31197 (
tomhudsone2c14d552016-05-26 17:07:46198 'setMatrixClip',
199 (
200 'Overriding setMatrixClip() is prohibited; ',
201 'the base function is deprecated. ',
202 ),
203 True,
204 (),
205 ),
206 (
[email protected]52657f62013-05-20 05:30:31207 'SkRefPtr',
208 (
209 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22210 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31211 ),
212 True,
213 (),
214 ),
215 (
216 'SkAutoRef',
217 (
218 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22219 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31220 ),
221 True,
222 (),
223 ),
224 (
225 'SkAutoTUnref',
226 (
227 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22228 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31229 ),
230 True,
231 (),
232 ),
233 (
234 'SkAutoUnref',
235 (
236 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
237 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22238 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31239 ),
240 True,
241 (),
242 ),
[email protected]d89eec82013-12-03 14:10:59243 (
244 r'/HANDLE_EINTR\(.*close',
245 (
246 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
247 'descriptor will be closed, and it is incorrect to retry the close.',
248 'Either call close directly and ignore its return value, or wrap close',
249 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
250 ),
251 True,
252 (),
253 ),
254 (
255 r'/IGNORE_EINTR\((?!.*close)',
256 (
257 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
258 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
259 ),
260 True,
261 (
262 # Files that #define IGNORE_EINTR.
263 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
264 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
265 ),
266 ),
[email protected]ec5b3f02014-04-04 18:43:43267 (
268 r'/v8::Extension\(',
269 (
270 'Do not introduce new v8::Extensions into the code base, use',
271 'gin::Wrappable instead. See http://crbug.com/334679',
272 ),
273 True,
[email protected]f55c90ee62014-04-12 00:50:03274 (
joaodasilva718f87672014-08-30 09:25:49275 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03276 ),
[email protected]ec5b3f02014-04-04 18:43:43277 ),
skyostilf9469f72015-04-20 10:38:52278 (
jame2d1a952016-04-02 00:27:10279 '#pragma comment(lib,',
280 (
281 'Specify libraries to link with in build files and not in the source.',
282 ),
283 True,
284 (),
285 ),
[email protected]127f18ec2012-06-16 05:05:59286)
287
wnwenbdc444e2016-05-25 13:44:15288
mlamouria82272622014-09-16 18:45:04289_IPC_ENUM_TRAITS_DEPRECATED = (
290 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
291 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
292
[email protected]127f18ec2012-06-16 05:05:59293
[email protected]b00342e7f2013-03-26 16:21:54294_VALID_OS_MACROS = (
295 # Please keep sorted.
296 'OS_ANDROID',
297 'OS_BSD',
298 'OS_CAT', # For testing.
299 'OS_CHROMEOS',
300 'OS_FREEBSD',
301 'OS_IOS',
302 'OS_LINUX',
303 'OS_MACOSX',
304 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21305 'OS_NACL_NONSFI',
306 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54307 'OS_OPENBSD',
308 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37309 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54310 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54311 'OS_WIN',
312)
313
314
agrievef32bcc72016-04-04 14:57:40315_ANDROID_SPECIFIC_PYDEPS_FILES = [
316 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19317 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40318]
319
wnwenbdc444e2016-05-25 13:44:15320
agrievef32bcc72016-04-04 14:57:40321_GENERIC_PYDEPS_FILES = [
322 'build/secondary/tools/swarming_client/isolate.pydeps',
323]
324
wnwenbdc444e2016-05-25 13:44:15325
agrievef32bcc72016-04-04 14:57:40326_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
327
328
[email protected]55459852011-08-10 15:17:19329def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
330 """Attempts to prevent use of functions intended only for testing in
331 non-testing code. For now this is just a best-effort implementation
332 that ignores header files and may have some false positives. A
333 better implementation would probably need a proper C++ parser.
334 """
335 # We only scan .cc files and the like, as the declaration of
336 # for-testing functions in header files are hard to distinguish from
337 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44338 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19339
jochenc0d4808c2015-07-27 09:25:42340 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19341 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09342 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19343 exclusion_pattern = input_api.re.compile(
344 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
345 base_function_pattern, base_function_pattern))
346
347 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44348 black_list = (_EXCLUDED_PATHS +
349 _TEST_CODE_EXCLUDED_PATHS +
350 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19351 return input_api.FilterSourceFile(
352 affected_file,
353 white_list=(file_inclusion_pattern, ),
354 black_list=black_list)
355
356 problems = []
357 for f in input_api.AffectedSourceFiles(FilterFile):
358 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24359 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03360 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46361 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03362 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19363 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03364 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19365
366 if problems:
[email protected]f7051d52013-04-02 18:31:42367 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03368 else:
369 return []
[email protected]55459852011-08-10 15:17:19370
371
[email protected]10689ca2011-09-02 02:31:54372def _CheckNoIOStreamInHeaders(input_api, output_api):
373 """Checks to make sure no .h files include <iostream>."""
374 files = []
375 pattern = input_api.re.compile(r'^#include\s*<iostream>',
376 input_api.re.MULTILINE)
377 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
378 if not f.LocalPath().endswith('.h'):
379 continue
380 contents = input_api.ReadFile(f)
381 if pattern.search(contents):
382 files.append(f)
383
384 if len(files):
yolandyandaabc6d2016-04-18 18:29:39385 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06386 'Do not #include <iostream> in header files, since it inserts static '
387 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54388 '#include <ostream>. See http://crbug.com/94794',
389 files) ]
390 return []
391
392
[email protected]72df4e782012-06-21 16:28:18393def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52394 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18395 problems = []
396 for f in input_api.AffectedFiles():
397 if (not f.LocalPath().endswith(('.cc', '.mm'))):
398 continue
399
400 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04401 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18402 problems.append(' %s:%d' % (f.LocalPath(), line_num))
403
404 if not problems:
405 return []
406 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
407 '\n'.join(problems))]
408
409
danakj61c1aa22015-10-26 19:55:52410def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
411 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
412 errors = []
413 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
414 input_api.re.MULTILINE)
415 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
416 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
417 continue
418 for lnum, line in f.ChangedContents():
419 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17420 errors.append(output_api.PresubmitError(
421 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
422 'DCHECK_IS_ON()", not forgetting the braces.')
423 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52424 return errors
425
426
mcasasb7440c282015-02-04 14:52:19427def _FindHistogramNameInLine(histogram_name, line):
428 """Tries to find a histogram name or prefix in a line."""
429 if not "affected-histogram" in line:
430 return histogram_name in line
431 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
432 # the histogram_name.
433 if not '"' in line:
434 return False
435 histogram_prefix = line.split('\"')[1]
436 return histogram_prefix in histogram_name
437
438
439def _CheckUmaHistogramChanges(input_api, output_api):
440 """Check that UMA histogram names in touched lines can still be found in other
441 lines of the patch or in histograms.xml. Note that this check would not catch
442 the reverse: changes in histograms.xml not matched in the code itself."""
443 touched_histograms = []
444 histograms_xml_modifications = []
445 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
446 for f in input_api.AffectedFiles():
447 # If histograms.xml itself is modified, keep the modified lines for later.
448 if f.LocalPath().endswith(('histograms.xml')):
449 histograms_xml_modifications = f.ChangedContents()
450 continue
451 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
452 continue
453 for line_num, line in f.ChangedContents():
454 found = pattern.search(line)
455 if found:
456 touched_histograms.append([found.group(1), f, line_num])
457
458 # Search for the touched histogram names in the local modifications to
459 # histograms.xml, and, if not found, on the base histograms.xml file.
460 unmatched_histograms = []
461 for histogram_info in touched_histograms:
462 histogram_name_found = False
463 for line_num, line in histograms_xml_modifications:
464 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
465 if histogram_name_found:
466 break
467 if not histogram_name_found:
468 unmatched_histograms.append(histogram_info)
469
eromanb90c82e7e32015-04-01 15:13:49470 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19471 problems = []
472 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49473 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19474 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45475 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19476 histogram_name_found = False
477 for line in histograms_xml:
478 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
479 if histogram_name_found:
480 break
481 if not histogram_name_found:
482 problems.append(' [%s:%d] %s' %
483 (f.LocalPath(), line_num, histogram_name))
484
485 if not problems:
486 return []
487 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
488 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49489 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19490
wnwenbdc444e2016-05-25 13:44:15491
yolandyandaabc6d2016-04-18 18:29:39492def _CheckFlakyTestUsage(input_api, output_api):
493 """Check that FlakyTest annotation is our own instead of the android one"""
494 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
495 files = []
496 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
497 if f.LocalPath().endswith('Test.java'):
498 if pattern.search(input_api.ReadFile(f)):
499 files.append(f)
500 if len(files):
501 return [output_api.PresubmitError(
502 'Use org.chromium.base.test.util.FlakyTest instead of '
503 'android.test.FlakyTest',
504 files)]
505 return []
mcasasb7440c282015-02-04 14:52:19506
wnwenbdc444e2016-05-25 13:44:15507
[email protected]8ea5d4b2011-09-13 21:49:22508def _CheckNoNewWStrings(input_api, output_api):
509 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27510 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22511 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20512 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57513 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34514 '/win/' in f.LocalPath() or
515 'chrome_elf' in f.LocalPath() or
516 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20517 continue
[email protected]8ea5d4b2011-09-13 21:49:22518
[email protected]a11dbe9b2012-08-07 01:32:58519 allowWString = False
[email protected]b5c24292011-11-28 14:38:20520 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58521 if 'presubmit: allow wstring' in line:
522 allowWString = True
523 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27524 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58525 allowWString = False
526 else:
527 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22528
[email protected]55463aa62011-10-12 00:48:27529 if not problems:
530 return []
531 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58532 ' If you are calling a cross-platform API that accepts a wstring, '
533 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27534 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22535
536
[email protected]2a8ac9c2011-10-19 17:20:44537def _CheckNoDEPSGIT(input_api, output_api):
538 """Make sure .DEPS.git is never modified manually."""
539 if any(f.LocalPath().endswith('.DEPS.git') for f in
540 input_api.AffectedFiles()):
541 return [output_api.PresubmitError(
542 'Never commit changes to .DEPS.git. This file is maintained by an\n'
543 'automated system based on what\'s in DEPS and your changes will be\n'
544 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34545 '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:44546 'for more information')]
547 return []
548
549
tandriief664692014-09-23 14:51:47550def _CheckValidHostsInDEPS(input_api, output_api):
551 """Checks that DEPS file deps are from allowed_hosts."""
552 # Run only if DEPS file has been modified to annoy fewer bystanders.
553 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
554 return []
555 # Outsource work to gclient verify
556 try:
557 input_api.subprocess.check_output(['gclient', 'verify'])
558 return []
559 except input_api.subprocess.CalledProcessError, error:
560 return [output_api.PresubmitError(
561 'DEPS file must have only git dependencies.',
562 long_text=error.output)]
563
564
[email protected]127f18ec2012-06-16 05:05:59565def _CheckNoBannedFunctions(input_api, output_api):
566 """Make sure that banned functions are not used."""
567 warnings = []
568 errors = []
569
wnwenbdc444e2016-05-25 13:44:15570 def IsBlacklisted(affected_file, blacklist):
571 local_path = affected_file.LocalPath()
572 for item in blacklist:
573 if input_api.re.match(item, local_path):
574 return True
575 return False
576
577 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
578 matched = False
579 if func_name[0:1] == '/':
580 regex = func_name[1:]
581 if input_api.re.search(regex, line):
582 matched = True
583 elif func_name in line:
dchenge07de812016-06-20 19:27:17584 matched = True
wnwenbdc444e2016-05-25 13:44:15585 if matched:
dchenge07de812016-06-20 19:27:17586 problems = warnings
wnwenbdc444e2016-05-25 13:44:15587 if error:
dchenge07de812016-06-20 19:27:17588 problems = errors
wnwenbdc444e2016-05-25 13:44:15589 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
590 for message_line in message:
591 problems.append(' %s' % message_line)
592
[email protected]127f18ec2012-06-16 05:05:59593 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
594 for f in input_api.AffectedFiles(file_filter=file_filter):
595 for line_num, line in f.ChangedContents():
596 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15597 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59598
599 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
600 for f in input_api.AffectedFiles(file_filter=file_filter):
601 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49602 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49603 if IsBlacklisted(f, excluded_paths):
604 continue
wnwenbdc444e2016-05-25 13:44:15605 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59606
607 result = []
608 if (warnings):
609 result.append(output_api.PresubmitPromptWarning(
610 'Banned functions were used.\n' + '\n'.join(warnings)))
611 if (errors):
612 result.append(output_api.PresubmitError(
613 'Banned functions were used.\n' + '\n'.join(errors)))
614 return result
615
616
[email protected]6c063c62012-07-11 19:11:06617def _CheckNoPragmaOnce(input_api, output_api):
618 """Make sure that banned functions are not used."""
619 files = []
620 pattern = input_api.re.compile(r'^#pragma\s+once',
621 input_api.re.MULTILINE)
622 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
623 if not f.LocalPath().endswith('.h'):
624 continue
625 contents = input_api.ReadFile(f)
626 if pattern.search(contents):
627 files.append(f)
628
629 if files:
630 return [output_api.PresubmitError(
631 'Do not use #pragma once in header files.\n'
632 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
633 files)]
634 return []
635
[email protected]127f18ec2012-06-16 05:05:59636
[email protected]e7479052012-09-19 00:26:12637def _CheckNoTrinaryTrueFalse(input_api, output_api):
638 """Checks to make sure we don't introduce use of foo ? true : false."""
639 problems = []
640 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
641 for f in input_api.AffectedFiles():
642 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
643 continue
644
645 for line_num, line in f.ChangedContents():
646 if pattern.match(line):
647 problems.append(' %s:%d' % (f.LocalPath(), line_num))
648
649 if not problems:
650 return []
651 return [output_api.PresubmitPromptWarning(
652 'Please consider avoiding the "? true : false" pattern if possible.\n' +
653 '\n'.join(problems))]
654
655
[email protected]55f9f382012-07-31 11:02:18656def _CheckUnwantedDependencies(input_api, output_api):
657 """Runs checkdeps on #include statements added in this
658 change. Breaking - rules is an error, breaking ! rules is a
659 warning.
660 """
mohan.reddyf21db962014-10-16 12:26:47661 import sys
[email protected]55f9f382012-07-31 11:02:18662 # We need to wait until we have an input_api object and use this
663 # roundabout construct to import checkdeps because this file is
664 # eval-ed and thus doesn't have __file__.
665 original_sys_path = sys.path
666 try:
667 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47668 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18669 import checkdeps
670 from cpp_checker import CppChecker
671 from rules import Rule
672 finally:
673 # Restore sys.path to what it was before.
674 sys.path = original_sys_path
675
676 added_includes = []
677 for f in input_api.AffectedFiles():
678 if not CppChecker.IsCppFile(f.LocalPath()):
679 continue
680
681 changed_lines = [line for line_num, line in f.ChangedContents()]
682 added_includes.append([f.LocalPath(), changed_lines])
683
[email protected]26385172013-05-09 23:11:35684 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18685
686 error_descriptions = []
687 warning_descriptions = []
688 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
689 added_includes):
690 description_with_path = '%s\n %s' % (path, rule_description)
691 if rule_type == Rule.DISALLOW:
692 error_descriptions.append(description_with_path)
693 else:
694 warning_descriptions.append(description_with_path)
695
696 results = []
697 if error_descriptions:
698 results.append(output_api.PresubmitError(
699 'You added one or more #includes that violate checkdeps rules.',
700 error_descriptions))
701 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42702 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18703 'You added one or more #includes of files that are temporarily\n'
704 'allowed but being removed. Can you avoid introducing the\n'
705 '#include? See relevant DEPS file(s) for details and contacts.',
706 warning_descriptions))
707 return results
708
709
[email protected]fbcafe5a2012-08-08 15:31:22710def _CheckFilePermissions(input_api, output_api):
711 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15712 if input_api.platform == 'win32':
713 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29714 checkperms_tool = input_api.os_path.join(
715 input_api.PresubmitLocalPath(),
716 'tools', 'checkperms', 'checkperms.py')
717 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47718 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22719 for f in input_api.AffectedFiles():
720 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11721 try:
722 input_api.subprocess.check_output(args)
723 return []
724 except input_api.subprocess.CalledProcessError as error:
725 return [output_api.PresubmitError(
726 'checkperms.py failed:',
727 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22728
729
[email protected]c8278b32012-10-30 20:35:49730def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
731 """Makes sure we don't include ui/aura/window_property.h
732 in header files.
733 """
734 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
735 errors = []
736 for f in input_api.AffectedFiles():
737 if not f.LocalPath().endswith('.h'):
738 continue
739 for line_num, line in f.ChangedContents():
740 if pattern.match(line):
741 errors.append(' %s:%d' % (f.LocalPath(), line_num))
742
743 results = []
744 if errors:
745 results.append(output_api.PresubmitError(
746 'Header files should not include ui/aura/window_property.h', errors))
747 return results
748
749
[email protected]cf9b78f2012-11-14 11:40:28750def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
751 """Checks that the lines in scope occur in the right order.
752
753 1. C system files in alphabetical order
754 2. C++ system files in alphabetical order
755 3. Project's .h files
756 """
757
758 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
759 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
760 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
761
762 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
763
764 state = C_SYSTEM_INCLUDES
765
766 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57767 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28768 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55769 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28770 for line_num, line in scope:
771 if c_system_include_pattern.match(line):
772 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55773 problem_linenums.append((line_num, previous_line_num,
774 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28775 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55776 problem_linenums.append((line_num, previous_line_num,
777 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28778 elif cpp_system_include_pattern.match(line):
779 if state == C_SYSTEM_INCLUDES:
780 state = CPP_SYSTEM_INCLUDES
781 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55782 problem_linenums.append((line_num, previous_line_num,
783 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28784 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55785 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28786 elif custom_include_pattern.match(line):
787 if state != CUSTOM_INCLUDES:
788 state = CUSTOM_INCLUDES
789 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55790 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28791 else:
brucedawson70fadb02015-06-30 17:47:55792 problem_linenums.append((line_num, previous_line_num,
793 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28794 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57795 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28796
797 warnings = []
brucedawson70fadb02015-06-30 17:47:55798 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57799 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55800 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28801 return warnings
802
803
[email protected]ac294a12012-12-06 16:38:43804def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28805 """Checks the #include order for the given file f."""
806
[email protected]2299dcf2012-11-15 19:56:24807 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30808 # Exclude the following includes from the check:
809 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
810 # specific order.
811 # 2) <atlbase.h>, "build/build_config.h"
812 excluded_include_pattern = input_api.re.compile(
813 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24814 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33815 # Match the final or penultimate token if it is xxxtest so we can ignore it
816 # when considering the special first include.
817 test_file_tag_pattern = input_api.re.compile(
818 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11819 if_pattern = input_api.re.compile(
820 r'\s*#\s*(if|elif|else|endif|define|undef).*')
821 # Some files need specialized order of includes; exclude such files from this
822 # check.
823 uncheckable_includes_pattern = input_api.re.compile(
824 r'\s*#include '
825 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28826
827 contents = f.NewContents()
828 warnings = []
829 line_num = 0
830
[email protected]ac294a12012-12-06 16:38:43831 # Handle the special first include. If the first include file is
832 # some/path/file.h, the corresponding including file can be some/path/file.cc,
833 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
834 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33835 # If the included file is some/path/file_platform.h the including file could
836 # also be some/path/file_xxxtest_platform.h.
837 including_file_base_name = test_file_tag_pattern.sub(
838 '', input_api.os_path.basename(f.LocalPath()))
839
[email protected]ac294a12012-12-06 16:38:43840 for line in contents:
841 line_num += 1
842 if system_include_pattern.match(line):
843 # No special first include -> process the line again along with normal
844 # includes.
845 line_num -= 1
846 break
847 match = custom_include_pattern.match(line)
848 if match:
849 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33850 header_basename = test_file_tag_pattern.sub(
851 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
852
853 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24854 # No special first include -> process the line again along with normal
855 # includes.
856 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43857 break
[email protected]cf9b78f2012-11-14 11:40:28858
859 # Split into scopes: Each region between #if and #endif is its own scope.
860 scopes = []
861 current_scope = []
862 for line in contents[line_num:]:
863 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11864 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54865 continue
[email protected]2309b0fa02012-11-16 12:18:27866 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28867 scopes.append(current_scope)
868 current_scope = []
[email protected]962f117e2012-11-22 18:11:56869 elif ((system_include_pattern.match(line) or
870 custom_include_pattern.match(line)) and
871 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28872 current_scope.append((line_num, line))
873 scopes.append(current_scope)
874
875 for scope in scopes:
876 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
877 changed_linenums))
878 return warnings
879
880
881def _CheckIncludeOrder(input_api, output_api):
882 """Checks that the #include order is correct.
883
884 1. The corresponding header for source files.
885 2. C system files in alphabetical order
886 3. C++ system files in alphabetical order
887 4. Project's .h files in alphabetical order
888
[email protected]ac294a12012-12-06 16:38:43889 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
890 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28891 """
[email protected]e120b012014-08-15 19:08:35892 def FileFilterIncludeOrder(affected_file):
893 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
894 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28895
896 warnings = []
[email protected]e120b012014-08-15 19:08:35897 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08898 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43899 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
900 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28901
902 results = []
903 if warnings:
[email protected]f7051d52013-04-02 18:31:42904 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53905 warnings))
[email protected]cf9b78f2012-11-14 11:40:28906 return results
907
908
[email protected]70ca77752012-11-20 03:45:03909def _CheckForVersionControlConflictsInFile(input_api, f):
910 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
911 errors = []
912 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23913 if f.LocalPath().endswith('.md'):
914 # First-level headers in markdown look a lot like version control
915 # conflict markers. http://daringfireball.net/projects/markdown/basics
916 continue
[email protected]70ca77752012-11-20 03:45:03917 if pattern.match(line):
918 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
919 return errors
920
921
922def _CheckForVersionControlConflicts(input_api, output_api):
923 """Usually this is not intentional and will cause a compile failure."""
924 errors = []
925 for f in input_api.AffectedFiles():
926 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
927
928 results = []
929 if errors:
930 results.append(output_api.PresubmitError(
931 'Version control conflict markers found, please resolve.', errors))
932 return results
933
934
[email protected]06e6d0ff2012-12-11 01:36:44935def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
936 def FilterFile(affected_file):
937 """Filter function for use with input_api.AffectedSourceFiles,
938 below. This filters out everything except non-test files from
939 top-level directories that generally speaking should not hard-code
940 service URLs (e.g. src/android_webview/, src/content/ and others).
941 """
942 return input_api.FilterSourceFile(
943 affected_file,
[email protected]78bb39d62012-12-11 15:11:56944 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44945 black_list=(_EXCLUDED_PATHS +
946 _TEST_CODE_EXCLUDED_PATHS +
947 input_api.DEFAULT_BLACK_LIST))
948
reillyi38965732015-11-16 18:27:33949 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
950 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46951 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
952 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44953 problems = [] # items are (filename, line_number, line)
954 for f in input_api.AffectedSourceFiles(FilterFile):
955 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46956 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44957 problems.append((f.LocalPath(), line_num, line))
958
959 if problems:
[email protected]f7051d52013-04-02 18:31:42960 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44961 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58962 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44963 [' %s:%d: %s' % (
964 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03965 else:
966 return []
[email protected]06e6d0ff2012-12-11 01:36:44967
968
[email protected]d2530012013-01-25 16:39:27969def _CheckNoAbbreviationInPngFileName(input_api, output_api):
970 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31971 The native_client_sdk directory is excluded because it has auto-generated PNG
972 files for documentation.
[email protected]d2530012013-01-25 16:39:27973 """
[email protected]d2530012013-01-25 16:39:27974 errors = []
binji0dcdf342014-12-12 18:32:31975 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
976 black_list = (r'^native_client_sdk[\\\/]',)
977 file_filter = lambda f: input_api.FilterSourceFile(
978 f, white_list=white_list, black_list=black_list)
979 for f in input_api.AffectedFiles(include_deletes=False,
980 file_filter=file_filter):
981 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27982
983 results = []
984 if errors:
985 results.append(output_api.PresubmitError(
986 'The name of PNG files should not have abbreviations. \n'
987 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
988 'Contact [email protected] if you have questions.', errors))
989 return results
990
991
[email protected]14a6131c2014-01-08 01:15:41992def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:08993 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:41994 a set of DEPS entries that we should look up.
995
996 For a directory (rather than a specific filename) we fake a path to
997 a specific filename by adding /DEPS. This is chosen as a file that
998 will seldom or never be subject to per-file include_rules.
999 """
[email protected]2b438d62013-11-14 17:54:141000 # We ignore deps entries on auto-generated directories.
1001 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081002
1003 # This pattern grabs the path without basename in the first
1004 # parentheses, and the basename (if present) in the second. It
1005 # relies on the simple heuristic that if there is a basename it will
1006 # be a header file ending in ".h".
1007 pattern = re.compile(
1008 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141009 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081010 for changed_line in changed_lines:
1011 m = pattern.match(changed_line)
1012 if m:
1013 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141014 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411015 if m.group(2):
1016 results.add('%s%s' % (path, m.group(2)))
1017 else:
1018 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081019 return results
1020
1021
[email protected]e871964c2013-05-13 14:14:551022def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1023 """When a dependency prefixed with + is added to a DEPS file, we
1024 want to make sure that the change is reviewed by an OWNER of the
1025 target file or directory, to avoid layering violations from being
1026 introduced. This check verifies that this happens.
1027 """
1028 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241029
1030 file_filter = lambda f: not input_api.re.match(
1031 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1032 for f in input_api.AffectedFiles(include_deletes=False,
1033 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551034 filename = input_api.os_path.basename(f.LocalPath())
1035 if filename == 'DEPS':
1036 changed_lines |= set(line.strip()
1037 for line_num, line
1038 in f.ChangedContents())
1039 if not changed_lines:
1040 return []
1041
[email protected]14a6131c2014-01-08 01:15:411042 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1043 changed_lines)
[email protected]e871964c2013-05-13 14:14:551044 if not virtual_depended_on_files:
1045 return []
1046
1047 if input_api.is_committing:
1048 if input_api.tbr:
1049 return [output_api.PresubmitNotifyResult(
1050 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271051 if input_api.dry_run:
1052 return [output_api.PresubmitNotifyResult(
1053 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551054 if not input_api.change.issue:
1055 return [output_api.PresubmitError(
1056 "DEPS approval by OWNERS check failed: this change has "
1057 "no Rietveld issue number, so we can't check it for approvals.")]
1058 output = output_api.PresubmitError
1059 else:
1060 output = output_api.PresubmitNotifyResult
1061
1062 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501063 owner_email, reviewers = (
1064 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1065 input_api,
1066 owners_db.email_regexp,
1067 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551068
1069 owner_email = owner_email or input_api.change.author_email
1070
[email protected]de4f7d22013-05-23 14:27:461071 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511072 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461073 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551074 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1075 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411076
1077 # We strip the /DEPS part that was added by
1078 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1079 # directory.
1080 def StripDeps(path):
1081 start_deps = path.rfind('/DEPS')
1082 if start_deps != -1:
1083 return path[:start_deps]
1084 else:
1085 return path
1086 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551087 for path in missing_files]
1088
1089 if unapproved_dependencies:
1090 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151091 output('You need LGTM from owners of depends-on paths in DEPS that were '
1092 'modified in this CL:\n %s' %
1093 '\n '.join(sorted(unapproved_dependencies)))]
1094 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1095 output_list.append(output(
1096 'Suggested missing target path OWNERS:\n %s' %
1097 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551098 return output_list
1099
1100 return []
1101
1102
[email protected]85218562013-11-22 07:41:401103def _CheckSpamLogging(input_api, output_api):
1104 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1105 black_list = (_EXCLUDED_PATHS +
1106 _TEST_CODE_EXCLUDED_PATHS +
1107 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501108 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191109 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481110 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461111 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121112 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1113 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581114 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161115 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031116 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151117 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1118 r"^chromecast[\\\/]",
1119 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311120 r"^components[\\\/]html_viewer[\\\/]"
1121 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461122 # TODO(peter): Remove this exception. https://crbug.com/534537
1123 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1124 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251125 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1126 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241127 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111128 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151129 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111130 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521131 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501132 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361133 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311134 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131135 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441136 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451137 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021138 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441139 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401140 source_file_filter = lambda x: input_api.FilterSourceFile(
1141 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1142
1143 log_info = []
1144 printf = []
1145
1146 for f in input_api.AffectedSourceFiles(source_file_filter):
1147 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471148 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401149 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471150 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131151 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371152
mohan.reddyf21db962014-10-16 12:26:471153 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371154 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471155 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401156 printf.append(f.LocalPath())
1157
1158 if log_info:
1159 return [output_api.PresubmitError(
1160 'These files spam the console log with LOG(INFO):',
1161 items=log_info)]
1162 if printf:
1163 return [output_api.PresubmitError(
1164 'These files spam the console log with printf/fprintf:',
1165 items=printf)]
1166 return []
1167
1168
[email protected]49aa76a2013-12-04 06:59:161169def _CheckForAnonymousVariables(input_api, output_api):
1170 """These types are all expected to hold locks while in scope and
1171 so should never be anonymous (which causes them to be immediately
1172 destroyed)."""
1173 they_who_must_be_named = [
1174 'base::AutoLock',
1175 'base::AutoReset',
1176 'base::AutoUnlock',
1177 'SkAutoAlphaRestore',
1178 'SkAutoBitmapShaderInstall',
1179 'SkAutoBlitterChoose',
1180 'SkAutoBounderCommit',
1181 'SkAutoCallProc',
1182 'SkAutoCanvasRestore',
1183 'SkAutoCommentBlock',
1184 'SkAutoDescriptor',
1185 'SkAutoDisableDirectionCheck',
1186 'SkAutoDisableOvalCheck',
1187 'SkAutoFree',
1188 'SkAutoGlyphCache',
1189 'SkAutoHDC',
1190 'SkAutoLockColors',
1191 'SkAutoLockPixels',
1192 'SkAutoMalloc',
1193 'SkAutoMaskFreeImage',
1194 'SkAutoMutexAcquire',
1195 'SkAutoPathBoundsUpdate',
1196 'SkAutoPDFRelease',
1197 'SkAutoRasterClipValidate',
1198 'SkAutoRef',
1199 'SkAutoTime',
1200 'SkAutoTrace',
1201 'SkAutoUnref',
1202 ]
1203 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1204 # bad: base::AutoLock(lock.get());
1205 # not bad: base::AutoLock lock(lock.get());
1206 bad_pattern = input_api.re.compile(anonymous)
1207 # good: new base::AutoLock(lock.get())
1208 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1209 errors = []
1210
1211 for f in input_api.AffectedFiles():
1212 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1213 continue
1214 for linenum, line in f.ChangedContents():
1215 if bad_pattern.search(line) and not good_pattern.search(line):
1216 errors.append('%s:%d' % (f.LocalPath(), linenum))
1217
1218 if errors:
1219 return [output_api.PresubmitError(
1220 'These lines create anonymous variables that need to be named:',
1221 items=errors)]
1222 return []
1223
1224
[email protected]5fe0f8742013-11-29 01:04:591225def _CheckCygwinShell(input_api, output_api):
1226 source_file_filter = lambda x: input_api.FilterSourceFile(
1227 x, white_list=(r'.+\.(gyp|gypi)$',))
1228 cygwin_shell = []
1229
1230 for f in input_api.AffectedSourceFiles(source_file_filter):
1231 for linenum, line in f.ChangedContents():
1232 if 'msvs_cygwin_shell' in line:
1233 cygwin_shell.append(f.LocalPath())
1234 break
1235
1236 if cygwin_shell:
1237 return [output_api.PresubmitError(
1238 'These files should not use msvs_cygwin_shell (the default is 0):',
1239 items=cygwin_shell)]
1240 return []
1241
[email protected]85218562013-11-22 07:41:401242
[email protected]999261d2014-03-03 20:08:081243def _CheckUserActionUpdate(input_api, output_api):
1244 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521245 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081246 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521247 # If actions.xml is already included in the changelist, the PRESUBMIT
1248 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081249 return []
1250
[email protected]999261d2014-03-03 20:08:081251 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1252 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521253 current_actions = None
[email protected]999261d2014-03-03 20:08:081254 for f in input_api.AffectedFiles(file_filter=file_filter):
1255 for line_num, line in f.ChangedContents():
1256 match = input_api.re.search(action_re, line)
1257 if match:
[email protected]2f92dec2014-03-07 19:21:521258 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1259 # loaded only once.
1260 if not current_actions:
1261 with open('tools/metrics/actions/actions.xml') as actions_f:
1262 current_actions = actions_f.read()
1263 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081264 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521265 action = 'name="{0}"'.format(action_name)
1266 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081267 return [output_api.PresubmitPromptWarning(
1268 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521269 'tools/metrics/actions/actions.xml. Please run '
1270 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081271 % (f.LocalPath(), line_num, action_name))]
1272 return []
1273
1274
[email protected]99171a92014-06-03 08:44:471275def _GetJSONParseError(input_api, filename, eat_comments=True):
1276 try:
1277 contents = input_api.ReadFile(filename)
1278 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131279 import sys
1280 original_sys_path = sys.path
1281 try:
1282 sys.path = sys.path + [input_api.os_path.join(
1283 input_api.PresubmitLocalPath(),
1284 'tools', 'json_comment_eater')]
1285 import json_comment_eater
1286 finally:
1287 sys.path = original_sys_path
1288 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471289
1290 input_api.json.loads(contents)
1291 except ValueError as e:
1292 return e
1293 return None
1294
1295
1296def _GetIDLParseError(input_api, filename):
1297 try:
1298 contents = input_api.ReadFile(filename)
1299 idl_schema = input_api.os_path.join(
1300 input_api.PresubmitLocalPath(),
1301 'tools', 'json_schema_compiler', 'idl_schema.py')
1302 process = input_api.subprocess.Popen(
1303 [input_api.python_executable, idl_schema],
1304 stdin=input_api.subprocess.PIPE,
1305 stdout=input_api.subprocess.PIPE,
1306 stderr=input_api.subprocess.PIPE,
1307 universal_newlines=True)
1308 (_, error) = process.communicate(input=contents)
1309 return error or None
1310 except ValueError as e:
1311 return e
1312
1313
1314def _CheckParseErrors(input_api, output_api):
1315 """Check that IDL and JSON files do not contain syntax errors."""
1316 actions = {
1317 '.idl': _GetIDLParseError,
1318 '.json': _GetJSONParseError,
1319 }
1320 # These paths contain test data and other known invalid JSON files.
1321 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491322 r'test[\\\/]data[\\\/]',
1323 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471324 ]
1325 # Most JSON files are preprocessed and support comments, but these do not.
1326 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491327 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471328 ]
1329 # Only run IDL checker on files in these directories.
1330 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491331 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1332 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471333 ]
1334
1335 def get_action(affected_file):
1336 filename = affected_file.LocalPath()
1337 return actions.get(input_api.os_path.splitext(filename)[1])
1338
1339 def MatchesFile(patterns, path):
1340 for pattern in patterns:
1341 if input_api.re.search(pattern, path):
1342 return True
1343 return False
1344
1345 def FilterFile(affected_file):
1346 action = get_action(affected_file)
1347 if not action:
1348 return False
1349 path = affected_file.LocalPath()
1350
1351 if MatchesFile(excluded_patterns, path):
1352 return False
1353
1354 if (action == _GetIDLParseError and
1355 not MatchesFile(idl_included_patterns, path)):
1356 return False
1357 return True
1358
1359 results = []
1360 for affected_file in input_api.AffectedFiles(
1361 file_filter=FilterFile, include_deletes=False):
1362 action = get_action(affected_file)
1363 kwargs = {}
1364 if (action == _GetJSONParseError and
1365 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1366 kwargs['eat_comments'] = False
1367 parse_error = action(input_api,
1368 affected_file.AbsoluteLocalPath(),
1369 **kwargs)
1370 if parse_error:
1371 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1372 (affected_file.LocalPath(), parse_error)))
1373 return results
1374
1375
[email protected]760deea2013-12-10 19:33:491376def _CheckJavaStyle(input_api, output_api):
1377 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471378 import sys
[email protected]760deea2013-12-10 19:33:491379 original_sys_path = sys.path
1380 try:
1381 sys.path = sys.path + [input_api.os_path.join(
1382 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1383 import checkstyle
1384 finally:
1385 # Restore sys.path to what it was before.
1386 sys.path = original_sys_path
1387
1388 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091389 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511390 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491391
1392
dchenge07de812016-06-20 19:27:171393def _CheckIpcOwners(input_api, output_api):
1394 """Checks that affected files involving IPC have an IPC OWNERS rule.
1395
1396 Whether or not a file affects IPC is determined by a simple whitelist of
1397 filename patterns."""
1398 file_patterns = [
1399 '*_messages.cc',
1400 '*_messages*.h',
1401 '*_param_traits*.*',
1402 '*.mojom',
1403 '*_struct_traits*.*',
1404 '*_type_converter*.*',
1405 # Blink uses a different file naming convention
1406 '*StructTraits*.*',
1407 '*TypeConverter*.*',
1408 ]
1409
1410 # Dictionary mapping an OWNERS file path to Patterns.
1411 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1412 # rules ) to a PatternEntry.
1413 # PatternEntry is a dictionary with two keys:
1414 # - 'files': the files that are matched by this pattern
1415 # - 'rules': the per-file rules needed for this pattern
1416 # For example, if we expect OWNERS file to contain rules for *.mojom and
1417 # *_struct_traits*.*, Patterns might look like this:
1418 # {
1419 # '*.mojom': {
1420 # 'files': ...,
1421 # 'rules': [
1422 # 'per-file *.mojom=set noparent',
1423 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1424 # ],
1425 # },
1426 # '*_struct_traits*.*': {
1427 # 'files': ...,
1428 # 'rules': [
1429 # 'per-file *_struct_traits*.*=set noparent',
1430 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1431 # ],
1432 # },
1433 # }
1434 to_check = {}
1435
1436 # Iterate through the affected files to see what we actually need to check
1437 # for. We should only nag patch authors about per-file rules if a file in that
1438 # directory would match that pattern. If a directory only contains *.mojom
1439 # files and no *_messages*.h files, we should only nag about rules for
1440 # *.mojom files.
rockot51249332016-06-23 16:32:251441 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171442 for pattern in file_patterns:
1443 if input_api.fnmatch.fnmatch(
1444 input_api.os_path.basename(f.LocalPath()), pattern):
1445 owners_file = input_api.os_path.join(
1446 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1447 if owners_file not in to_check:
1448 to_check[owners_file] = {}
1449 if pattern not in to_check[owners_file]:
1450 to_check[owners_file][pattern] = {
1451 'files': [],
1452 'rules': [
1453 'per-file %s=set noparent' % pattern,
1454 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1455 ]
1456 }
1457 to_check[owners_file][pattern]['files'].append(f)
1458 break
1459
1460 # Now go through the OWNERS files we collected, filtering out rules that are
1461 # already present in that OWNERS file.
1462 for owners_file, patterns in to_check.iteritems():
1463 try:
1464 with file(owners_file) as f:
1465 lines = set(f.read().splitlines())
1466 for entry in patterns.itervalues():
1467 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1468 ]
1469 except IOError:
1470 # No OWNERS file, so all the rules are definitely missing.
1471 continue
1472
1473 # All the remaining lines weren't found in OWNERS files, so emit an error.
1474 errors = []
1475 for owners_file, patterns in to_check.iteritems():
1476 missing_lines = []
1477 files = []
1478 for pattern, entry in patterns.iteritems():
1479 missing_lines.extend(entry['rules'])
1480 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1481 if missing_lines:
1482 errors.append(
1483 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1484 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1485
1486 results = []
1487 if errors:
vabrf5ce3bf92016-07-11 14:52:411488 if input_api.is_committing:
1489 output = output_api.PresubmitError
1490 else:
1491 output = output_api.PresubmitPromptWarning
1492 results.append(output(
dchenge07de812016-06-20 19:27:171493 'Found changes to IPC files without a security OWNER!',
1494 long_text='\n\n'.join(errors)))
1495
1496 return results
1497
1498
yzshend99f726a2016-07-25 21:44:231499def _CheckMojoUsesNewWrapperTypes(input_api, output_api):
1500 """Checks to make sure that all newly added mojom targets map array/map/string
1501 to STL (for chromium) or WTF (for blink) types.
1502 TODO(yzshen): remove this check once crbug.com/624136 is completed.
1503 """
1504 files = []
1505 pattern = input_api.re.compile(r'use_new_wrapper_types.*false',
1506 input_api.re.MULTILINE)
1507
1508 for f in input_api.AffectedFiles():
1509 if not f.LocalPath().endswith(('.gyp', '.gypi', 'gn', 'gni')):
1510 continue
1511
1512 for _, line in f.ChangedContents():
1513 if pattern.search(line):
1514 files.append(f)
1515 break
1516
1517 if len(files):
1518 return [output_api.PresubmitError(
1519 'Do not introduce new mojom targets with use_new_wrapper_types set to '
1520 'false. The mode is deprecated and will be removed soon.',
1521 files)]
1522 return []
1523
1524
dskiba88634f4e2015-08-14 23:03:291525def _CheckAndroidToastUsage(input_api, output_api):
1526 """Checks that code uses org.chromium.ui.widget.Toast instead of
1527 android.widget.Toast (Chromium Toast doesn't force hardware
1528 acceleration on low-end devices, saving memory).
1529 """
1530 toast_import_pattern = input_api.re.compile(
1531 r'^import android\.widget\.Toast;$')
1532
1533 errors = []
1534
1535 sources = lambda affected_file: input_api.FilterSourceFile(
1536 affected_file,
1537 black_list=(_EXCLUDED_PATHS +
1538 _TEST_CODE_EXCLUDED_PATHS +
1539 input_api.DEFAULT_BLACK_LIST +
1540 (r'^chromecast[\\\/].*',
1541 r'^remoting[\\\/].*')),
1542 white_list=(r'.*\.java$',))
1543
1544 for f in input_api.AffectedSourceFiles(sources):
1545 for line_num, line in f.ChangedContents():
1546 if toast_import_pattern.search(line):
1547 errors.append("%s:%d" % (f.LocalPath(), line_num))
1548
1549 results = []
1550
1551 if errors:
1552 results.append(output_api.PresubmitError(
1553 'android.widget.Toast usage is detected. Android toasts use hardware'
1554 ' acceleration, and can be\ncostly on low-end devices. Please use'
1555 ' org.chromium.ui.widget.Toast instead.\n'
1556 'Contact [email protected] if you have any questions.',
1557 errors))
1558
1559 return results
1560
1561
dgnaa68d5e2015-06-10 10:08:221562def _CheckAndroidCrLogUsage(input_api, output_api):
1563 """Checks that new logs using org.chromium.base.Log:
1564 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511565 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221566 """
pkotwicza1dd0b002016-05-16 14:41:041567
1568 # Do not check format of logs in //chrome/android/webapk because
1569 # //chrome/android/webapk cannot depend on //base
1570 cr_log_check_excluded_paths = [
1571 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1572 ]
1573
dgnaa68d5e2015-06-10 10:08:221574 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121575 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1576 class_in_base_pattern = input_api.re.compile(
1577 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1578 has_some_log_import_pattern = input_api.re.compile(
1579 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221580 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121581 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221582 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511583 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221584 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221585
Vincent Scheib16d7b272015-09-15 18:09:071586 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221587 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041588 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1589 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121590
dgnaa68d5e2015-06-10 10:08:221591 tag_decl_errors = []
1592 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121593 tag_errors = []
dgn38736db2015-09-18 19:20:511594 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121595 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221596
1597 for f in input_api.AffectedSourceFiles(sources):
1598 file_content = input_api.ReadFile(f)
1599 has_modified_logs = False
1600
1601 # Per line checks
dgn87d9fb62015-06-12 09:15:121602 if (cr_log_import_pattern.search(file_content) or
1603 (class_in_base_pattern.search(file_content) and
1604 not has_some_log_import_pattern.search(file_content))):
1605 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221606 for line_num, line in f.ChangedContents():
1607
1608 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121609 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221610 if match:
1611 has_modified_logs = True
1612
1613 # Make sure it uses "TAG"
1614 if not match.group('tag') == 'TAG':
1615 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121616 else:
1617 # Report non cr Log function calls in changed lines
1618 for line_num, line in f.ChangedContents():
1619 if log_call_pattern.search(line):
1620 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221621
1622 # Per file checks
1623 if has_modified_logs:
1624 # Make sure the tag is using the "cr" prefix and is not too long
1625 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511626 tag_name = match.group('name') if match else None
1627 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221628 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511629 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221630 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511631 elif '.' in tag_name:
1632 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221633
1634 results = []
1635 if tag_decl_errors:
1636 results.append(output_api.PresubmitPromptWarning(
1637 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511638 '"private static final String TAG = "<package tag>".\n'
1639 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221640 tag_decl_errors))
1641
1642 if tag_length_errors:
1643 results.append(output_api.PresubmitError(
1644 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511645 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221646 tag_length_errors))
1647
1648 if tag_errors:
1649 results.append(output_api.PresubmitPromptWarning(
1650 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1651 tag_errors))
1652
dgn87d9fb62015-06-12 09:15:121653 if util_log_errors:
dgn4401aa52015-04-29 16:26:171654 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121655 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1656 util_log_errors))
1657
dgn38736db2015-09-18 19:20:511658 if tag_with_dot_errors:
1659 results.append(output_api.PresubmitPromptWarning(
1660 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1661 tag_with_dot_errors))
1662
dgn4401aa52015-04-29 16:26:171663 return results
1664
1665
agrieve7b6479d82015-10-07 14:24:221666def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1667 """Checks if MDPI assets are placed in a correct directory."""
1668 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1669 ('/res/drawable/' in f.LocalPath() or
1670 '/res/drawable-ldrtl/' in f.LocalPath()))
1671 errors = []
1672 for f in input_api.AffectedFiles(include_deletes=False,
1673 file_filter=file_filter):
1674 errors.append(' %s' % f.LocalPath())
1675
1676 results = []
1677 if errors:
1678 results.append(output_api.PresubmitError(
1679 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1680 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1681 '/res/drawable-ldrtl/.\n'
1682 'Contact [email protected] if you have questions.', errors))
1683 return results
1684
1685
agrievef32bcc72016-04-04 14:57:401686class PydepsChecker(object):
1687 def __init__(self, input_api, pydeps_files):
1688 self._file_cache = {}
1689 self._input_api = input_api
1690 self._pydeps_files = pydeps_files
1691
1692 def _LoadFile(self, path):
1693 """Returns the list of paths within a .pydeps file relative to //."""
1694 if path not in self._file_cache:
1695 with open(path) as f:
1696 self._file_cache[path] = f.read()
1697 return self._file_cache[path]
1698
1699 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1700 """Returns an interable of paths within the .pydep, relativized to //."""
1701 os_path = self._input_api.os_path
1702 pydeps_dir = os_path.dirname(pydeps_path)
1703 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1704 if not l.startswith('*'))
1705 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1706
1707 def _CreateFilesToPydepsMap(self):
1708 """Returns a map of local_path -> list_of_pydeps."""
1709 ret = {}
1710 for pydep_local_path in self._pydeps_files:
1711 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1712 ret.setdefault(path, []).append(pydep_local_path)
1713 return ret
1714
1715 def ComputeAffectedPydeps(self):
1716 """Returns an iterable of .pydeps files that might need regenerating."""
1717 affected_pydeps = set()
1718 file_to_pydeps_map = None
1719 for f in self._input_api.AffectedFiles(include_deletes=True):
1720 local_path = f.LocalPath()
1721 if local_path == 'DEPS':
1722 return self._pydeps_files
1723 elif local_path.endswith('.pydeps'):
1724 if local_path in self._pydeps_files:
1725 affected_pydeps.add(local_path)
1726 elif local_path.endswith('.py'):
1727 if file_to_pydeps_map is None:
1728 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1729 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1730 return affected_pydeps
1731
1732 def DetermineIfStale(self, pydeps_path):
1733 """Runs print_python_deps.py to see if the files is stale."""
1734 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1735 cmd = old_pydeps_data[1][1:].strip()
1736 new_pydeps_data = self._input_api.subprocess.check_output(
1737 cmd + ' --output ""', shell=True)
1738 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
1739 return cmd
1740
1741
1742def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1743 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001744 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281745 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1746 # Mac, so skip it on other platforms.
1747 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001748 return []
agrievef32bcc72016-04-04 14:57:401749 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1750 is_android = input_api.os_path.exists('third_party/android_tools')
1751 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1752 results = []
1753 # First, check for new / deleted .pydeps.
1754 for f in input_api.AffectedFiles(include_deletes=True):
1755 if f.LocalPath().endswith('.pydeps'):
1756 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1757 results.append(output_api.PresubmitError(
1758 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1759 'remove %s' % f.LocalPath()))
1760 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1761 results.append(output_api.PresubmitError(
1762 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1763 'include %s' % f.LocalPath()))
1764
1765 if results:
1766 return results
1767
1768 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1769
1770 for pydep_path in checker.ComputeAffectedPydeps():
1771 try:
1772 cmd = checker.DetermineIfStale(pydep_path)
1773 if cmd:
1774 results.append(output_api.PresubmitError(
1775 'File is stale: %s\nTo regenerate, run:\n\n %s' %
1776 (pydep_path, cmd)))
1777 except input_api.subprocess.CalledProcessError as error:
1778 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1779 long_text=error.output)]
1780
1781 return results
1782
1783
mnaganov9b9b1fe82014-12-11 16:30:361784def _CheckForCopyrightedCode(input_api, output_api):
1785 """Verifies that newly added code doesn't contain copyrighted material
1786 and is properly licensed under the standard Chromium license.
1787
1788 As there can be false positives, we maintain a whitelist file. This check
1789 also verifies that the whitelist file is up to date.
1790 """
1791 import sys
1792 original_sys_path = sys.path
1793 try:
1794 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221795 input_api.PresubmitLocalPath(), 'tools')]
1796 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361797 finally:
1798 # Restore sys.path to what it was before.
1799 sys.path = original_sys_path
1800
1801 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1802
1803
glidere61efad2015-02-18 17:39:431804def _CheckSingletonInHeaders(input_api, output_api):
1805 """Checks to make sure no header files have |Singleton<|."""
1806 def FileFilter(affected_file):
1807 # It's ok for base/memory/singleton.h to have |Singleton<|.
1808 black_list = (_EXCLUDED_PATHS +
1809 input_api.DEFAULT_BLACK_LIST +
1810 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1811 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1812
sergeyu34d21222015-09-16 00:11:441813 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431814 files = []
1815 for f in input_api.AffectedSourceFiles(FileFilter):
1816 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1817 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1818 contents = input_api.ReadFile(f)
1819 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241820 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431821 pattern.search(line)):
1822 files.append(f)
1823 break
1824
1825 if files:
yolandyandaabc6d2016-04-18 18:29:391826 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441827 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431828 'Please move them to an appropriate source file so that the ' +
1829 'template gets instantiated in a single compilation unit.',
1830 files) ]
1831 return []
1832
1833
dbeam37e8e7402016-02-10 22:58:201834def _CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api):
1835 """Checks for old style compiled_resources.gyp files."""
1836 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1837
1838 added_compiled_resources = filter(is_compiled_resource, [
1839 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1840 ])
1841
1842 if not added_compiled_resources:
1843 return []
1844
1845 return [output_api.PresubmitError(
1846 "Found new compiled_resources.gyp files:\n%s\n\n"
1847 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551848 "please use compiled_resources2.gyp instead:\n"
1849 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1850 %
dbeam37e8e7402016-02-10 22:58:201851 "\n".join(added_compiled_resources))]
1852
1853
[email protected]fd20b902014-05-09 02:14:531854_DEPRECATED_CSS = [
1855 # Values
1856 ( "-webkit-box", "flex" ),
1857 ( "-webkit-inline-box", "inline-flex" ),
1858 ( "-webkit-flex", "flex" ),
1859 ( "-webkit-inline-flex", "inline-flex" ),
1860 ( "-webkit-min-content", "min-content" ),
1861 ( "-webkit-max-content", "max-content" ),
1862
1863 # Properties
1864 ( "-webkit-background-clip", "background-clip" ),
1865 ( "-webkit-background-origin", "background-origin" ),
1866 ( "-webkit-background-size", "background-size" ),
1867 ( "-webkit-box-shadow", "box-shadow" ),
1868
1869 # Functions
1870 ( "-webkit-gradient", "gradient" ),
1871 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1872 ( "-webkit-linear-gradient", "linear-gradient" ),
1873 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1874 ( "-webkit-radial-gradient", "radial-gradient" ),
1875 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1876]
1877
1878def _CheckNoDeprecatedCSS(input_api, output_api):
1879 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251880 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341881 documentation and iOS CSS for dom distiller
1882 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251883 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531884 results = []
dbeam070cfe62014-10-22 06:44:021885 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251886 black_list = (_EXCLUDED_PATHS +
1887 _TEST_CODE_EXCLUDED_PATHS +
1888 input_api.DEFAULT_BLACK_LIST +
1889 (r"^chrome/common/extensions/docs",
1890 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341891 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051892 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441893 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251894 r"^native_client_sdk"))
1895 file_filter = lambda f: input_api.FilterSourceFile(
1896 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531897 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1898 for line_num, line in fpath.ChangedContents():
1899 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021900 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531901 results.append(output_api.PresubmitError(
1902 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1903 (fpath.LocalPath(), line_num, deprecated_value, value)))
1904 return results
1905
mohan.reddyf21db962014-10-16 12:26:471906
dbeam070cfe62014-10-22 06:44:021907_DEPRECATED_JS = [
1908 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1909 ( "__defineGetter__", "Object.defineProperty" ),
1910 ( "__defineSetter__", "Object.defineProperty" ),
1911]
1912
1913def _CheckNoDeprecatedJS(input_api, output_api):
1914 """Make sure that we don't use deprecated JS in Chrome code."""
1915 results = []
1916 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1917 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1918 input_api.DEFAULT_BLACK_LIST)
1919 file_filter = lambda f: input_api.FilterSourceFile(
1920 f, white_list=file_inclusion_pattern, black_list=black_list)
1921 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1922 for lnum, line in fpath.ChangedContents():
1923 for (deprecated, replacement) in _DEPRECATED_JS:
1924 if deprecated in line:
1925 results.append(output_api.PresubmitError(
1926 "%s:%d: Use of deprecated JS %s, use %s instead" %
1927 (fpath.LocalPath(), lnum, deprecated, replacement)))
1928 return results
1929
1930
dgnaa68d5e2015-06-10 10:08:221931def _AndroidSpecificOnUploadChecks(input_api, output_api):
1932 """Groups checks that target android code."""
1933 results = []
dgnaa68d5e2015-06-10 10:08:221934 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221935 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291936 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221937 return results
1938
1939
[email protected]22c9bd72011-03-27 16:47:391940def _CommonChecks(input_api, output_api):
1941 """Checks common to both upload and commit."""
1942 results = []
1943 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381944 input_api, output_api,
1945 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461946 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191947 results.extend(
[email protected]760deea2013-12-10 19:33:491948 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541949 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181950 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521951 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221952 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441953 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591954 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061955 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121956 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181957 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221958 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491959 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271960 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031961 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491962 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441963 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271964 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541965 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441966 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:391967 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551968 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041969 results.extend(
1970 input_api.canned_checks.CheckChangeHasNoTabs(
1971 input_api,
1972 output_api,
1973 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401974 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161975 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591976 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081977 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531978 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021979 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471980 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041981 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361982 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231983 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431984 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam37e8e7402016-02-10 22:58:201985 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api))
agrievef32bcc72016-04-04 14:57:401986 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:151987 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:171988 results.extend(_CheckIpcOwners(input_api, output_api))
yzshend99f726a2016-07-25 21:44:231989 results.extend(_CheckMojoUsesNewWrapperTypes(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241990
1991 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1992 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1993 input_api, output_api,
1994 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381995 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391996 return results
[email protected]1f7b4172010-01-28 01:17:341997
[email protected]b337cb5b2011-01-23 21:24:051998
[email protected]66daa702011-05-28 14:41:461999def _CheckAuthorizedAuthor(input_api, output_api):
2000 """For non-googler/chromites committers, verify the author's email address is
2001 in AUTHORS.
2002 """
2003 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:012004 if not author:
2005 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:462006 return []
[email protected]c99663292011-05-31 19:46:082007 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:462008 input_api.PresubmitLocalPath(), 'AUTHORS')
2009 valid_authors = (
2010 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
2011 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:182012 valid_authors = [item.group(1).lower() for item in valid_authors if item]
dchenge07de812016-06-20 19:27:172013 if not any(input_api.fnmatch.fnmatch(author.lower(), valid)
2014 for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:232015 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:462016 return [output_api.PresubmitPromptWarning(
2017 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
2018 '\n'
2019 'http://www.chromium.org/developers/contributing-code and read the '
2020 '"Legal" section\n'
2021 'If you are a chromite, verify the contributor signed the CLA.') %
2022 author)]
2023 return []
2024
2025
[email protected]b8079ae4a2012-12-05 19:56:492026def _CheckPatchFiles(input_api, output_api):
2027 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2028 if f.LocalPath().endswith(('.orig', '.rej'))]
2029 if problems:
2030 return [output_api.PresubmitError(
2031 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032032 else:
2033 return []
[email protected]b8079ae4a2012-12-05 19:56:492034
2035
[email protected]b00342e7f2013-03-26 16:21:542036def _DidYouMeanOSMacro(bad_macro):
2037 try:
2038 return {'A': 'OS_ANDROID',
2039 'B': 'OS_BSD',
2040 'C': 'OS_CHROMEOS',
2041 'F': 'OS_FREEBSD',
2042 'L': 'OS_LINUX',
2043 'M': 'OS_MACOSX',
2044 'N': 'OS_NACL',
2045 'O': 'OS_OPENBSD',
2046 'P': 'OS_POSIX',
2047 'S': 'OS_SOLARIS',
2048 'W': 'OS_WIN'}[bad_macro[3].upper()]
2049 except KeyError:
2050 return ''
2051
2052
2053def _CheckForInvalidOSMacrosInFile(input_api, f):
2054 """Check for sensible looking, totally invalid OS macros."""
2055 preprocessor_statement = input_api.re.compile(r'^\s*#')
2056 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2057 results = []
2058 for lnum, line in f.ChangedContents():
2059 if preprocessor_statement.search(line):
2060 for match in os_macro.finditer(line):
2061 if not match.group(1) in _VALID_OS_MACROS:
2062 good = _DidYouMeanOSMacro(match.group(1))
2063 did_you_mean = ' (did you mean %s?)' % good if good else ''
2064 results.append(' %s:%d %s%s' % (f.LocalPath(),
2065 lnum,
2066 match.group(1),
2067 did_you_mean))
2068 return results
2069
2070
2071def _CheckForInvalidOSMacros(input_api, output_api):
2072 """Check all affected files for invalid OS macros."""
2073 bad_macros = []
2074 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472075 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542076 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2077
2078 if not bad_macros:
2079 return []
2080
2081 return [output_api.PresubmitError(
2082 'Possibly invalid OS macro[s] found. Please fix your code\n'
2083 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2084
lliabraa35bab3932014-10-01 12:16:442085
2086def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2087 """Check all affected files for invalid "if defined" macros."""
2088 ALWAYS_DEFINED_MACROS = (
2089 "TARGET_CPU_PPC",
2090 "TARGET_CPU_PPC64",
2091 "TARGET_CPU_68K",
2092 "TARGET_CPU_X86",
2093 "TARGET_CPU_ARM",
2094 "TARGET_CPU_MIPS",
2095 "TARGET_CPU_SPARC",
2096 "TARGET_CPU_ALPHA",
2097 "TARGET_IPHONE_SIMULATOR",
2098 "TARGET_OS_EMBEDDED",
2099 "TARGET_OS_IPHONE",
2100 "TARGET_OS_MAC",
2101 "TARGET_OS_UNIX",
2102 "TARGET_OS_WIN32",
2103 )
2104 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2105 results = []
2106 for lnum, line in f.ChangedContents():
2107 for match in ifdef_macro.finditer(line):
2108 if match.group(1) in ALWAYS_DEFINED_MACROS:
2109 always_defined = ' %s is always defined. ' % match.group(1)
2110 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2111 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2112 lnum,
2113 always_defined,
2114 did_you_mean))
2115 return results
2116
2117
2118def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2119 """Check all affected files for invalid "if defined" macros."""
2120 bad_macros = []
2121 for f in input_api.AffectedFiles():
2122 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2123 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2124
2125 if not bad_macros:
2126 return []
2127
2128 return [output_api.PresubmitError(
2129 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2130 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2131 bad_macros)]
2132
2133
mlamouria82272622014-09-16 18:45:042134def _CheckForIPCRules(input_api, output_api):
2135 """Check for same IPC rules described in
2136 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2137 """
2138 base_pattern = r'IPC_ENUM_TRAITS\('
2139 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2140 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2141
2142 problems = []
2143 for f in input_api.AffectedSourceFiles(None):
2144 local_path = f.LocalPath()
2145 if not local_path.endswith('.h'):
2146 continue
2147 for line_number, line in f.ChangedContents():
2148 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2149 problems.append(
2150 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2151
2152 if problems:
2153 return [output_api.PresubmitPromptWarning(
2154 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2155 else:
2156 return []
2157
[email protected]b00342e7f2013-03-26 16:21:542158
mostynbb639aca52015-01-07 20:31:232159def _CheckForWindowsLineEndings(input_api, output_api):
2160 """Check source code and known ascii text files for Windows style line
2161 endings.
2162 """
earthdok1b5e0ee2015-03-10 15:19:102163 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232164
2165 file_inclusion_pattern = (
2166 known_text_files,
2167 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2168 )
2169
2170 filter = lambda f: input_api.FilterSourceFile(
2171 f, white_list=file_inclusion_pattern, black_list=None)
2172 files = [f.LocalPath() for f in
2173 input_api.AffectedSourceFiles(filter)]
2174
2175 problems = []
2176
2177 for file in files:
2178 fp = open(file, 'r')
2179 for line in fp:
2180 if line.endswith('\r\n'):
2181 problems.append(file)
2182 break
2183 fp.close()
2184
2185 if problems:
2186 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2187 'these files to contain Windows style line endings?\n' +
2188 '\n'.join(problems))]
2189
2190 return []
2191
2192
[email protected]1f7b4172010-01-28 01:17:342193def CheckChangeOnUpload(input_api, output_api):
2194 results = []
2195 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472196 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282197 results.extend(
2198 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192199 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222200 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542201 return results
[email protected]ca8d19842009-02-19 16:33:122202
2203
[email protected]1bfb8322014-04-23 01:02:412204def GetTryServerMasterForBot(bot):
2205 """Returns the Try Server master for the given bot.
2206
[email protected]0bb112362014-07-26 04:38:322207 It tries to guess the master from the bot name, but may still fail
2208 and return None. There is no longer a default master.
2209 """
2210 # Potentially ambiguous bot names are listed explicitly.
2211 master_map = {
tandriie5587792016-07-14 00:34:502212 'chromium_presubmit': 'master.tryserver.chromium.linux',
2213 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412214 }
[email protected]0bb112362014-07-26 04:38:322215 master = master_map.get(bot)
2216 if not master:
wnwen4fbaab82016-05-25 12:54:362217 if 'android' in bot:
tandriie5587792016-07-14 00:34:502218 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362219 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502220 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322221 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502222 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322223 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502224 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322225 return master
[email protected]1bfb8322014-04-23 01:02:412226
2227
Paweł Hajdan, Jr55083782014-12-19 20:32:562228def GetDefaultTryConfigs(bots):
2229 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012230 """
2231
Paweł Hajdan, Jr55083782014-12-19 20:32:562232 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412233
2234 # Build up the mapping from tryserver master to bot/test.
2235 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562236 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412237 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2238 return out
[email protected]38c6a512013-12-18 23:48:012239
2240
[email protected]ca8d19842009-02-19 16:33:122241def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542242 results = []
[email protected]1f7b4172010-01-28 01:17:342243 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542244 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272245 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342246 input_api,
2247 output_api,
[email protected]2fdd1f362013-01-16 03:56:032248 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272249
[email protected]3e4eb112011-01-18 03:29:542250 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2251 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412252 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2253 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542254 return results