blob: 5548a58b0d611d8c82d4b9ae7d8dd159d2f793fb [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
calamity8ec9430c2016-08-23 03:56:2926 r".*vulcanized.html$",
27 r".*crisper.js$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d19842009-02-19 16:33:1229
wnwenbdc444e2016-05-25 13:44:1530
[email protected]06e6d0ff2012-12-11 01:36:4431# Fragment of a regular expression that matches C++ and Objective-C++
32# implementation files.
33_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
34
wnwenbdc444e2016-05-25 13:44:1535
[email protected]06e6d0ff2012-12-11 01:36:4436# Regular expression that matches code only used for test binaries
37# (best effort).
38_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4939 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4440 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
sdefresne1fccb0a2016-12-19 08:10:5341 r'.+_(api|browser|eg|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1242 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4944 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0545 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4946 r'content[\\\/]shell[\\\/].*',
[email protected]7b054982013-11-27 00:44:4747 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4948 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0849 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4950 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4451)
[email protected]ca8d19842009-02-19 16:33:1252
wnwenbdc444e2016-05-25 13:44:1553
[email protected]eea609a2011-11-18 13:10:1254_TEST_ONLY_WARNING = (
55 'You might be calling functions intended only for testing from\n'
56 'production code. It is OK to ignore this warning if you know what\n'
57 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5858 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1259
60
[email protected]cf9b78f2012-11-14 11:40:2861_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4062 'Your #include order seems to be broken. Remember to use the right '
avice9a8982015-11-24 20:36:2163 'collation (LC_COLLATE=C) and check\nhttps://google.github.io/styleguide/'
64 'cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2865
wnwenbdc444e2016-05-25 13:44:1566
[email protected]127f18ec2012-06-16 05:05:5967_BANNED_OBJC_FUNCTIONS = (
68 (
69 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2070 (
71 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5972 'prohibited. Please use CrTrackingArea instead.',
73 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
74 ),
75 False,
76 ),
77 (
[email protected]eaae1972014-04-16 04:17:2678 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2079 (
80 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5981 'instead.',
82 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
83 ),
84 False,
85 ),
86 (
87 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2088 (
89 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5990 'Please use |convertPoint:(point) fromView:nil| instead.',
91 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
92 ),
93 True,
94 ),
95 (
96 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2097 (
98 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5999 'Please use |convertPoint:(point) toView:nil| instead.',
100 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
101 ),
102 True,
103 ),
104 (
105 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20106 (
107 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59108 'Please use |convertRect:(point) fromView:nil| instead.',
109 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
110 ),
111 True,
112 ),
113 (
114 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20115 (
116 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59117 'Please use |convertRect:(point) toView:nil| instead.',
118 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
119 ),
120 True,
121 ),
122 (
123 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20124 (
125 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59126 'Please use |convertSize:(point) fromView:nil| instead.',
127 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
128 ),
129 True,
130 ),
131 (
132 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20133 (
134 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59135 'Please use |convertSize:(point) toView:nil| instead.',
136 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
137 ),
138 True,
139 ),
jif65398702016-10-27 10:19:48140 (
141 r"/\s+UTF8String\s*]",
142 (
143 'The use of -[NSString UTF8String] is dangerous as it can return null',
144 'even if |canBeConvertedToEncoding:NSUTF8StringEncoding| returns YES.',
145 'Please use |SysNSStringToUTF8| instead.',
146 ),
147 True,
148 ),
[email protected]127f18ec2012-06-16 05:05:59149)
150
151
152_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20153 # Make sure that gtest's FRIEND_TEST() macro is not used; the
154 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30155 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20156 (
157 'FRIEND_TEST(',
158 (
[email protected]e3c945502012-06-26 20:01:49159 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20160 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
161 ),
162 False,
[email protected]7345da02012-11-27 14:31:49163 (),
[email protected]23e6cbc2012-06-16 18:51:20164 ),
165 (
thomasanderson4b569052016-09-14 20:15:53166 r'XSelectInput|CWEventMask|XCB_CW_EVENT_MASK',
167 (
168 'Chrome clients wishing to select events on X windows should use',
169 'ui::XScopedEventSelector. It is safe to ignore this warning only if',
170 'you are selecting events from the GPU process, or if you are using',
171 'an XDisplay other than gfx::GetXDisplay().',
172 ),
173 True,
174 (
175 r"^ui[\\\/]gl[\\\/].*\.cc$",
176 r"^media[\\\/]gpu[\\\/].*\.cc$",
177 r"^gpu[\\\/].*\.cc$",
178 ),
179 ),
180 (
[email protected]23e6cbc2012-06-16 18:51:20181 'ScopedAllowIO',
182 (
[email protected]e3c945502012-06-26 20:01:49183 'New code should not use ScopedAllowIO. Post a task to the blocking',
184 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20185 ),
[email protected]e3c945502012-06-26 20:01:49186 True,
[email protected]7345da02012-11-27 14:31:49187 (
nyad2c548b2015-12-09 03:22:32188 r"^base[\\\/]process[\\\/]process_linux\.cc$",
thestig75844fdb2014-09-09 19:47:10189 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
kmarshallbb619532016-01-29 21:24:49190 r"^blimp[\\\/]engine[\\\/]app[\\\/]blimp_browser_main_parts\.cc$",
tfarina0923ac52015-01-07 03:21:22191 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
sky0e07a142016-03-25 21:27:31192 r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
alematee4016bb2014-11-12 17:38:51193 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
194 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09195 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
jochene9ba6dd2016-02-23 17:20:49196 r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
197 r"test_info_extractor\.cc$",
lukasza7947ccd2016-07-28 21:56:25198 r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
[email protected]de7d61ff2013-08-20 11:30:41199 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
200 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
lukasza7947ccd2016-07-28 21:56:25201 r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
jamesra03ae492014-10-03 04:26:48202 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
203 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01204 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
lukasza7947ccd2016-07-28 21:56:25205 r"^net[\\\/]cert[\\\/]test_root_certs\.cc$",
206 r"^net[\\\/]test[\\\/]embedded_test_server[\\\/]" +
207 r"embedded_test_server\.cc$",
208 r"^net[\\\/]test[\\\/]spawned_test_server[\\\/]local_test_server\.cc$",
209 r"^net[\\\/]test[\\\/]test_data_directory\.cc$",
[email protected]1f52a572014-05-12 23:21:54210 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu2c41f9842016-12-10 01:45:16211 r"^remoting[\\\/]protocol[\\\/]webrtc_transport\.cc$",
lambroslambrouf6fb94ea2016-06-27 21:21:53212 r"^ui[\\\/]base[\\\/]material_design[\\\/]"
213 "material_design_controller\.cc$",
kylechar16666242016-07-04 20:54:45214 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_mac\.cc$",
215 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_win\.cc$",
216 r"^ui[\\\/]gl[\\\/]init[\\\/]gl_initializer_x11\.cc$",
217 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
218 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49219 ),
[email protected]23e6cbc2012-06-16 18:51:20220 ),
[email protected]52657f62013-05-20 05:30:31221 (
tomhudsone2c14d552016-05-26 17:07:46222 'setMatrixClip',
223 (
224 'Overriding setMatrixClip() is prohibited; ',
225 'the base function is deprecated. ',
226 ),
227 True,
228 (),
229 ),
230 (
[email protected]52657f62013-05-20 05:30:31231 'SkRefPtr',
232 (
233 'The use of SkRefPtr is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22234 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31235 ),
236 True,
237 (),
238 ),
239 (
240 'SkAutoRef',
241 (
242 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
tomhudson7e6e0512016-04-19 19:27:22243 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31244 ),
245 True,
246 (),
247 ),
248 (
249 'SkAutoTUnref',
250 (
251 'The use of SkAutoTUnref is dangerous because it implicitly ',
tomhudson7e6e0512016-04-19 19:27:22252 'converts to a raw pointer. Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31253 ),
254 True,
255 (),
256 ),
257 (
258 'SkAutoUnref',
259 (
260 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
261 'because it implicitly converts to a raw pointer. ',
tomhudson7e6e0512016-04-19 19:27:22262 'Please use sk_sp<> instead.'
[email protected]52657f62013-05-20 05:30:31263 ),
264 True,
265 (),
266 ),
[email protected]d89eec82013-12-03 14:10:59267 (
268 r'/HANDLE_EINTR\(.*close',
269 (
270 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
271 'descriptor will be closed, and it is incorrect to retry the close.',
272 'Either call close directly and ignore its return value, or wrap close',
273 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
274 ),
275 True,
276 (),
277 ),
278 (
279 r'/IGNORE_EINTR\((?!.*close)',
280 (
281 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
282 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
283 ),
284 True,
285 (
286 # Files that #define IGNORE_EINTR.
287 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
288 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
289 ),
290 ),
[email protected]ec5b3f02014-04-04 18:43:43291 (
292 r'/v8::Extension\(',
293 (
294 'Do not introduce new v8::Extensions into the code base, use',
295 'gin::Wrappable instead. See http://crbug.com/334679',
296 ),
297 True,
[email protected]f55c90ee62014-04-12 00:50:03298 (
joaodasilva718f87672014-08-30 09:25:49299 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03300 ),
[email protected]ec5b3f02014-04-04 18:43:43301 ),
skyostilf9469f72015-04-20 10:38:52302 (
jame2d1a952016-04-02 00:27:10303 '#pragma comment(lib,',
304 (
305 'Specify libraries to link with in build files and not in the source.',
306 ),
307 True,
308 (),
309 ),
[email protected]127f18ec2012-06-16 05:05:59310)
311
wnwenbdc444e2016-05-25 13:44:15312
mlamouria82272622014-09-16 18:45:04313_IPC_ENUM_TRAITS_DEPRECATED = (
314 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
315 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
316
[email protected]127f18ec2012-06-16 05:05:59317
[email protected]b00342e7f2013-03-26 16:21:54318_VALID_OS_MACROS = (
319 # Please keep sorted.
320 'OS_ANDROID',
321 'OS_BSD',
322 'OS_CAT', # For testing.
323 'OS_CHROMEOS',
324 'OS_FREEBSD',
325 'OS_IOS',
326 'OS_LINUX',
327 'OS_MACOSX',
328 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21329 'OS_NACL_NONSFI',
330 'OS_NACL_SFI',
krytarowski969759f2016-07-31 23:55:12331 'OS_NETBSD',
[email protected]b00342e7f2013-03-26 16:21:54332 'OS_OPENBSD',
333 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37334 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54335 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54336 'OS_WIN',
337)
338
339
agrievef32bcc72016-04-04 14:57:40340_ANDROID_SPECIFIC_PYDEPS_FILES = [
341 'build/android/test_runner.pydeps',
agrieve732db3a2016-04-26 19:18:19342 'net/tools/testserver/testserver.pydeps',
agrievef32bcc72016-04-04 14:57:40343]
344
wnwenbdc444e2016-05-25 13:44:15345
agrievef32bcc72016-04-04 14:57:40346_GENERIC_PYDEPS_FILES = [
agrievef32bcc72016-04-04 14:57:40347]
348
wnwenbdc444e2016-05-25 13:44:15349
agrievef32bcc72016-04-04 14:57:40350_ALL_PYDEPS_FILES = _ANDROID_SPECIFIC_PYDEPS_FILES + _GENERIC_PYDEPS_FILES
351
352
[email protected]55459852011-08-10 15:17:19353def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
354 """Attempts to prevent use of functions intended only for testing in
355 non-testing code. For now this is just a best-effort implementation
356 that ignores header files and may have some false positives. A
357 better implementation would probably need a proper C++ parser.
358 """
359 # We only scan .cc files and the like, as the declaration of
360 # for-testing functions in header files are hard to distinguish from
361 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44362 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19363
jochenc0d4808c2015-07-27 09:25:42364 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19365 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09366 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19367 exclusion_pattern = input_api.re.compile(
368 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
369 base_function_pattern, base_function_pattern))
370
371 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44372 black_list = (_EXCLUDED_PATHS +
373 _TEST_CODE_EXCLUDED_PATHS +
374 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19375 return input_api.FilterSourceFile(
376 affected_file,
377 white_list=(file_inclusion_pattern, ),
378 black_list=black_list)
379
380 problems = []
381 for f in input_api.AffectedSourceFiles(FilterFile):
382 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24383 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03384 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46385 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03386 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19387 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03388 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19389
390 if problems:
[email protected]f7051d52013-04-02 18:31:42391 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03392 else:
393 return []
[email protected]55459852011-08-10 15:17:19394
395
[email protected]10689ca2011-09-02 02:31:54396def _CheckNoIOStreamInHeaders(input_api, output_api):
397 """Checks to make sure no .h files include <iostream>."""
398 files = []
399 pattern = input_api.re.compile(r'^#include\s*<iostream>',
400 input_api.re.MULTILINE)
401 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
402 if not f.LocalPath().endswith('.h'):
403 continue
404 contents = input_api.ReadFile(f)
405 if pattern.search(contents):
406 files.append(f)
407
408 if len(files):
yolandyandaabc6d2016-04-18 18:29:39409 return [output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06410 'Do not #include <iostream> in header files, since it inserts static '
411 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54412 '#include <ostream>. See http://crbug.com/94794',
413 files) ]
414 return []
415
416
[email protected]72df4e782012-06-21 16:28:18417def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52418 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18419 problems = []
420 for f in input_api.AffectedFiles():
421 if (not f.LocalPath().endswith(('.cc', '.mm'))):
422 continue
423
424 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04425 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18426 problems.append(' %s:%d' % (f.LocalPath(), line_num))
427
428 if not problems:
429 return []
430 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
431 '\n'.join(problems))]
432
433
danakj61c1aa22015-10-26 19:55:52434def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
435 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
436 errors = []
437 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
438 input_api.re.MULTILINE)
439 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
440 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
441 continue
442 for lnum, line in f.ChangedContents():
443 if input_api.re.search(pattern, line):
dchenge07de812016-06-20 19:27:17444 errors.append(output_api.PresubmitError(
445 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
446 'DCHECK_IS_ON()", not forgetting the braces.')
447 % (f.LocalPath(), lnum)))
danakj61c1aa22015-10-26 19:55:52448 return errors
449
450
mcasasb7440c282015-02-04 14:52:19451def _FindHistogramNameInLine(histogram_name, line):
452 """Tries to find a histogram name or prefix in a line."""
453 if not "affected-histogram" in line:
454 return histogram_name in line
455 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
456 # the histogram_name.
457 if not '"' in line:
458 return False
459 histogram_prefix = line.split('\"')[1]
460 return histogram_prefix in histogram_name
461
462
463def _CheckUmaHistogramChanges(input_api, output_api):
464 """Check that UMA histogram names in touched lines can still be found in other
465 lines of the patch or in histograms.xml. Note that this check would not catch
466 the reverse: changes in histograms.xml not matched in the code itself."""
467 touched_histograms = []
468 histograms_xml_modifications = []
469 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
470 for f in input_api.AffectedFiles():
471 # If histograms.xml itself is modified, keep the modified lines for later.
472 if f.LocalPath().endswith(('histograms.xml')):
473 histograms_xml_modifications = f.ChangedContents()
474 continue
475 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
476 continue
477 for line_num, line in f.ChangedContents():
478 found = pattern.search(line)
479 if found:
480 touched_histograms.append([found.group(1), f, line_num])
481
482 # Search for the touched histogram names in the local modifications to
483 # histograms.xml, and, if not found, on the base histograms.xml file.
484 unmatched_histograms = []
485 for histogram_info in touched_histograms:
486 histogram_name_found = False
487 for line_num, line in histograms_xml_modifications:
488 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
489 if histogram_name_found:
490 break
491 if not histogram_name_found:
492 unmatched_histograms.append(histogram_info)
493
eromanb90c82e7e32015-04-01 15:13:49494 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19495 problems = []
496 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49497 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19498 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45499 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19500 histogram_name_found = False
501 for line in histograms_xml:
502 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
503 if histogram_name_found:
504 break
505 if not histogram_name_found:
506 problems.append(' [%s:%d] %s' %
507 (f.LocalPath(), line_num, histogram_name))
508
509 if not problems:
510 return []
511 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
512 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49513 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19514
wnwenbdc444e2016-05-25 13:44:15515
yolandyandaabc6d2016-04-18 18:29:39516def _CheckFlakyTestUsage(input_api, output_api):
517 """Check that FlakyTest annotation is our own instead of the android one"""
518 pattern = input_api.re.compile(r'import android.test.FlakyTest;')
519 files = []
520 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
521 if f.LocalPath().endswith('Test.java'):
522 if pattern.search(input_api.ReadFile(f)):
523 files.append(f)
524 if len(files):
525 return [output_api.PresubmitError(
526 'Use org.chromium.base.test.util.FlakyTest instead of '
527 'android.test.FlakyTest',
528 files)]
529 return []
mcasasb7440c282015-02-04 14:52:19530
wnwenbdc444e2016-05-25 13:44:15531
[email protected]8ea5d4b2011-09-13 21:49:22532def _CheckNoNewWStrings(input_api, output_api):
533 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27534 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22535 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20536 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57537 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
pennymac84fd6692016-07-13 22:35:34538 '/win/' in f.LocalPath() or
539 'chrome_elf' in f.LocalPath() or
540 'install_static' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20541 continue
[email protected]8ea5d4b2011-09-13 21:49:22542
[email protected]a11dbe9b2012-08-07 01:32:58543 allowWString = False
[email protected]b5c24292011-11-28 14:38:20544 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58545 if 'presubmit: allow wstring' in line:
546 allowWString = True
547 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27548 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58549 allowWString = False
550 else:
551 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22552
[email protected]55463aa62011-10-12 00:48:27553 if not problems:
554 return []
555 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58556 ' If you are calling a cross-platform API that accepts a wstring, '
557 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27558 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22559
560
[email protected]2a8ac9c2011-10-19 17:20:44561def _CheckNoDEPSGIT(input_api, output_api):
562 """Make sure .DEPS.git is never modified manually."""
563 if any(f.LocalPath().endswith('.DEPS.git') for f in
564 input_api.AffectedFiles()):
565 return [output_api.PresubmitError(
566 'Never commit changes to .DEPS.git. This file is maintained by an\n'
567 'automated system based on what\'s in DEPS and your changes will be\n'
568 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34569 '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:44570 'for more information')]
571 return []
572
573
tandriief664692014-09-23 14:51:47574def _CheckValidHostsInDEPS(input_api, output_api):
575 """Checks that DEPS file deps are from allowed_hosts."""
576 # Run only if DEPS file has been modified to annoy fewer bystanders.
577 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
578 return []
579 # Outsource work to gclient verify
580 try:
581 input_api.subprocess.check_output(['gclient', 'verify'])
582 return []
583 except input_api.subprocess.CalledProcessError, error:
584 return [output_api.PresubmitError(
585 'DEPS file must have only git dependencies.',
586 long_text=error.output)]
587
588
[email protected]127f18ec2012-06-16 05:05:59589def _CheckNoBannedFunctions(input_api, output_api):
590 """Make sure that banned functions are not used."""
591 warnings = []
592 errors = []
593
wnwenbdc444e2016-05-25 13:44:15594 def IsBlacklisted(affected_file, blacklist):
595 local_path = affected_file.LocalPath()
596 for item in blacklist:
597 if input_api.re.match(item, local_path):
598 return True
599 return False
600
601 def CheckForMatch(affected_file, line_num, line, func_name, message, error):
602 matched = False
603 if func_name[0:1] == '/':
604 regex = func_name[1:]
605 if input_api.re.search(regex, line):
606 matched = True
607 elif func_name in line:
dchenge07de812016-06-20 19:27:17608 matched = True
wnwenbdc444e2016-05-25 13:44:15609 if matched:
dchenge07de812016-06-20 19:27:17610 problems = warnings
wnwenbdc444e2016-05-25 13:44:15611 if error:
dchenge07de812016-06-20 19:27:17612 problems = errors
wnwenbdc444e2016-05-25 13:44:15613 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num))
614 for message_line in message:
615 problems.append(' %s' % message_line)
616
[email protected]127f18ec2012-06-16 05:05:59617 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
618 for f in input_api.AffectedFiles(file_filter=file_filter):
619 for line_num, line in f.ChangedContents():
620 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
wnwenbdc444e2016-05-25 13:44:15621 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59622
623 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
624 for f in input_api.AffectedFiles(file_filter=file_filter):
625 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49626 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
[email protected]7345da02012-11-27 14:31:49627 if IsBlacklisted(f, excluded_paths):
628 continue
wnwenbdc444e2016-05-25 13:44:15629 CheckForMatch(f, line_num, line, func_name, message, error)
[email protected]127f18ec2012-06-16 05:05:59630
631 result = []
632 if (warnings):
633 result.append(output_api.PresubmitPromptWarning(
634 'Banned functions were used.\n' + '\n'.join(warnings)))
635 if (errors):
636 result.append(output_api.PresubmitError(
637 'Banned functions were used.\n' + '\n'.join(errors)))
638 return result
639
640
[email protected]6c063c62012-07-11 19:11:06641def _CheckNoPragmaOnce(input_api, output_api):
642 """Make sure that banned functions are not used."""
643 files = []
644 pattern = input_api.re.compile(r'^#pragma\s+once',
645 input_api.re.MULTILINE)
646 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
647 if not f.LocalPath().endswith('.h'):
648 continue
649 contents = input_api.ReadFile(f)
650 if pattern.search(contents):
651 files.append(f)
652
653 if files:
654 return [output_api.PresubmitError(
655 'Do not use #pragma once in header files.\n'
656 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
657 files)]
658 return []
659
[email protected]127f18ec2012-06-16 05:05:59660
[email protected]e7479052012-09-19 00:26:12661def _CheckNoTrinaryTrueFalse(input_api, output_api):
662 """Checks to make sure we don't introduce use of foo ? true : false."""
663 problems = []
664 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
665 for f in input_api.AffectedFiles():
666 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
667 continue
668
669 for line_num, line in f.ChangedContents():
670 if pattern.match(line):
671 problems.append(' %s:%d' % (f.LocalPath(), line_num))
672
673 if not problems:
674 return []
675 return [output_api.PresubmitPromptWarning(
676 'Please consider avoiding the "? true : false" pattern if possible.\n' +
677 '\n'.join(problems))]
678
679
[email protected]55f9f382012-07-31 11:02:18680def _CheckUnwantedDependencies(input_api, output_api):
681 """Runs checkdeps on #include statements added in this
682 change. Breaking - rules is an error, breaking ! rules is a
683 warning.
684 """
mohan.reddyf21db962014-10-16 12:26:47685 import sys
[email protected]55f9f382012-07-31 11:02:18686 # We need to wait until we have an input_api object and use this
687 # roundabout construct to import checkdeps because this file is
688 # eval-ed and thus doesn't have __file__.
689 original_sys_path = sys.path
690 try:
691 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47692 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18693 import checkdeps
694 from cpp_checker import CppChecker
695 from rules import Rule
696 finally:
697 # Restore sys.path to what it was before.
698 sys.path = original_sys_path
699
700 added_includes = []
701 for f in input_api.AffectedFiles():
702 if not CppChecker.IsCppFile(f.LocalPath()):
703 continue
704
705 changed_lines = [line for line_num, line in f.ChangedContents()]
706 added_includes.append([f.LocalPath(), changed_lines])
707
[email protected]26385172013-05-09 23:11:35708 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18709
710 error_descriptions = []
711 warning_descriptions = []
712 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
713 added_includes):
714 description_with_path = '%s\n %s' % (path, rule_description)
715 if rule_type == Rule.DISALLOW:
716 error_descriptions.append(description_with_path)
717 else:
718 warning_descriptions.append(description_with_path)
719
720 results = []
721 if error_descriptions:
722 results.append(output_api.PresubmitError(
723 'You added one or more #includes that violate checkdeps rules.',
724 error_descriptions))
725 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42726 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18727 'You added one or more #includes of files that are temporarily\n'
728 'allowed but being removed. Can you avoid introducing the\n'
729 '#include? See relevant DEPS file(s) for details and contacts.',
730 warning_descriptions))
731 return results
732
733
[email protected]fbcafe5a2012-08-08 15:31:22734def _CheckFilePermissions(input_api, output_api):
735 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15736 if input_api.platform == 'win32':
737 return []
raphael.kubo.da.costac1d13e60b2016-04-01 11:49:29738 checkperms_tool = input_api.os_path.join(
739 input_api.PresubmitLocalPath(),
740 'tools', 'checkperms', 'checkperms.py')
741 args = [input_api.python_executable, checkperms_tool,
mohan.reddyf21db962014-10-16 12:26:47742 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22743 for f in input_api.AffectedFiles():
744 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11745 try:
746 input_api.subprocess.check_output(args)
747 return []
748 except input_api.subprocess.CalledProcessError as error:
749 return [output_api.PresubmitError(
750 'checkperms.py failed:',
751 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22752
753
[email protected]c8278b32012-10-30 20:35:49754def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
755 """Makes sure we don't include ui/aura/window_property.h
756 in header files.
757 """
758 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
759 errors = []
760 for f in input_api.AffectedFiles():
761 if not f.LocalPath().endswith('.h'):
762 continue
763 for line_num, line in f.ChangedContents():
764 if pattern.match(line):
765 errors.append(' %s:%d' % (f.LocalPath(), line_num))
766
767 results = []
768 if errors:
769 results.append(output_api.PresubmitError(
770 'Header files should not include ui/aura/window_property.h', errors))
771 return results
772
773
[email protected]cf9b78f2012-11-14 11:40:28774def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
775 """Checks that the lines in scope occur in the right order.
776
777 1. C system files in alphabetical order
778 2. C++ system files in alphabetical order
779 3. Project's .h files
780 """
781
782 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
783 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
784 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
785
786 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
787
788 state = C_SYSTEM_INCLUDES
789
790 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57791 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28792 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55793 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28794 for line_num, line in scope:
795 if c_system_include_pattern.match(line):
796 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55797 problem_linenums.append((line_num, previous_line_num,
798 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28799 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55800 problem_linenums.append((line_num, previous_line_num,
801 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28802 elif cpp_system_include_pattern.match(line):
803 if state == C_SYSTEM_INCLUDES:
804 state = CPP_SYSTEM_INCLUDES
805 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55806 problem_linenums.append((line_num, previous_line_num,
807 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28808 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55809 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28810 elif custom_include_pattern.match(line):
811 if state != CUSTOM_INCLUDES:
812 state = CUSTOM_INCLUDES
813 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55814 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28815 else:
brucedawson70fadb02015-06-30 17:47:55816 problem_linenums.append((line_num, previous_line_num,
817 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28818 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57819 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28820
821 warnings = []
brucedawson70fadb02015-06-30 17:47:55822 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57823 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55824 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28825 return warnings
826
827
[email protected]ac294a12012-12-06 16:38:43828def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28829 """Checks the #include order for the given file f."""
830
[email protected]2299dcf2012-11-15 19:56:24831 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30832 # Exclude the following includes from the check:
833 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
834 # specific order.
835 # 2) <atlbase.h>, "build/build_config.h"
836 excluded_include_pattern = input_api.re.compile(
837 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24838 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33839 # Match the final or penultimate token if it is xxxtest so we can ignore it
840 # when considering the special first include.
841 test_file_tag_pattern = input_api.re.compile(
842 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11843 if_pattern = input_api.re.compile(
844 r'\s*#\s*(if|elif|else|endif|define|undef).*')
845 # Some files need specialized order of includes; exclude such files from this
846 # check.
847 uncheckable_includes_pattern = input_api.re.compile(
848 r'\s*#include '
849 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28850
851 contents = f.NewContents()
852 warnings = []
853 line_num = 0
854
[email protected]ac294a12012-12-06 16:38:43855 # Handle the special first include. If the first include file is
856 # some/path/file.h, the corresponding including file can be some/path/file.cc,
857 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
858 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33859 # If the included file is some/path/file_platform.h the including file could
860 # also be some/path/file_xxxtest_platform.h.
861 including_file_base_name = test_file_tag_pattern.sub(
862 '', input_api.os_path.basename(f.LocalPath()))
863
[email protected]ac294a12012-12-06 16:38:43864 for line in contents:
865 line_num += 1
866 if system_include_pattern.match(line):
867 # No special first include -> process the line again along with normal
868 # includes.
869 line_num -= 1
870 break
871 match = custom_include_pattern.match(line)
872 if match:
873 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33874 header_basename = test_file_tag_pattern.sub(
875 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
876
877 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24878 # No special first include -> process the line again along with normal
879 # includes.
880 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43881 break
[email protected]cf9b78f2012-11-14 11:40:28882
883 # Split into scopes: Each region between #if and #endif is its own scope.
884 scopes = []
885 current_scope = []
886 for line in contents[line_num:]:
887 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11888 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54889 continue
[email protected]2309b0fa02012-11-16 12:18:27890 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28891 scopes.append(current_scope)
892 current_scope = []
[email protected]962f117e2012-11-22 18:11:56893 elif ((system_include_pattern.match(line) or
894 custom_include_pattern.match(line)) and
895 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28896 current_scope.append((line_num, line))
897 scopes.append(current_scope)
898
899 for scope in scopes:
900 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
901 changed_linenums))
902 return warnings
903
904
905def _CheckIncludeOrder(input_api, output_api):
906 """Checks that the #include order is correct.
907
908 1. The corresponding header for source files.
909 2. C system files in alphabetical order
910 3. C++ system files in alphabetical order
911 4. Project's .h files in alphabetical order
912
[email protected]ac294a12012-12-06 16:38:43913 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
914 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28915 """
[email protected]e120b012014-08-15 19:08:35916 def FileFilterIncludeOrder(affected_file):
917 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
918 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28919
920 warnings = []
[email protected]e120b012014-08-15 19:08:35921 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08922 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43923 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
924 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28925
926 results = []
927 if warnings:
[email protected]f7051d52013-04-02 18:31:42928 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53929 warnings))
[email protected]cf9b78f2012-11-14 11:40:28930 return results
931
932
[email protected]70ca77752012-11-20 03:45:03933def _CheckForVersionControlConflictsInFile(input_api, f):
934 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
935 errors = []
936 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23937 if f.LocalPath().endswith('.md'):
938 # First-level headers in markdown look a lot like version control
939 # conflict markers. http://daringfireball.net/projects/markdown/basics
940 continue
[email protected]70ca77752012-11-20 03:45:03941 if pattern.match(line):
942 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
943 return errors
944
945
946def _CheckForVersionControlConflicts(input_api, output_api):
947 """Usually this is not intentional and will cause a compile failure."""
948 errors = []
949 for f in input_api.AffectedFiles():
950 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
951
952 results = []
953 if errors:
954 results.append(output_api.PresubmitError(
955 'Version control conflict markers found, please resolve.', errors))
956 return results
957
958
[email protected]06e6d0ff2012-12-11 01:36:44959def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
960 def FilterFile(affected_file):
961 """Filter function for use with input_api.AffectedSourceFiles,
962 below. This filters out everything except non-test files from
963 top-level directories that generally speaking should not hard-code
964 service URLs (e.g. src/android_webview/, src/content/ and others).
965 """
966 return input_api.FilterSourceFile(
967 affected_file,
[email protected]78bb39d62012-12-11 15:11:56968 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44969 black_list=(_EXCLUDED_PATHS +
970 _TEST_CODE_EXCLUDED_PATHS +
971 input_api.DEFAULT_BLACK_LIST))
972
reillyi38965732015-11-16 18:27:33973 base_pattern = ('"[^"]*(google|googleapis|googlezip|googledrive|appspot)'
974 '\.(com|net)[^"]*"')
[email protected]de4f7d22013-05-23 14:27:46975 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
976 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44977 problems = [] # items are (filename, line_number, line)
978 for f in input_api.AffectedSourceFiles(FilterFile):
979 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46980 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44981 problems.append((f.LocalPath(), line_num, line))
982
983 if problems:
[email protected]f7051d52013-04-02 18:31:42984 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44985 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58986 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44987 [' %s:%d: %s' % (
988 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03989 else:
990 return []
[email protected]06e6d0ff2012-12-11 01:36:44991
992
[email protected]d2530012013-01-25 16:39:27993def _CheckNoAbbreviationInPngFileName(input_api, output_api):
994 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31995 The native_client_sdk directory is excluded because it has auto-generated PNG
996 files for documentation.
[email protected]d2530012013-01-25 16:39:27997 """
[email protected]d2530012013-01-25 16:39:27998 errors = []
binji0dcdf342014-12-12 18:32:31999 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
1000 black_list = (r'^native_client_sdk[\\\/]',)
1001 file_filter = lambda f: input_api.FilterSourceFile(
1002 f, white_list=white_list, black_list=black_list)
1003 for f in input_api.AffectedFiles(include_deletes=False,
1004 file_filter=file_filter):
1005 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:271006
1007 results = []
1008 if errors:
1009 results.append(output_api.PresubmitError(
1010 'The name of PNG files should not have abbreviations. \n'
1011 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
1012 'Contact [email protected] if you have questions.', errors))
1013 return results
1014
1015
[email protected]14a6131c2014-01-08 01:15:411016def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:081017 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:411018 a set of DEPS entries that we should look up.
1019
1020 For a directory (rather than a specific filename) we fake a path to
1021 a specific filename by adding /DEPS. This is chosen as a file that
1022 will seldom or never be subject to per-file include_rules.
1023 """
[email protected]2b438d62013-11-14 17:54:141024 # We ignore deps entries on auto-generated directories.
1025 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:081026
1027 # This pattern grabs the path without basename in the first
1028 # parentheses, and the basename (if present) in the second. It
1029 # relies on the simple heuristic that if there is a basename it will
1030 # be a header file ending in ".h".
1031 pattern = re.compile(
1032 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:141033 results = set()
[email protected]f32e2d1e2013-07-26 21:39:081034 for changed_line in changed_lines:
1035 m = pattern.match(changed_line)
1036 if m:
1037 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:141038 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:411039 if m.group(2):
1040 results.add('%s%s' % (path, m.group(2)))
1041 else:
1042 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:081043 return results
1044
1045
[email protected]e871964c2013-05-13 14:14:551046def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
1047 """When a dependency prefixed with + is added to a DEPS file, we
1048 want to make sure that the change is reviewed by an OWNER of the
1049 target file or directory, to avoid layering violations from being
1050 introduced. This check verifies that this happens.
1051 """
1052 changed_lines = set()
jochen53efcdd2016-01-29 05:09:241053
1054 file_filter = lambda f: not input_api.re.match(
1055 r"^third_party[\\\/]WebKit[\\\/].*", f.LocalPath())
1056 for f in input_api.AffectedFiles(include_deletes=False,
1057 file_filter=file_filter):
[email protected]e871964c2013-05-13 14:14:551058 filename = input_api.os_path.basename(f.LocalPath())
1059 if filename == 'DEPS':
1060 changed_lines |= set(line.strip()
1061 for line_num, line
1062 in f.ChangedContents())
1063 if not changed_lines:
1064 return []
1065
[email protected]14a6131c2014-01-08 01:15:411066 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
1067 changed_lines)
[email protected]e871964c2013-05-13 14:14:551068 if not virtual_depended_on_files:
1069 return []
1070
1071 if input_api.is_committing:
1072 if input_api.tbr:
1073 return [output_api.PresubmitNotifyResult(
1074 '--tbr was specified, skipping OWNERS check for DEPS additions')]
Paweł Hajdan, Jrbe6739ea2016-04-28 15:07:271075 if input_api.dry_run:
1076 return [output_api.PresubmitNotifyResult(
1077 'This is a dry run, skipping OWNERS check for DEPS additions')]
[email protected]e871964c2013-05-13 14:14:551078 if not input_api.change.issue:
1079 return [output_api.PresubmitError(
1080 "DEPS approval by OWNERS check failed: this change has "
1081 "no Rietveld issue number, so we can't check it for approvals.")]
1082 output = output_api.PresubmitError
1083 else:
1084 output = output_api.PresubmitNotifyResult
1085
1086 owners_db = input_api.owners_db
tandriied3b7e12016-05-12 14:38:501087 owner_email, reviewers = (
1088 input_api.canned_checks.GetCodereviewOwnerAndReviewers(
1089 input_api,
1090 owners_db.email_regexp,
1091 approval_needed=input_api.is_committing))
[email protected]e871964c2013-05-13 14:14:551092
1093 owner_email = owner_email or input_api.change.author_email
1094
[email protected]de4f7d22013-05-23 14:27:461095 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511096 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461097 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551098 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1099 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411100
1101 # We strip the /DEPS part that was added by
1102 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1103 # directory.
1104 def StripDeps(path):
1105 start_deps = path.rfind('/DEPS')
1106 if start_deps != -1:
1107 return path[:start_deps]
1108 else:
1109 return path
1110 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551111 for path in missing_files]
1112
1113 if unapproved_dependencies:
1114 output_list = [
Paweł Hajdan, Jrec17f882016-07-04 14:16:151115 output('You need LGTM from owners of depends-on paths in DEPS that were '
1116 'modified in this CL:\n %s' %
1117 '\n '.join(sorted(unapproved_dependencies)))]
1118 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1119 output_list.append(output(
1120 'Suggested missing target path OWNERS:\n %s' %
1121 '\n '.join(suggested_owners or [])))
[email protected]e871964c2013-05-13 14:14:551122 return output_list
1123
1124 return []
1125
1126
[email protected]85218562013-11-22 07:41:401127def _CheckSpamLogging(input_api, output_api):
1128 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1129 black_list = (_EXCLUDED_PATHS +
1130 _TEST_CODE_EXCLUDED_PATHS +
1131 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501132 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191133 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481134 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461135 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121136 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1137 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581138 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161139 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031140 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151141 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1142 r"^chromecast[\\\/]",
1143 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311144 r"^components[\\\/]html_viewer[\\\/]"
1145 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461146 # TODO(peter): Remove this exception. https://crbug.com/534537
1147 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1148 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251149 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1150 r"gl_helper_benchmark\.cc$",
altimin979ea2e12016-05-18 16:16:241151 r"^courgette[\\\/]courgette_minimal_tool\.cc$",
thestigc9e38a22014-09-13 01:02:111152 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151153 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111154 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521155 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501156 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361157 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311158 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131159 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441160 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
halliwellf7fc61c62016-01-28 17:18:451161 r"^ui[\\\/]ozone[\\\/]platform[\\\/]cast[\\\/]",
vchigrin14251492015-01-12 08:09:021162 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
skyostil87681be82016-12-19 12:46:351163 r"dump_file_system.cc$",
1164 r"^headless[\\\/]app[\\\/]headless_shell\.cc$"))
[email protected]85218562013-11-22 07:41:401165 source_file_filter = lambda x: input_api.FilterSourceFile(
1166 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1167
1168 log_info = []
1169 printf = []
1170
1171 for f in input_api.AffectedSourceFiles(source_file_filter):
1172 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471173 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401174 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471175 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131176 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371177
mohan.reddyf21db962014-10-16 12:26:471178 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371179 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471180 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401181 printf.append(f.LocalPath())
1182
1183 if log_info:
1184 return [output_api.PresubmitError(
1185 'These files spam the console log with LOG(INFO):',
1186 items=log_info)]
1187 if printf:
1188 return [output_api.PresubmitError(
1189 'These files spam the console log with printf/fprintf:',
1190 items=printf)]
1191 return []
1192
1193
[email protected]49aa76a2013-12-04 06:59:161194def _CheckForAnonymousVariables(input_api, output_api):
1195 """These types are all expected to hold locks while in scope and
1196 so should never be anonymous (which causes them to be immediately
1197 destroyed)."""
1198 they_who_must_be_named = [
1199 'base::AutoLock',
1200 'base::AutoReset',
1201 'base::AutoUnlock',
1202 'SkAutoAlphaRestore',
1203 'SkAutoBitmapShaderInstall',
1204 'SkAutoBlitterChoose',
1205 'SkAutoBounderCommit',
1206 'SkAutoCallProc',
1207 'SkAutoCanvasRestore',
1208 'SkAutoCommentBlock',
1209 'SkAutoDescriptor',
1210 'SkAutoDisableDirectionCheck',
1211 'SkAutoDisableOvalCheck',
1212 'SkAutoFree',
1213 'SkAutoGlyphCache',
1214 'SkAutoHDC',
1215 'SkAutoLockColors',
1216 'SkAutoLockPixels',
1217 'SkAutoMalloc',
1218 'SkAutoMaskFreeImage',
1219 'SkAutoMutexAcquire',
1220 'SkAutoPathBoundsUpdate',
1221 'SkAutoPDFRelease',
1222 'SkAutoRasterClipValidate',
1223 'SkAutoRef',
1224 'SkAutoTime',
1225 'SkAutoTrace',
1226 'SkAutoUnref',
1227 ]
1228 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1229 # bad: base::AutoLock(lock.get());
1230 # not bad: base::AutoLock lock(lock.get());
1231 bad_pattern = input_api.re.compile(anonymous)
1232 # good: new base::AutoLock(lock.get())
1233 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1234 errors = []
1235
1236 for f in input_api.AffectedFiles():
1237 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1238 continue
1239 for linenum, line in f.ChangedContents():
1240 if bad_pattern.search(line) and not good_pattern.search(line):
1241 errors.append('%s:%d' % (f.LocalPath(), linenum))
1242
1243 if errors:
1244 return [output_api.PresubmitError(
1245 'These lines create anonymous variables that need to be named:',
1246 items=errors)]
1247 return []
1248
1249
[email protected]5fe0f8742013-11-29 01:04:591250def _CheckCygwinShell(input_api, output_api):
1251 source_file_filter = lambda x: input_api.FilterSourceFile(
1252 x, white_list=(r'.+\.(gyp|gypi)$',))
1253 cygwin_shell = []
1254
1255 for f in input_api.AffectedSourceFiles(source_file_filter):
1256 for linenum, line in f.ChangedContents():
1257 if 'msvs_cygwin_shell' in line:
1258 cygwin_shell.append(f.LocalPath())
1259 break
1260
1261 if cygwin_shell:
1262 return [output_api.PresubmitError(
1263 'These files should not use msvs_cygwin_shell (the default is 0):',
1264 items=cygwin_shell)]
1265 return []
1266
[email protected]85218562013-11-22 07:41:401267
[email protected]999261d2014-03-03 20:08:081268def _CheckUserActionUpdate(input_api, output_api):
1269 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521270 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081271 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521272 # If actions.xml is already included in the changelist, the PRESUBMIT
1273 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081274 return []
1275
[email protected]999261d2014-03-03 20:08:081276 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1277 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521278 current_actions = None
[email protected]999261d2014-03-03 20:08:081279 for f in input_api.AffectedFiles(file_filter=file_filter):
1280 for line_num, line in f.ChangedContents():
1281 match = input_api.re.search(action_re, line)
1282 if match:
[email protected]2f92dec2014-03-07 19:21:521283 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1284 # loaded only once.
1285 if not current_actions:
1286 with open('tools/metrics/actions/actions.xml') as actions_f:
1287 current_actions = actions_f.read()
1288 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081289 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521290 action = 'name="{0}"'.format(action_name)
1291 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081292 return [output_api.PresubmitPromptWarning(
1293 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521294 'tools/metrics/actions/actions.xml. Please run '
1295 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081296 % (f.LocalPath(), line_num, action_name))]
1297 return []
1298
1299
[email protected]99171a92014-06-03 08:44:471300def _GetJSONParseError(input_api, filename, eat_comments=True):
1301 try:
1302 contents = input_api.ReadFile(filename)
1303 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131304 import sys
1305 original_sys_path = sys.path
1306 try:
1307 sys.path = sys.path + [input_api.os_path.join(
1308 input_api.PresubmitLocalPath(),
1309 'tools', 'json_comment_eater')]
1310 import json_comment_eater
1311 finally:
1312 sys.path = original_sys_path
1313 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471314
1315 input_api.json.loads(contents)
1316 except ValueError as e:
1317 return e
1318 return None
1319
1320
1321def _GetIDLParseError(input_api, filename):
1322 try:
1323 contents = input_api.ReadFile(filename)
1324 idl_schema = input_api.os_path.join(
1325 input_api.PresubmitLocalPath(),
1326 'tools', 'json_schema_compiler', 'idl_schema.py')
1327 process = input_api.subprocess.Popen(
1328 [input_api.python_executable, idl_schema],
1329 stdin=input_api.subprocess.PIPE,
1330 stdout=input_api.subprocess.PIPE,
1331 stderr=input_api.subprocess.PIPE,
1332 universal_newlines=True)
1333 (_, error) = process.communicate(input=contents)
1334 return error or None
1335 except ValueError as e:
1336 return e
1337
1338
1339def _CheckParseErrors(input_api, output_api):
1340 """Check that IDL and JSON files do not contain syntax errors."""
1341 actions = {
1342 '.idl': _GetIDLParseError,
1343 '.json': _GetJSONParseError,
1344 }
1345 # These paths contain test data and other known invalid JSON files.
1346 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491347 r'test[\\\/]data[\\\/]',
1348 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471349 ]
1350 # Most JSON files are preprocessed and support comments, but these do not.
1351 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491352 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471353 ]
1354 # Only run IDL checker on files in these directories.
1355 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491356 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1357 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471358 ]
1359
1360 def get_action(affected_file):
1361 filename = affected_file.LocalPath()
1362 return actions.get(input_api.os_path.splitext(filename)[1])
1363
1364 def MatchesFile(patterns, path):
1365 for pattern in patterns:
1366 if input_api.re.search(pattern, path):
1367 return True
1368 return False
1369
1370 def FilterFile(affected_file):
1371 action = get_action(affected_file)
1372 if not action:
1373 return False
1374 path = affected_file.LocalPath()
1375
1376 if MatchesFile(excluded_patterns, path):
1377 return False
1378
1379 if (action == _GetIDLParseError and
1380 not MatchesFile(idl_included_patterns, path)):
1381 return False
1382 return True
1383
1384 results = []
1385 for affected_file in input_api.AffectedFiles(
1386 file_filter=FilterFile, include_deletes=False):
1387 action = get_action(affected_file)
1388 kwargs = {}
1389 if (action == _GetJSONParseError and
1390 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1391 kwargs['eat_comments'] = False
1392 parse_error = action(input_api,
1393 affected_file.AbsoluteLocalPath(),
1394 **kwargs)
1395 if parse_error:
1396 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1397 (affected_file.LocalPath(), parse_error)))
1398 return results
1399
1400
[email protected]760deea2013-12-10 19:33:491401def _CheckJavaStyle(input_api, output_api):
1402 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471403 import sys
[email protected]760deea2013-12-10 19:33:491404 original_sys_path = sys.path
1405 try:
1406 sys.path = sys.path + [input_api.os_path.join(
1407 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1408 import checkstyle
1409 finally:
1410 # Restore sys.path to what it was before.
1411 sys.path = original_sys_path
1412
1413 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091414 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511415 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491416
1417
dchenge07de812016-06-20 19:27:171418def _CheckIpcOwners(input_api, output_api):
1419 """Checks that affected files involving IPC have an IPC OWNERS rule.
1420
1421 Whether or not a file affects IPC is determined by a simple whitelist of
1422 filename patterns."""
1423 file_patterns = [
1424 '*_messages.cc',
1425 '*_messages*.h',
1426 '*_param_traits*.*',
1427 '*.mojom',
1428 '*_struct_traits*.*',
1429 '*_type_converter*.*',
1430 # Blink uses a different file naming convention
1431 '*StructTraits*.*',
1432 '*TypeConverter*.*',
1433 ]
1434
scottmg7a6ed5ba2016-11-04 18:22:041435 # These third_party directories do not contain IPCs, but contain files
1436 # matching the above patterns, which trigger false positives.
1437 exclude_paths = [
1438 'third_party/crashpad/*',
1439 ]
1440
dchenge07de812016-06-20 19:27:171441 # Dictionary mapping an OWNERS file path to Patterns.
1442 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file
1443 # rules ) to a PatternEntry.
1444 # PatternEntry is a dictionary with two keys:
1445 # - 'files': the files that are matched by this pattern
1446 # - 'rules': the per-file rules needed for this pattern
1447 # For example, if we expect OWNERS file to contain rules for *.mojom and
1448 # *_struct_traits*.*, Patterns might look like this:
1449 # {
1450 # '*.mojom': {
1451 # 'files': ...,
1452 # 'rules': [
1453 # 'per-file *.mojom=set noparent',
1454 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS',
1455 # ],
1456 # },
1457 # '*_struct_traits*.*': {
1458 # 'files': ...,
1459 # 'rules': [
1460 # 'per-file *_struct_traits*.*=set noparent',
1461 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS',
1462 # ],
1463 # },
1464 # }
1465 to_check = {}
1466
1467 # Iterate through the affected files to see what we actually need to check
1468 # for. We should only nag patch authors about per-file rules if a file in that
1469 # directory would match that pattern. If a directory only contains *.mojom
1470 # files and no *_messages*.h files, we should only nag about rules for
1471 # *.mojom files.
rockot51249332016-06-23 16:32:251472 for f in input_api.change.AffectedFiles(include_deletes=False):
dchenge07de812016-06-20 19:27:171473 for pattern in file_patterns:
1474 if input_api.fnmatch.fnmatch(
1475 input_api.os_path.basename(f.LocalPath()), pattern):
scottmg7a6ed5ba2016-11-04 18:22:041476 skip = False
1477 for exclude in exclude_paths:
1478 if input_api.fnmatch.fnmatch(f.LocalPath(), exclude):
1479 skip = True
1480 break
1481 if skip:
1482 continue
dchenge07de812016-06-20 19:27:171483 owners_file = input_api.os_path.join(
1484 input_api.os_path.dirname(f.LocalPath()), 'OWNERS')
1485 if owners_file not in to_check:
1486 to_check[owners_file] = {}
1487 if pattern not in to_check[owners_file]:
1488 to_check[owners_file][pattern] = {
1489 'files': [],
1490 'rules': [
1491 'per-file %s=set noparent' % pattern,
1492 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern,
1493 ]
1494 }
1495 to_check[owners_file][pattern]['files'].append(f)
1496 break
1497
1498 # Now go through the OWNERS files we collected, filtering out rules that are
1499 # already present in that OWNERS file.
1500 for owners_file, patterns in to_check.iteritems():
1501 try:
1502 with file(owners_file) as f:
1503 lines = set(f.read().splitlines())
1504 for entry in patterns.itervalues():
1505 entry['rules'] = [rule for rule in entry['rules'] if rule not in lines
1506 ]
1507 except IOError:
1508 # No OWNERS file, so all the rules are definitely missing.
1509 continue
1510
1511 # All the remaining lines weren't found in OWNERS files, so emit an error.
1512 errors = []
1513 for owners_file, patterns in to_check.iteritems():
1514 missing_lines = []
1515 files = []
1516 for pattern, entry in patterns.iteritems():
1517 missing_lines.extend(entry['rules'])
1518 files.extend([' %s' % f.LocalPath() for f in entry['files']])
1519 if missing_lines:
1520 errors.append(
1521 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' %
1522 (owners_file, '\n'.join(missing_lines), '\n'.join(files)))
1523
1524 results = []
1525 if errors:
vabrf5ce3bf92016-07-11 14:52:411526 if input_api.is_committing:
1527 output = output_api.PresubmitError
1528 else:
1529 output = output_api.PresubmitPromptWarning
1530 results.append(output(
dchenge07de812016-06-20 19:27:171531 'Found changes to IPC files without a security OWNER!',
1532 long_text='\n\n'.join(errors)))
1533
1534 return results
1535
1536
jbriance9e12f162016-11-25 07:57:501537def _CheckUselessForwardDeclarations(input_api, output_api):
jbriance2c51e821a2016-12-12 08:24:311538 """Checks that added or removed lines in non third party affected
1539 header files do not lead to new useless class or struct forward
1540 declaration.
jbriance9e12f162016-11-25 07:57:501541 """
1542 results = []
1543 class_pattern = input_api.re.compile(r'^class\s+(\w+);$',
1544 input_api.re.MULTILINE)
1545 struct_pattern = input_api.re.compile(r'^struct\s+(\w+);$',
1546 input_api.re.MULTILINE)
1547 for f in input_api.AffectedFiles(include_deletes=False):
jbriance2c51e821a2016-12-12 08:24:311548 if (f.LocalPath().startswith('third_party') and
1549 not f.LocalPath().startswith('third_party/WebKit') and
1550 not f.LocalPath().startswith('third_party\\WebKit')):
1551 continue
1552
jbriance9e12f162016-11-25 07:57:501553 if not f.LocalPath().endswith('.h'):
1554 continue
1555
1556 contents = input_api.ReadFile(f)
1557 fwd_decls = input_api.re.findall(class_pattern, contents)
1558 fwd_decls.extend(input_api.re.findall(struct_pattern, contents))
1559
1560 useless_fwd_decls = []
1561 for decl in fwd_decls:
1562 count = sum(1 for _ in input_api.re.finditer(
1563 r'\b%s\b' % input_api.re.escape(decl), contents))
1564 if count == 1:
1565 useless_fwd_decls.append(decl)
1566
1567 if not useless_fwd_decls:
1568 continue
1569
1570 for line in f.GenerateScmDiff().splitlines():
1571 if (line.startswith('-') and not line.startswith('--') or
1572 line.startswith('+') and not line.startswith('++')):
1573 for decl in useless_fwd_decls:
1574 if input_api.re.search(r'\b%s\b' % decl, line[1:]):
1575 results.append(output_api.PresubmitPromptWarning(
1576 '%s: %s forward declaration is becoming useless' %
1577 (f.LocalPath(), decl)))
1578 useless_fwd_decls.remove(decl)
1579
1580 return results
1581
1582
dskiba88634f4e2015-08-14 23:03:291583def _CheckAndroidToastUsage(input_api, output_api):
1584 """Checks that code uses org.chromium.ui.widget.Toast instead of
1585 android.widget.Toast (Chromium Toast doesn't force hardware
1586 acceleration on low-end devices, saving memory).
1587 """
1588 toast_import_pattern = input_api.re.compile(
1589 r'^import android\.widget\.Toast;$')
1590
1591 errors = []
1592
1593 sources = lambda affected_file: input_api.FilterSourceFile(
1594 affected_file,
1595 black_list=(_EXCLUDED_PATHS +
1596 _TEST_CODE_EXCLUDED_PATHS +
1597 input_api.DEFAULT_BLACK_LIST +
1598 (r'^chromecast[\\\/].*',
1599 r'^remoting[\\\/].*')),
1600 white_list=(r'.*\.java$',))
1601
1602 for f in input_api.AffectedSourceFiles(sources):
1603 for line_num, line in f.ChangedContents():
1604 if toast_import_pattern.search(line):
1605 errors.append("%s:%d" % (f.LocalPath(), line_num))
1606
1607 results = []
1608
1609 if errors:
1610 results.append(output_api.PresubmitError(
1611 'android.widget.Toast usage is detected. Android toasts use hardware'
1612 ' acceleration, and can be\ncostly on low-end devices. Please use'
1613 ' org.chromium.ui.widget.Toast instead.\n'
1614 'Contact [email protected] if you have any questions.',
1615 errors))
1616
1617 return results
1618
1619
dgnaa68d5e2015-06-10 10:08:221620def _CheckAndroidCrLogUsage(input_api, output_api):
1621 """Checks that new logs using org.chromium.base.Log:
1622 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511623 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221624 """
pkotwicza1dd0b002016-05-16 14:41:041625
1626 # Do not check format of logs in //chrome/android/webapk because
1627 # //chrome/android/webapk cannot depend on //base
1628 cr_log_check_excluded_paths = [
1629 r"^chrome[\\\/]android[\\\/]webapk[\\\/].*",
1630 ]
1631
dgnaa68d5e2015-06-10 10:08:221632 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121633 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1634 class_in_base_pattern = input_api.re.compile(
1635 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1636 has_some_log_import_pattern = input_api.re.compile(
1637 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221638 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121639 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221640 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511641 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221642 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221643
Vincent Scheib16d7b272015-09-15 18:09:071644 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221645 'or contact [email protected] for more info.')
pkotwicza1dd0b002016-05-16 14:41:041646 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',),
1647 black_list=cr_log_check_excluded_paths)
dgn87d9fb62015-06-12 09:15:121648
dgnaa68d5e2015-06-10 10:08:221649 tag_decl_errors = []
1650 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121651 tag_errors = []
dgn38736db2015-09-18 19:20:511652 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121653 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221654
1655 for f in input_api.AffectedSourceFiles(sources):
1656 file_content = input_api.ReadFile(f)
1657 has_modified_logs = False
1658
1659 # Per line checks
dgn87d9fb62015-06-12 09:15:121660 if (cr_log_import_pattern.search(file_content) or
1661 (class_in_base_pattern.search(file_content) and
1662 not has_some_log_import_pattern.search(file_content))):
1663 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221664 for line_num, line in f.ChangedContents():
1665
1666 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121667 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221668 if match:
1669 has_modified_logs = True
1670
1671 # Make sure it uses "TAG"
1672 if not match.group('tag') == 'TAG':
1673 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121674 else:
1675 # Report non cr Log function calls in changed lines
1676 for line_num, line in f.ChangedContents():
1677 if log_call_pattern.search(line):
1678 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221679
1680 # Per file checks
1681 if has_modified_logs:
1682 # Make sure the tag is using the "cr" prefix and is not too long
1683 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511684 tag_name = match.group('name') if match else None
1685 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221686 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511687 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221688 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511689 elif '.' in tag_name:
1690 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221691
1692 results = []
1693 if tag_decl_errors:
1694 results.append(output_api.PresubmitPromptWarning(
1695 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511696 '"private static final String TAG = "<package tag>".\n'
1697 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221698 tag_decl_errors))
1699
1700 if tag_length_errors:
1701 results.append(output_api.PresubmitError(
1702 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511703 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221704 tag_length_errors))
1705
1706 if tag_errors:
1707 results.append(output_api.PresubmitPromptWarning(
1708 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1709 tag_errors))
1710
dgn87d9fb62015-06-12 09:15:121711 if util_log_errors:
dgn4401aa52015-04-29 16:26:171712 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121713 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1714 util_log_errors))
1715
dgn38736db2015-09-18 19:20:511716 if tag_with_dot_errors:
1717 results.append(output_api.PresubmitPromptWarning(
1718 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1719 tag_with_dot_errors))
1720
dgn4401aa52015-04-29 16:26:171721 return results
1722
1723
agrieve7b6479d82015-10-07 14:24:221724def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1725 """Checks if MDPI assets are placed in a correct directory."""
1726 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1727 ('/res/drawable/' in f.LocalPath() or
1728 '/res/drawable-ldrtl/' in f.LocalPath()))
1729 errors = []
1730 for f in input_api.AffectedFiles(include_deletes=False,
1731 file_filter=file_filter):
1732 errors.append(' %s' % f.LocalPath())
1733
1734 results = []
1735 if errors:
1736 results.append(output_api.PresubmitError(
1737 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1738 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1739 '/res/drawable-ldrtl/.\n'
1740 'Contact [email protected] if you have questions.', errors))
1741 return results
1742
1743
agrievef32bcc72016-04-04 14:57:401744class PydepsChecker(object):
1745 def __init__(self, input_api, pydeps_files):
1746 self._file_cache = {}
1747 self._input_api = input_api
1748 self._pydeps_files = pydeps_files
1749
1750 def _LoadFile(self, path):
1751 """Returns the list of paths within a .pydeps file relative to //."""
1752 if path not in self._file_cache:
1753 with open(path) as f:
1754 self._file_cache[path] = f.read()
1755 return self._file_cache[path]
1756
1757 def _ComputeNormalizedPydepsEntries(self, pydeps_path):
1758 """Returns an interable of paths within the .pydep, relativized to //."""
1759 os_path = self._input_api.os_path
1760 pydeps_dir = os_path.dirname(pydeps_path)
1761 entries = (l.rstrip() for l in self._LoadFile(pydeps_path).splitlines()
1762 if not l.startswith('*'))
1763 return (os_path.normpath(os_path.join(pydeps_dir, e)) for e in entries)
1764
1765 def _CreateFilesToPydepsMap(self):
1766 """Returns a map of local_path -> list_of_pydeps."""
1767 ret = {}
1768 for pydep_local_path in self._pydeps_files:
1769 for path in self._ComputeNormalizedPydepsEntries(pydep_local_path):
1770 ret.setdefault(path, []).append(pydep_local_path)
1771 return ret
1772
1773 def ComputeAffectedPydeps(self):
1774 """Returns an iterable of .pydeps files that might need regenerating."""
1775 affected_pydeps = set()
1776 file_to_pydeps_map = None
1777 for f in self._input_api.AffectedFiles(include_deletes=True):
1778 local_path = f.LocalPath()
1779 if local_path == 'DEPS':
1780 return self._pydeps_files
1781 elif local_path.endswith('.pydeps'):
1782 if local_path in self._pydeps_files:
1783 affected_pydeps.add(local_path)
1784 elif local_path.endswith('.py'):
1785 if file_to_pydeps_map is None:
1786 file_to_pydeps_map = self._CreateFilesToPydepsMap()
1787 affected_pydeps.update(file_to_pydeps_map.get(local_path, ()))
1788 return affected_pydeps
1789
1790 def DetermineIfStale(self, pydeps_path):
1791 """Runs print_python_deps.py to see if the files is stale."""
phajdan.jr0d9878552016-11-04 10:49:411792 import difflib
agrievef32bcc72016-04-04 14:57:401793 old_pydeps_data = self._LoadFile(pydeps_path).splitlines()
1794 cmd = old_pydeps_data[1][1:].strip()
1795 new_pydeps_data = self._input_api.subprocess.check_output(
1796 cmd + ' --output ""', shell=True)
phajdan.jr0d9878552016-11-04 10:49:411797 old_contents = old_pydeps_data[2:]
1798 new_contents = new_pydeps_data.splitlines()[2:]
agrievef32bcc72016-04-04 14:57:401799 if old_pydeps_data[2:] != new_pydeps_data.splitlines()[2:]:
phajdan.jr0d9878552016-11-04 10:49:411800 return cmd, '\n'.join(difflib.context_diff(old_contents, new_contents))
agrievef32bcc72016-04-04 14:57:401801
1802
1803def _CheckPydepsNeedsUpdating(input_api, output_api, checker_for_tests=None):
1804 """Checks if a .pydeps file needs to be regenerated."""
agrievebb9c5b472016-04-22 15:13:001805 # This check is mainly for Android, and involves paths not only in the
agrieve9bc4200b2016-05-04 16:33:281806 # PRESUBMIT.py, but also in the .pydeps files. It doesn't work on Windows and
1807 # Mac, so skip it on other platforms.
1808 if input_api.platform != 'linux2':
agrievebb9c5b472016-04-22 15:13:001809 return []
agrievef32bcc72016-04-04 14:57:401810 # TODO(agrieve): Update when there's a better way to detect this: crbug/570091
1811 is_android = input_api.os_path.exists('third_party/android_tools')
1812 pydeps_files = _ALL_PYDEPS_FILES if is_android else _GENERIC_PYDEPS_FILES
1813 results = []
1814 # First, check for new / deleted .pydeps.
1815 for f in input_api.AffectedFiles(include_deletes=True):
1816 if f.LocalPath().endswith('.pydeps'):
1817 if f.Action() == 'D' and f.LocalPath() in _ALL_PYDEPS_FILES:
1818 results.append(output_api.PresubmitError(
1819 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1820 'remove %s' % f.LocalPath()))
1821 elif f.Action() != 'D' and f.LocalPath() not in _ALL_PYDEPS_FILES:
1822 results.append(output_api.PresubmitError(
1823 'Please update _ALL_PYDEPS_FILES within //PRESUBMIT.py to '
1824 'include %s' % f.LocalPath()))
1825
1826 if results:
1827 return results
1828
1829 checker = checker_for_tests or PydepsChecker(input_api, pydeps_files)
1830
1831 for pydep_path in checker.ComputeAffectedPydeps():
1832 try:
phajdan.jr0d9878552016-11-04 10:49:411833 result = checker.DetermineIfStale(pydep_path)
1834 if result:
1835 cmd, diff = result
agrievef32bcc72016-04-04 14:57:401836 results.append(output_api.PresubmitError(
phajdan.jr0d9878552016-11-04 10:49:411837 'File is stale: %s\nDiff (apply to fix):\n%s\n'
1838 'To regenerate, run:\n\n %s' %
1839 (pydep_path, diff, cmd)))
agrievef32bcc72016-04-04 14:57:401840 except input_api.subprocess.CalledProcessError as error:
1841 return [output_api.PresubmitError('Error running: %s' % error.cmd,
1842 long_text=error.output)]
1843
1844 return results
1845
1846
glidere61efad2015-02-18 17:39:431847def _CheckSingletonInHeaders(input_api, output_api):
1848 """Checks to make sure no header files have |Singleton<|."""
1849 def FileFilter(affected_file):
1850 # It's ok for base/memory/singleton.h to have |Singleton<|.
1851 black_list = (_EXCLUDED_PATHS +
1852 input_api.DEFAULT_BLACK_LIST +
1853 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1854 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1855
sergeyu34d21222015-09-16 00:11:441856 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431857 files = []
1858 for f in input_api.AffectedSourceFiles(FileFilter):
1859 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1860 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1861 contents = input_api.ReadFile(f)
1862 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241863 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431864 pattern.search(line)):
1865 files.append(f)
1866 break
1867
1868 if files:
yolandyandaabc6d2016-04-18 18:29:391869 return [output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441870 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431871 'Please move them to an appropriate source file so that the ' +
1872 'template gets instantiated in a single compilation unit.',
1873 files) ]
1874 return []
1875
1876
dbeam1ec68ac2016-12-15 05:22:241877def _CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api):
dbeam37e8e7402016-02-10 22:58:201878 """Checks for old style compiled_resources.gyp files."""
1879 is_compiled_resource = lambda fp: fp.endswith('compiled_resources.gyp')
1880
1881 added_compiled_resources = filter(is_compiled_resource, [
1882 f.LocalPath() for f in input_api.AffectedFiles() if f.Action() == 'A'
1883 ])
1884
1885 if not added_compiled_resources:
1886 return []
1887
1888 return [output_api.PresubmitError(
1889 "Found new compiled_resources.gyp files:\n%s\n\n"
1890 "compiled_resources.gyp files are deprecated,\n"
michaelpgdb9985072016-02-24 19:13:551891 "please use compiled_resources2.gyp instead:\n"
1892 "https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md"
1893 %
dbeam37e8e7402016-02-10 22:58:201894 "\n".join(added_compiled_resources))]
1895
1896
[email protected]fd20b902014-05-09 02:14:531897_DEPRECATED_CSS = [
1898 # Values
1899 ( "-webkit-box", "flex" ),
1900 ( "-webkit-inline-box", "inline-flex" ),
1901 ( "-webkit-flex", "flex" ),
1902 ( "-webkit-inline-flex", "inline-flex" ),
1903 ( "-webkit-min-content", "min-content" ),
1904 ( "-webkit-max-content", "max-content" ),
1905
1906 # Properties
1907 ( "-webkit-background-clip", "background-clip" ),
1908 ( "-webkit-background-origin", "background-origin" ),
1909 ( "-webkit-background-size", "background-size" ),
1910 ( "-webkit-box-shadow", "box-shadow" ),
1911
1912 # Functions
1913 ( "-webkit-gradient", "gradient" ),
1914 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1915 ( "-webkit-linear-gradient", "linear-gradient" ),
1916 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1917 ( "-webkit-radial-gradient", "radial-gradient" ),
1918 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1919]
1920
dbeam1ec68ac2016-12-15 05:22:241921def _CheckNoDeprecatedCss(input_api, output_api):
[email protected]fd20b902014-05-09 02:14:531922 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251923 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341924 documentation and iOS CSS for dom distiller
1925 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251926 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531927 results = []
dbeam070cfe62014-10-22 06:44:021928 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251929 black_list = (_EXCLUDED_PATHS +
1930 _TEST_CODE_EXCLUDED_PATHS +
1931 input_api.DEFAULT_BLACK_LIST +
1932 (r"^chrome/common/extensions/docs",
1933 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341934 r"^components/dom_distiller/core/css/distilledpage_ios.css",
sdefresneda218472015-12-07 18:38:051935 r"^components/flags_ui/resources/apple_flags.css",
sdefresne6308d7f2016-02-15 09:38:441936 r"^components/neterror/resources/neterror.css",
[email protected]9a48e3f82014-05-22 00:06:251937 r"^native_client_sdk"))
1938 file_filter = lambda f: input_api.FilterSourceFile(
1939 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531940 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1941 for line_num, line in fpath.ChangedContents():
1942 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021943 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531944 results.append(output_api.PresubmitError(
1945 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1946 (fpath.LocalPath(), line_num, deprecated_value, value)))
1947 return results
1948
mohan.reddyf21db962014-10-16 12:26:471949
dbeam070cfe62014-10-22 06:44:021950_DEPRECATED_JS = [
1951 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1952 ( "__defineGetter__", "Object.defineProperty" ),
1953 ( "__defineSetter__", "Object.defineProperty" ),
1954]
1955
dbeam1ec68ac2016-12-15 05:22:241956def _CheckNoDeprecatedJs(input_api, output_api):
dbeam070cfe62014-10-22 06:44:021957 """Make sure that we don't use deprecated JS in Chrome code."""
1958 results = []
1959 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1960 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1961 input_api.DEFAULT_BLACK_LIST)
1962 file_filter = lambda f: input_api.FilterSourceFile(
1963 f, white_list=file_inclusion_pattern, black_list=black_list)
1964 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1965 for lnum, line in fpath.ChangedContents():
1966 for (deprecated, replacement) in _DEPRECATED_JS:
1967 if deprecated in line:
1968 results.append(output_api.PresubmitError(
1969 "%s:%d: Use of deprecated JS %s, use %s instead" %
1970 (fpath.LocalPath(), lnum, deprecated, replacement)))
1971 return results
1972
1973
dbeam1ec68ac2016-12-15 05:22:241974def _CheckForRiskyJsFeatures(input_api, output_api):
1975 maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
1976 file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
1977
1978 arrow_lines = []
1979 for f in input_api.AffectedFiles(file_filter=file_filter):
1980 for lnum, line in f.ChangedContents():
1981 if ' => ' in line:
1982 arrow_lines.append((f.LocalPath(), lnum))
1983
1984 if not arrow_lines:
1985 return []
1986
1987 return [output_api.PresubmitPromptWarning("""
1988Use of => operator detected in:
1989%s
1990Please ensure your code does not run on iOS9 (=> (arrow) does not work there).
1991https://chromium.googlesource.com/chromium/src/+/master/docs/es6_chromium.md#Arrow-Functions
1992""" % "\n".join(" %s:%d\n" % line for line in arrow_lines))]
1993
1994
dgnaa68d5e2015-06-10 10:08:221995def _AndroidSpecificOnUploadChecks(input_api, output_api):
1996 """Groups checks that target android code."""
1997 results = []
dgnaa68d5e2015-06-10 10:08:221998 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221999 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:292000 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222001 return results
2002
2003
[email protected]22c9bd72011-03-27 16:47:392004def _CommonChecks(input_api, output_api):
2005 """Checks common to both upload and commit."""
2006 results = []
2007 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:382008 input_api, output_api,
qyearsleyfa2cfcf82016-12-15 18:03:542009 excluded_paths=_EXCLUDED_PATHS))
machenbachfbda9b72016-12-06 13:13:582010 results.extend(
2011 input_api.canned_checks.CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:192012 results.extend(
[email protected]760deea2013-12-10 19:33:492013 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:542014 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:182015 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:522016 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:222017 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:442018 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:592019 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:062020 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:122021 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:182022 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:222023 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:492024 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:272025 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:032026 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:492027 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:442028 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:272029 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:542030 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:442031 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
yolandyandaabc6d2016-04-18 18:29:392032 results.extend(_CheckFlakyTestUsage(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:552033 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:042034 results.extend(
2035 input_api.canned_checks.CheckChangeHasNoTabs(
2036 input_api,
2037 output_api,
2038 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:402039 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:162040 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:592041 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:082042 results.extend(_CheckUserActionUpdate(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242043 results.extend(_CheckNoDeprecatedCss(input_api, output_api))
2044 results.extend(_CheckNoDeprecatedJs(input_api, output_api))
[email protected]99171a92014-06-03 08:44:472045 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:042046 results.extend(_CheckForIPCRules(input_api, output_api))
mostynbb639aca52015-01-07 20:31:232047 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:432048 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242049 results.extend(_CheckNoDeprecatedCompiledResourcesGyp(input_api, output_api))
agrievef32bcc72016-04-04 14:57:402050 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api))
wnwenbdc444e2016-05-25 13:44:152051 results.extend(_CheckJavaStyle(input_api, output_api))
dchenge07de812016-06-20 19:27:172052 results.extend(_CheckIpcOwners(input_api, output_api))
jbriance9e12f162016-11-25 07:57:502053 results.extend(_CheckUselessForwardDeclarations(input_api, output_api))
dbeam1ec68ac2016-12-15 05:22:242054 results.extend(_CheckForRiskyJsFeatures(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:242055
2056 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
2057 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
2058 input_api, output_api,
2059 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:382060 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:392061 return results
[email protected]1f7b4172010-01-28 01:17:342062
[email protected]b337cb5b2011-01-23 21:24:052063
[email protected]b8079ae4a2012-12-05 19:56:492064def _CheckPatchFiles(input_api, output_api):
2065 problems = [f.LocalPath() for f in input_api.AffectedFiles()
2066 if f.LocalPath().endswith(('.orig', '.rej'))]
2067 if problems:
2068 return [output_api.PresubmitError(
2069 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:032070 else:
2071 return []
[email protected]b8079ae4a2012-12-05 19:56:492072
2073
[email protected]b00342e7f2013-03-26 16:21:542074def _DidYouMeanOSMacro(bad_macro):
2075 try:
2076 return {'A': 'OS_ANDROID',
2077 'B': 'OS_BSD',
2078 'C': 'OS_CHROMEOS',
2079 'F': 'OS_FREEBSD',
2080 'L': 'OS_LINUX',
2081 'M': 'OS_MACOSX',
2082 'N': 'OS_NACL',
2083 'O': 'OS_OPENBSD',
2084 'P': 'OS_POSIX',
2085 'S': 'OS_SOLARIS',
2086 'W': 'OS_WIN'}[bad_macro[3].upper()]
2087 except KeyError:
2088 return ''
2089
2090
2091def _CheckForInvalidOSMacrosInFile(input_api, f):
2092 """Check for sensible looking, totally invalid OS macros."""
2093 preprocessor_statement = input_api.re.compile(r'^\s*#')
2094 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
2095 results = []
2096 for lnum, line in f.ChangedContents():
2097 if preprocessor_statement.search(line):
2098 for match in os_macro.finditer(line):
2099 if not match.group(1) in _VALID_OS_MACROS:
2100 good = _DidYouMeanOSMacro(match.group(1))
2101 did_you_mean = ' (did you mean %s?)' % good if good else ''
2102 results.append(' %s:%d %s%s' % (f.LocalPath(),
2103 lnum,
2104 match.group(1),
2105 did_you_mean))
2106 return results
2107
2108
2109def _CheckForInvalidOSMacros(input_api, output_api):
2110 """Check all affected files for invalid OS macros."""
2111 bad_macros = []
2112 for f in input_api.AffectedFiles():
ellyjones47654342016-05-06 15:50:472113 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css', '.md')):
[email protected]b00342e7f2013-03-26 16:21:542114 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
2115
2116 if not bad_macros:
2117 return []
2118
2119 return [output_api.PresubmitError(
2120 'Possibly invalid OS macro[s] found. Please fix your code\n'
2121 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
2122
lliabraa35bab3932014-10-01 12:16:442123
2124def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
2125 """Check all affected files for invalid "if defined" macros."""
2126 ALWAYS_DEFINED_MACROS = (
2127 "TARGET_CPU_PPC",
2128 "TARGET_CPU_PPC64",
2129 "TARGET_CPU_68K",
2130 "TARGET_CPU_X86",
2131 "TARGET_CPU_ARM",
2132 "TARGET_CPU_MIPS",
2133 "TARGET_CPU_SPARC",
2134 "TARGET_CPU_ALPHA",
2135 "TARGET_IPHONE_SIMULATOR",
2136 "TARGET_OS_EMBEDDED",
2137 "TARGET_OS_IPHONE",
2138 "TARGET_OS_MAC",
2139 "TARGET_OS_UNIX",
2140 "TARGET_OS_WIN32",
2141 )
2142 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
2143 results = []
2144 for lnum, line in f.ChangedContents():
2145 for match in ifdef_macro.finditer(line):
2146 if match.group(1) in ALWAYS_DEFINED_MACROS:
2147 always_defined = ' %s is always defined. ' % match.group(1)
2148 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
2149 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
2150 lnum,
2151 always_defined,
2152 did_you_mean))
2153 return results
2154
2155
2156def _CheckForInvalidIfDefinedMacros(input_api, output_api):
2157 """Check all affected files for invalid "if defined" macros."""
2158 bad_macros = []
2159 for f in input_api.AffectedFiles():
2160 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
2161 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
2162
2163 if not bad_macros:
2164 return []
2165
2166 return [output_api.PresubmitError(
2167 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
2168 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
2169 bad_macros)]
2170
2171
mlamouria82272622014-09-16 18:45:042172def _CheckForIPCRules(input_api, output_api):
2173 """Check for same IPC rules described in
2174 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
2175 """
2176 base_pattern = r'IPC_ENUM_TRAITS\('
2177 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
2178 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
2179
2180 problems = []
2181 for f in input_api.AffectedSourceFiles(None):
2182 local_path = f.LocalPath()
2183 if not local_path.endswith('.h'):
2184 continue
2185 for line_number, line in f.ChangedContents():
2186 if inclusion_pattern.search(line) and not comment_pattern.search(line):
2187 problems.append(
2188 '%s:%d\n %s' % (local_path, line_number, line.strip()))
2189
2190 if problems:
2191 return [output_api.PresubmitPromptWarning(
2192 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
2193 else:
2194 return []
2195
[email protected]b00342e7f2013-03-26 16:21:542196
mostynbb639aca52015-01-07 20:31:232197def _CheckForWindowsLineEndings(input_api, output_api):
2198 """Check source code and known ascii text files for Windows style line
2199 endings.
2200 """
earthdok1b5e0ee2015-03-10 15:19:102201 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:232202
2203 file_inclusion_pattern = (
2204 known_text_files,
2205 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
2206 )
2207
2208 filter = lambda f: input_api.FilterSourceFile(
2209 f, white_list=file_inclusion_pattern, black_list=None)
2210 files = [f.LocalPath() for f in
2211 input_api.AffectedSourceFiles(filter)]
2212
2213 problems = []
2214
2215 for file in files:
2216 fp = open(file, 'r')
2217 for line in fp:
2218 if line.endswith('\r\n'):
2219 problems.append(file)
2220 break
2221 fp.close()
2222
2223 if problems:
2224 return [output_api.PresubmitPromptWarning('Are you sure that you want '
2225 'these files to contain Windows style line endings?\n' +
2226 '\n'.join(problems))]
2227
2228 return []
2229
2230
pastarmovj89f7ee12016-09-20 14:58:132231def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None,
2232 lint_filters=None, verbose_level=None):
2233 """Checks that all source files use SYSLOG properly."""
2234 syslog_files = []
2235 for f in input_api.AffectedSourceFiles(source_file_filter):
2236 if 'SYSLOG' in input_api.ReadFile(f, 'rb'):
2237 syslog_files.append(f.LocalPath())
2238 if syslog_files:
2239 return [output_api.PresubmitPromptWarning(
2240 'Please make sure there are no privacy sensitive bits of data in SYSLOG'
2241 ' calls.\nFiles to check:\n', items=syslog_files)]
2242 return []
2243
2244
[email protected]1f7b4172010-01-28 01:17:342245def CheckChangeOnUpload(input_api, output_api):
2246 results = []
2247 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:472248 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
scottmg39b29952014-12-08 18:31:282249 results.extend(
2250 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:192251 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:222252 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
pastarmovj89f7ee12016-09-20 14:58:132253 results.extend(_CheckSyslogUseWarning(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542254 return results
[email protected]ca8d19842009-02-19 16:33:122255
2256
[email protected]1bfb8322014-04-23 01:02:412257def GetTryServerMasterForBot(bot):
2258 """Returns the Try Server master for the given bot.
2259
[email protected]0bb112362014-07-26 04:38:322260 It tries to guess the master from the bot name, but may still fail
2261 and return None. There is no longer a default master.
2262 """
2263 # Potentially ambiguous bot names are listed explicitly.
2264 master_map = {
tandriie5587792016-07-14 00:34:502265 'chromium_presubmit': 'master.tryserver.chromium.linux',
2266 'tools_build_presubmit': 'master.tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:412267 }
[email protected]0bb112362014-07-26 04:38:322268 master = master_map.get(bot)
2269 if not master:
wnwen4fbaab82016-05-25 12:54:362270 if 'android' in bot:
tandriie5587792016-07-14 00:34:502271 master = 'master.tryserver.chromium.android'
wnwen4fbaab82016-05-25 12:54:362272 elif 'linux' in bot or 'presubmit' in bot:
tandriie5587792016-07-14 00:34:502273 master = 'master.tryserver.chromium.linux'
[email protected]0bb112362014-07-26 04:38:322274 elif 'win' in bot:
tandriie5587792016-07-14 00:34:502275 master = 'master.tryserver.chromium.win'
[email protected]0bb112362014-07-26 04:38:322276 elif 'mac' in bot or 'ios' in bot:
tandriie5587792016-07-14 00:34:502277 master = 'master.tryserver.chromium.mac'
[email protected]0bb112362014-07-26 04:38:322278 return master
[email protected]1bfb8322014-04-23 01:02:412279
2280
Paweł Hajdan, Jr55083782014-12-19 20:32:562281def GetDefaultTryConfigs(bots):
2282 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:012283 """
2284
Paweł Hajdan, Jr55083782014-12-19 20:32:562285 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:412286
2287 # Build up the mapping from tryserver master to bot/test.
2288 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:562289 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:412290 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
2291 return out
[email protected]38c6a512013-12-18 23:48:012292
2293
[email protected]ca8d19842009-02-19 16:33:122294def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:542295 results = []
[email protected]1f7b4172010-01-28 01:17:342296 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542297 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:272298 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:342299 input_api,
2300 output_api,
[email protected]2fdd1f362013-01-16 03:56:032301 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:272302
[email protected]3e4eb112011-01-18 03:29:542303 results.extend(input_api.canned_checks.CheckChangeHasBugField(
2304 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:412305 results.extend(input_api.canned_checks.CheckChangeHasDescription(
2306 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:542307 return results