blob: 293d9dd3eeeb73a07bd2fd0de6ac67a2bd825d90 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d19842009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
tfarina78bb92f42015-01-31 00:20:488for more details about the presubmit API built into depot_tools.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]379e7dd2010-01-28 17:39:2112_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5413 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0014 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
15 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2816 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0817 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5418 r"^skia[\\\/].*",
primiano0166ccc82015-10-06 12:12:2819 r"^third_party[\\\/]WebKit[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5420 r"^v8[\\\/].*",
21 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5322 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3423 r".+[\\\/]pnacl_shim\.c$",
[email protected]e07b6ac72013-08-20 00:30:4224 r"^gpu[\\\/]config[\\\/].*_list_json\.cc$",
primiano0166ccc82015-10-06 12:12:2825 r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js",
[email protected]4306417642009-06-11 00:33:4026)
[email protected]ca8d19842009-02-19 16:33:1227
jochen9ea8fdbc2014-09-25 13:21:3528# The NetscapePlugIn library is excluded from pan-project as it will soon
29# be deleted together with the rest of the NPAPI and it's not worthwhile to
30# update the coding style until then.
[email protected]3de922f2013-12-20 13:27:3831_TESTRUNNER_PATHS = (
[email protected]de28fed2e2014-02-01 14:36:3232 r"^content[\\\/]shell[\\\/]tools[\\\/]plugin[\\\/].*",
[email protected]3de922f2013-12-20 13:27:3833)
34
[email protected]06e6d0ff2012-12-11 01:36:4435# Fragment of a regular expression that matches C++ and Objective-C++
36# implementation files.
37_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
38
39# Regular expression that matches code only used for test binaries
40# (best effort).
41_TEST_CODE_EXCLUDED_PATHS = (
joaodasilva718f87672014-08-30 09:25:4942 r'.*[\\\/](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4443 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
[email protected]6e04f8c2014-01-29 18:08:3244 r'.+_(api|browser|kif|perf|pixel|unit|ui)?test(_[a-z]+)?%s' %
[email protected]e2d7e6f2013-04-23 12:57:1245 _IMPLEMENTATION_EXTENSIONS,
[email protected]06e6d0ff2012-12-11 01:36:4446 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
joaodasilva718f87672014-08-30 09:25:4947 r'.*[\\\/](test|tool(s)?)[\\\/].*',
[email protected]ef070cc2013-05-03 11:53:0548 # content_shell is used for running layout tests.
joaodasilva718f87672014-08-30 09:25:4949 r'content[\\\/]shell[\\\/].*',
[email protected]06e6d0ff2012-12-11 01:36:4450 # At request of folks maintaining this folder.
joaodasilva718f87672014-08-30 09:25:4951 r'chrome[\\\/]browser[\\\/]automation[\\\/].*',
[email protected]7b054982013-11-27 00:44:4752 # Non-production example code.
joaodasilva718f87672014-08-30 09:25:4953 r'mojo[\\\/]examples[\\\/].*',
[email protected]8176de12014-06-20 19:07:0854 # Launcher for running iOS tests on the simulator.
joaodasilva718f87672014-08-30 09:25:4955 r'testing[\\\/]iossim[\\\/]iossim\.mm$',
[email protected]06e6d0ff2012-12-11 01:36:4456)
[email protected]ca8d19842009-02-19 16:33:1257
[email protected]eea609a2011-11-18 13:10:1258_TEST_ONLY_WARNING = (
59 'You might be calling functions intended only for testing from\n'
60 'production code. It is OK to ignore this warning if you know what\n'
61 'you are doing, as the heuristics used to detect the situation are\n'
[email protected]b0149772014-03-27 16:47:5862 'not perfect. The commit queue will not block on this warning.')
[email protected]eea609a2011-11-18 13:10:1263
64
[email protected]cf9b78f2012-11-14 11:40:2865_INCLUDE_ORDER_WARNING = (
marjaa017dc482015-03-09 17:13:4066 'Your #include order seems to be broken. Remember to use the right '
brucedawson70fadb02015-06-30 17:47:5567 'collation (LC_COLLATE=C) and check\nhttps://google-styleguide.googlecode'
marjaa017dc482015-03-09 17:13:4068 '.com/svn/trunk/cppguide.html#Names_and_Order_of_Includes')
[email protected]cf9b78f2012-11-14 11:40:2869
[email protected]127f18ec2012-06-16 05:05:5970_BANNED_OBJC_FUNCTIONS = (
71 (
72 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2073 (
74 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5975 'prohibited. Please use CrTrackingArea instead.',
76 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
77 ),
78 False,
79 ),
80 (
[email protected]eaae1972014-04-16 04:17:2681 r'/NSTrackingArea\W',
[email protected]23e6cbc2012-06-16 18:51:2082 (
83 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5984 'instead.',
85 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
86 ),
87 False,
88 ),
89 (
90 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2091 (
92 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5993 'Please use |convertPoint:(point) fromView:nil| instead.',
94 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
95 ),
96 True,
97 ),
98 (
99 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:20100 (
101 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59102 'Please use |convertPoint:(point) toView:nil| instead.',
103 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
104 ),
105 True,
106 ),
107 (
108 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20109 (
110 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59111 'Please use |convertRect:(point) fromView:nil| instead.',
112 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
113 ),
114 True,
115 ),
116 (
117 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20118 (
119 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59120 'Please use |convertRect:(point) toView:nil| instead.',
121 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
122 ),
123 True,
124 ),
125 (
126 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20127 (
128 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59129 'Please use |convertSize:(point) fromView:nil| instead.',
130 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
131 ),
132 True,
133 ),
134 (
135 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20136 (
137 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59138 'Please use |convertSize:(point) toView:nil| instead.',
139 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
140 ),
141 True,
142 ),
143)
144
145
146_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20147 # Make sure that gtest's FRIEND_TEST() macro is not used; the
148 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30149 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20150 (
151 'FRIEND_TEST(',
152 (
[email protected]e3c945502012-06-26 20:01:49153 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20154 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
155 ),
156 False,
[email protected]7345da02012-11-27 14:31:49157 (),
[email protected]23e6cbc2012-06-16 18:51:20158 ),
159 (
160 'ScopedAllowIO',
161 (
[email protected]e3c945502012-06-26 20:01:49162 'New code should not use ScopedAllowIO. Post a task to the blocking',
163 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20164 ),
[email protected]e3c945502012-06-26 20:01:49165 True,
[email protected]7345da02012-11-27 14:31:49166 (
thestig75844fdb2014-09-09 19:47:10167 r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
tfarina0923ac52015-01-07 03:21:22168 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
alematee4016bb2014-11-12 17:38:51169 r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
170 "customization_document_browsertest\.cc$",
philipj3f9d5bde2014-08-28 14:09:09171 r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
[email protected]de7d61ff2013-08-20 11:30:41172 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
173 r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
jamesra03ae492014-10-03 04:26:48174 r"^mojo[\\\/]edk[\\\/]embedder[\\\/]" +
175 r"simple_platform_shared_buffer_posix\.cc$",
[email protected]398ad132013-04-02 15:11:01176 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]1f52a572014-05-12 23:21:54177 r"^net[\\\/]url_request[\\\/]test_url_fetcher_factory\.cc$",
sergeyu34d21222015-09-16 00:11:44178 r"^remoting[\\\/]host[\\\/]gnubby_auth_handler_posix\.cc$",
dnicoara171d8c82015-03-05 20:46:18179 r"^ui[\\\/]ozone[\\\/]platform[\\\/]drm[\\\/]host[\\\/]"
dnicoarab29d0512015-05-07 19:29:23180 "drm_display_host_manager\.cc$",
[email protected]7345da02012-11-27 14:31:49181 ),
[email protected]23e6cbc2012-06-16 18:51:20182 ),
[email protected]52657f62013-05-20 05:30:31183 (
184 'SkRefPtr',
185 (
186 'The use of SkRefPtr is prohibited. ',
187 'Please use skia::RefPtr instead.'
188 ),
189 True,
190 (),
191 ),
192 (
193 'SkAutoRef',
194 (
195 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
196 'Please use skia::RefPtr instead.'
197 ),
198 True,
199 (),
200 ),
201 (
202 'SkAutoTUnref',
203 (
204 'The use of SkAutoTUnref is dangerous because it implicitly ',
205 'converts to a raw pointer. Please use skia::RefPtr instead.'
206 ),
207 True,
208 (),
209 ),
210 (
211 'SkAutoUnref',
212 (
213 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
214 'because it implicitly converts to a raw pointer. ',
215 'Please use skia::RefPtr instead.'
216 ),
217 True,
218 (),
219 ),
[email protected]d89eec82013-12-03 14:10:59220 (
221 r'/HANDLE_EINTR\(.*close',
222 (
223 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
224 'descriptor will be closed, and it is incorrect to retry the close.',
225 'Either call close directly and ignore its return value, or wrap close',
226 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
227 ),
228 True,
229 (),
230 ),
231 (
232 r'/IGNORE_EINTR\((?!.*close)',
233 (
234 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
235 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
236 ),
237 True,
238 (
239 # Files that #define IGNORE_EINTR.
240 r'^base[\\\/]posix[\\\/]eintr_wrapper\.h$',
241 r'^ppapi[\\\/]tests[\\\/]test_broker\.cc$',
242 ),
243 ),
[email protected]ec5b3f02014-04-04 18:43:43244 (
245 r'/v8::Extension\(',
246 (
247 'Do not introduce new v8::Extensions into the code base, use',
248 'gin::Wrappable instead. See http://crbug.com/334679',
249 ),
250 True,
[email protected]f55c90ee62014-04-12 00:50:03251 (
joaodasilva718f87672014-08-30 09:25:49252 r'extensions[\\\/]renderer[\\\/]safe_builtins\.*',
[email protected]f55c90ee62014-04-12 00:50:03253 ),
[email protected]ec5b3f02014-04-04 18:43:43254 ),
skyostilf9469f72015-04-20 10:38:52255 (
sdefresneeaeccc52015-04-22 08:18:32256 '\<MessageLoopProxy\>',
skyostilf9469f72015-04-20 10:38:52257 (
258 'MessageLoopProxy is deprecated. ',
259 'Please use SingleThreadTaskRunner or ThreadTaskRunnerHandle instead.'
260 ),
261 True,
kinuko59024ce2015-04-21 22:18:30262 (
263 # Internal message_loop related code may still use it.
264 r'^base[\\\/]message_loop[\\\/].*',
265 ),
skyostilf9469f72015-04-20 10:38:52266 ),
[email protected]127f18ec2012-06-16 05:05:59267)
268
mlamouria82272622014-09-16 18:45:04269_IPC_ENUM_TRAITS_DEPRECATED = (
270 'You are using IPC_ENUM_TRAITS() in your code. It has been deprecated.\n'
271 'See http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc')
272
[email protected]127f18ec2012-06-16 05:05:59273
[email protected]b00342e7f2013-03-26 16:21:54274_VALID_OS_MACROS = (
275 # Please keep sorted.
276 'OS_ANDROID',
[email protected]f4440b42014-03-19 05:47:01277 'OS_ANDROID_HOST',
[email protected]b00342e7f2013-03-26 16:21:54278 'OS_BSD',
279 'OS_CAT', # For testing.
280 'OS_CHROMEOS',
281 'OS_FREEBSD',
282 'OS_IOS',
283 'OS_LINUX',
284 'OS_MACOSX',
285 'OS_NACL',
hidehikof7295f22014-10-28 11:57:21286 'OS_NACL_NONSFI',
287 'OS_NACL_SFI',
[email protected]b00342e7f2013-03-26 16:21:54288 'OS_OPENBSD',
289 'OS_POSIX',
[email protected]eda7afa12014-02-06 12:27:37290 'OS_QNX',
[email protected]b00342e7f2013-03-26 16:21:54291 'OS_SOLARIS',
[email protected]b00342e7f2013-03-26 16:21:54292 'OS_WIN',
293)
294
295
[email protected]55459852011-08-10 15:17:19296def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
297 """Attempts to prevent use of functions intended only for testing in
298 non-testing code. For now this is just a best-effort implementation
299 that ignores header files and may have some false positives. A
300 better implementation would probably need a proper C++ parser.
301 """
302 # We only scan .cc files and the like, as the declaration of
303 # for-testing functions in header files are hard to distinguish from
304 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44305 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19306
jochenc0d4808c2015-07-27 09:25:42307 base_function_pattern = r'[ :]test::[^\s]+|ForTest(s|ing)?|for_test(s|ing)?'
[email protected]55459852011-08-10 15:17:19308 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
[email protected]23501822014-05-14 02:06:09309 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
[email protected]55459852011-08-10 15:17:19310 exclusion_pattern = input_api.re.compile(
311 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
312 base_function_pattern, base_function_pattern))
313
314 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44315 black_list = (_EXCLUDED_PATHS +
316 _TEST_CODE_EXCLUDED_PATHS +
317 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19318 return input_api.FilterSourceFile(
319 affected_file,
320 white_list=(file_inclusion_pattern, ),
321 black_list=black_list)
322
323 problems = []
324 for f in input_api.AffectedSourceFiles(FilterFile):
325 local_path = f.LocalPath()
[email protected]825d27182014-01-02 21:24:24326 for line_number, line in f.ChangedContents():
[email protected]2fdd1f362013-01-16 03:56:03327 if (inclusion_pattern.search(line) and
[email protected]de4f7d22013-05-23 14:27:46328 not comment_pattern.search(line) and
[email protected]2fdd1f362013-01-16 03:56:03329 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19330 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03331 '%s:%d\n %s' % (local_path, line_number, line.strip()))
[email protected]55459852011-08-10 15:17:19332
333 if problems:
[email protected]f7051d52013-04-02 18:31:42334 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03335 else:
336 return []
[email protected]55459852011-08-10 15:17:19337
338
[email protected]10689ca2011-09-02 02:31:54339def _CheckNoIOStreamInHeaders(input_api, output_api):
340 """Checks to make sure no .h files include <iostream>."""
341 files = []
342 pattern = input_api.re.compile(r'^#include\s*<iostream>',
343 input_api.re.MULTILINE)
344 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
345 if not f.LocalPath().endswith('.h'):
346 continue
347 contents = input_api.ReadFile(f)
348 if pattern.search(contents):
349 files.append(f)
350
351 if len(files):
352 return [ output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06353 'Do not #include <iostream> in header files, since it inserts static '
354 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54355 '#include <ostream>. See http://crbug.com/94794',
356 files) ]
357 return []
358
359
[email protected]72df4e782012-06-21 16:28:18360def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
danakj61c1aa22015-10-26 19:55:52361 """Checks to make sure no source files use UNIT_TEST."""
[email protected]72df4e782012-06-21 16:28:18362 problems = []
363 for f in input_api.AffectedFiles():
364 if (not f.LocalPath().endswith(('.cc', '.mm'))):
365 continue
366
367 for line_num, line in f.ChangedContents():
[email protected]549f86a2013-11-19 13:00:04368 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
[email protected]72df4e782012-06-21 16:28:18369 problems.append(' %s:%d' % (f.LocalPath(), line_num))
370
371 if not problems:
372 return []
373 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
374 '\n'.join(problems))]
375
376
danakj61c1aa22015-10-26 19:55:52377def _CheckDCHECK_IS_ONHasBraces(input_api, output_api):
378 """Checks to make sure DCHECK_IS_ON() does not skip the braces."""
379 errors = []
380 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))',
381 input_api.re.MULTILINE)
382 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
383 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))):
384 continue
385 for lnum, line in f.ChangedContents():
386 if input_api.re.search(pattern, line):
387 errors.append(output_api.PresubmitError(
388 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' +
389 'DCHECK_IS_ON()", not forgetting the braces.')
390 % (f.LocalPath(), lnum)))
391 return errors
392
393
mcasasb7440c282015-02-04 14:52:19394def _FindHistogramNameInLine(histogram_name, line):
395 """Tries to find a histogram name or prefix in a line."""
396 if not "affected-histogram" in line:
397 return histogram_name in line
398 # A histogram_suffixes tag type has an affected-histogram name as a prefix of
399 # the histogram_name.
400 if not '"' in line:
401 return False
402 histogram_prefix = line.split('\"')[1]
403 return histogram_prefix in histogram_name
404
405
406def _CheckUmaHistogramChanges(input_api, output_api):
407 """Check that UMA histogram names in touched lines can still be found in other
408 lines of the patch or in histograms.xml. Note that this check would not catch
409 the reverse: changes in histograms.xml not matched in the code itself."""
410 touched_histograms = []
411 histograms_xml_modifications = []
412 pattern = input_api.re.compile('UMA_HISTOGRAM.*\("(.*)"')
413 for f in input_api.AffectedFiles():
414 # If histograms.xml itself is modified, keep the modified lines for later.
415 if f.LocalPath().endswith(('histograms.xml')):
416 histograms_xml_modifications = f.ChangedContents()
417 continue
418 if not f.LocalPath().endswith(('cc', 'mm', 'cpp')):
419 continue
420 for line_num, line in f.ChangedContents():
421 found = pattern.search(line)
422 if found:
423 touched_histograms.append([found.group(1), f, line_num])
424
425 # Search for the touched histogram names in the local modifications to
426 # histograms.xml, and, if not found, on the base histograms.xml file.
427 unmatched_histograms = []
428 for histogram_info in touched_histograms:
429 histogram_name_found = False
430 for line_num, line in histograms_xml_modifications:
431 histogram_name_found = _FindHistogramNameInLine(histogram_info[0], line)
432 if histogram_name_found:
433 break
434 if not histogram_name_found:
435 unmatched_histograms.append(histogram_info)
436
eromanb90c82e7e32015-04-01 15:13:49437 histograms_xml_path = 'tools/metrics/histograms/histograms.xml'
mcasasb7440c282015-02-04 14:52:19438 problems = []
439 if unmatched_histograms:
eromanb90c82e7e32015-04-01 15:13:49440 with open(histograms_xml_path) as histograms_xml:
mcasasb7440c282015-02-04 14:52:19441 for histogram_name, f, line_num in unmatched_histograms:
mcasas39c1b8b2015-02-25 15:33:45442 histograms_xml.seek(0)
mcasasb7440c282015-02-04 14:52:19443 histogram_name_found = False
444 for line in histograms_xml:
445 histogram_name_found = _FindHistogramNameInLine(histogram_name, line)
446 if histogram_name_found:
447 break
448 if not histogram_name_found:
449 problems.append(' [%s:%d] %s' %
450 (f.LocalPath(), line_num, histogram_name))
451
452 if not problems:
453 return []
454 return [output_api.PresubmitPromptWarning('Some UMA_HISTOGRAM lines have '
455 'been modified and the associated histogram name has no match in either '
eromanb90c82e7e32015-04-01 15:13:49456 '%s or the modifications of it:' % (histograms_xml_path), problems)]
mcasasb7440c282015-02-04 14:52:19457
458
[email protected]8ea5d4b2011-09-13 21:49:22459def _CheckNoNewWStrings(input_api, output_api):
460 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27461 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22462 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20463 if (not f.LocalPath().endswith(('.cc', '.h')) or
scottmge6f04402014-11-05 01:59:57464 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or
465 '/win/' in f.LocalPath()):
[email protected]b5c24292011-11-28 14:38:20466 continue
[email protected]8ea5d4b2011-09-13 21:49:22467
[email protected]a11dbe9b2012-08-07 01:32:58468 allowWString = False
[email protected]b5c24292011-11-28 14:38:20469 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58470 if 'presubmit: allow wstring' in line:
471 allowWString = True
472 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27473 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58474 allowWString = False
475 else:
476 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22477
[email protected]55463aa62011-10-12 00:48:27478 if not problems:
479 return []
480 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58481 ' If you are calling a cross-platform API that accepts a wstring, '
482 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27483 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22484
485
[email protected]2a8ac9c2011-10-19 17:20:44486def _CheckNoDEPSGIT(input_api, output_api):
487 """Make sure .DEPS.git is never modified manually."""
488 if any(f.LocalPath().endswith('.DEPS.git') for f in
489 input_api.AffectedFiles()):
490 return [output_api.PresubmitError(
491 'Never commit changes to .DEPS.git. This file is maintained by an\n'
492 'automated system based on what\'s in DEPS and your changes will be\n'
493 'overwritten.\n'
[email protected]cb706912014-06-28 20:46:34494 '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:44495 'for more information')]
496 return []
497
498
tandriief664692014-09-23 14:51:47499def _CheckValidHostsInDEPS(input_api, output_api):
500 """Checks that DEPS file deps are from allowed_hosts."""
501 # Run only if DEPS file has been modified to annoy fewer bystanders.
502 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
503 return []
504 # Outsource work to gclient verify
505 try:
506 input_api.subprocess.check_output(['gclient', 'verify'])
507 return []
508 except input_api.subprocess.CalledProcessError, error:
509 return [output_api.PresubmitError(
510 'DEPS file must have only git dependencies.',
511 long_text=error.output)]
512
513
[email protected]127f18ec2012-06-16 05:05:59514def _CheckNoBannedFunctions(input_api, output_api):
515 """Make sure that banned functions are not used."""
516 warnings = []
517 errors = []
518
519 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
520 for f in input_api.AffectedFiles(file_filter=file_filter):
521 for line_num, line in f.ChangedContents():
522 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
[email protected]eaae1972014-04-16 04:17:26523 matched = False
524 if func_name[0:1] == '/':
525 regex = func_name[1:]
526 if input_api.re.search(regex, line):
527 matched = True
528 elif func_name in line:
529 matched = True
530 if matched:
[email protected]127f18ec2012-06-16 05:05:59531 problems = warnings;
532 if error:
533 problems = errors;
534 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
535 for message_line in message:
536 problems.append(' %s' % message_line)
537
538 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
539 for f in input_api.AffectedFiles(file_filter=file_filter):
540 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49541 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
542 def IsBlacklisted(affected_file, blacklist):
543 local_path = affected_file.LocalPath()
544 for item in blacklist:
545 if input_api.re.match(item, local_path):
546 return True
547 return False
548 if IsBlacklisted(f, excluded_paths):
549 continue
[email protected]d89eec82013-12-03 14:10:59550 matched = False
551 if func_name[0:1] == '/':
552 regex = func_name[1:]
553 if input_api.re.search(regex, line):
554 matched = True
555 elif func_name in line:
556 matched = True
557 if matched:
[email protected]127f18ec2012-06-16 05:05:59558 problems = warnings;
559 if error:
560 problems = errors;
561 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
562 for message_line in message:
563 problems.append(' %s' % message_line)
564
565 result = []
566 if (warnings):
567 result.append(output_api.PresubmitPromptWarning(
568 'Banned functions were used.\n' + '\n'.join(warnings)))
569 if (errors):
570 result.append(output_api.PresubmitError(
571 'Banned functions were used.\n' + '\n'.join(errors)))
572 return result
573
574
[email protected]6c063c62012-07-11 19:11:06575def _CheckNoPragmaOnce(input_api, output_api):
576 """Make sure that banned functions are not used."""
577 files = []
578 pattern = input_api.re.compile(r'^#pragma\s+once',
579 input_api.re.MULTILINE)
580 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
581 if not f.LocalPath().endswith('.h'):
582 continue
583 contents = input_api.ReadFile(f)
584 if pattern.search(contents):
585 files.append(f)
586
587 if files:
588 return [output_api.PresubmitError(
589 'Do not use #pragma once in header files.\n'
590 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
591 files)]
592 return []
593
[email protected]127f18ec2012-06-16 05:05:59594
[email protected]e7479052012-09-19 00:26:12595def _CheckNoTrinaryTrueFalse(input_api, output_api):
596 """Checks to make sure we don't introduce use of foo ? true : false."""
597 problems = []
598 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
599 for f in input_api.AffectedFiles():
600 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
601 continue
602
603 for line_num, line in f.ChangedContents():
604 if pattern.match(line):
605 problems.append(' %s:%d' % (f.LocalPath(), line_num))
606
607 if not problems:
608 return []
609 return [output_api.PresubmitPromptWarning(
610 'Please consider avoiding the "? true : false" pattern if possible.\n' +
611 '\n'.join(problems))]
612
613
[email protected]55f9f382012-07-31 11:02:18614def _CheckUnwantedDependencies(input_api, output_api):
615 """Runs checkdeps on #include statements added in this
616 change. Breaking - rules is an error, breaking ! rules is a
617 warning.
618 """
mohan.reddyf21db962014-10-16 12:26:47619 import sys
[email protected]55f9f382012-07-31 11:02:18620 # We need to wait until we have an input_api object and use this
621 # roundabout construct to import checkdeps because this file is
622 # eval-ed and thus doesn't have __file__.
623 original_sys_path = sys.path
624 try:
625 sys.path = sys.path + [input_api.os_path.join(
[email protected]5298cc982014-05-29 20:53:47626 input_api.PresubmitLocalPath(), 'buildtools', 'checkdeps')]
[email protected]55f9f382012-07-31 11:02:18627 import checkdeps
628 from cpp_checker import CppChecker
629 from rules import Rule
630 finally:
631 # Restore sys.path to what it was before.
632 sys.path = original_sys_path
633
634 added_includes = []
635 for f in input_api.AffectedFiles():
636 if not CppChecker.IsCppFile(f.LocalPath()):
637 continue
638
639 changed_lines = [line for line_num, line in f.ChangedContents()]
640 added_includes.append([f.LocalPath(), changed_lines])
641
[email protected]26385172013-05-09 23:11:35642 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
[email protected]55f9f382012-07-31 11:02:18643
644 error_descriptions = []
645 warning_descriptions = []
646 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
647 added_includes):
648 description_with_path = '%s\n %s' % (path, rule_description)
649 if rule_type == Rule.DISALLOW:
650 error_descriptions.append(description_with_path)
651 else:
652 warning_descriptions.append(description_with_path)
653
654 results = []
655 if error_descriptions:
656 results.append(output_api.PresubmitError(
657 'You added one or more #includes that violate checkdeps rules.',
658 error_descriptions))
659 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42660 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18661 'You added one or more #includes of files that are temporarily\n'
662 'allowed but being removed. Can you avoid introducing the\n'
663 '#include? See relevant DEPS file(s) for details and contacts.',
664 warning_descriptions))
665 return results
666
667
[email protected]fbcafe5a2012-08-08 15:31:22668def _CheckFilePermissions(input_api, output_api):
669 """Check that all files have their permissions properly set."""
[email protected]791507202014-02-03 23:19:15670 if input_api.platform == 'win32':
671 return []
mohan.reddyf21db962014-10-16 12:26:47672 args = [input_api.python_executable, 'tools/checkperms/checkperms.py',
673 '--root', input_api.change.RepositoryRoot()]
[email protected]fbcafe5a2012-08-08 15:31:22674 for f in input_api.AffectedFiles():
675 args += ['--file', f.LocalPath()]
phajdan.jr5ea54792015-10-14 10:51:11676 try:
677 input_api.subprocess.check_output(args)
678 return []
679 except input_api.subprocess.CalledProcessError as error:
680 return [output_api.PresubmitError(
681 'checkperms.py failed:',
682 long_text=error.output)]
[email protected]fbcafe5a2012-08-08 15:31:22683
684
[email protected]c8278b32012-10-30 20:35:49685def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
686 """Makes sure we don't include ui/aura/window_property.h
687 in header files.
688 """
689 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
690 errors = []
691 for f in input_api.AffectedFiles():
692 if not f.LocalPath().endswith('.h'):
693 continue
694 for line_num, line in f.ChangedContents():
695 if pattern.match(line):
696 errors.append(' %s:%d' % (f.LocalPath(), line_num))
697
698 results = []
699 if errors:
700 results.append(output_api.PresubmitError(
701 'Header files should not include ui/aura/window_property.h', errors))
702 return results
703
704
[email protected]cf9b78f2012-11-14 11:40:28705def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
706 """Checks that the lines in scope occur in the right order.
707
708 1. C system files in alphabetical order
709 2. C++ system files in alphabetical order
710 3. Project's .h files
711 """
712
713 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
714 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
715 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
716
717 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
718
719 state = C_SYSTEM_INCLUDES
720
721 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57722 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28723 problem_linenums = []
brucedawson70fadb02015-06-30 17:47:55724 out_of_order = " - line belongs before previous line"
[email protected]cf9b78f2012-11-14 11:40:28725 for line_num, line in scope:
726 if c_system_include_pattern.match(line):
727 if state != C_SYSTEM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55728 problem_linenums.append((line_num, previous_line_num,
729 " - C system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28730 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55731 problem_linenums.append((line_num, previous_line_num,
732 out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28733 elif cpp_system_include_pattern.match(line):
734 if state == C_SYSTEM_INCLUDES:
735 state = CPP_SYSTEM_INCLUDES
736 elif state == CUSTOM_INCLUDES:
brucedawson70fadb02015-06-30 17:47:55737 problem_linenums.append((line_num, previous_line_num,
738 " - c++ system include file in wrong block"))
[email protected]cf9b78f2012-11-14 11:40:28739 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55740 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28741 elif custom_include_pattern.match(line):
742 if state != CUSTOM_INCLUDES:
743 state = CUSTOM_INCLUDES
744 elif previous_line and previous_line > line:
brucedawson70fadb02015-06-30 17:47:55745 problem_linenums.append((line_num, previous_line_num, out_of_order))
[email protected]cf9b78f2012-11-14 11:40:28746 else:
brucedawson70fadb02015-06-30 17:47:55747 problem_linenums.append((line_num, previous_line_num,
748 "Unknown include type"))
[email protected]cf9b78f2012-11-14 11:40:28749 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57750 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28751
752 warnings = []
brucedawson70fadb02015-06-30 17:47:55753 for (line_num, previous_line_num, failure_type) in problem_linenums:
[email protected]728b9bb2012-11-14 20:38:57754 if line_num in changed_linenums or previous_line_num in changed_linenums:
brucedawson70fadb02015-06-30 17:47:55755 warnings.append(' %s:%d:%s' % (file_path, line_num, failure_type))
[email protected]cf9b78f2012-11-14 11:40:28756 return warnings
757
758
[email protected]ac294a12012-12-06 16:38:43759def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28760 """Checks the #include order for the given file f."""
761
[email protected]2299dcf2012-11-15 19:56:24762 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]23093b62013-09-20 12:16:30763 # Exclude the following includes from the check:
764 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
765 # specific order.
766 # 2) <atlbase.h>, "build/build_config.h"
767 excluded_include_pattern = input_api.re.compile(
768 r'\s*#include (\<.*/.*|\<atlbase\.h\>|"build/build_config.h")')
[email protected]2299dcf2012-11-15 19:56:24769 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]3e83618c2013-10-09 22:32:33770 # Match the final or penultimate token if it is xxxtest so we can ignore it
771 # when considering the special first include.
772 test_file_tag_pattern = input_api.re.compile(
773 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
[email protected]0e5c1852012-12-18 20:17:11774 if_pattern = input_api.re.compile(
775 r'\s*#\s*(if|elif|else|endif|define|undef).*')
776 # Some files need specialized order of includes; exclude such files from this
777 # check.
778 uncheckable_includes_pattern = input_api.re.compile(
779 r'\s*#include '
780 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28781
782 contents = f.NewContents()
783 warnings = []
784 line_num = 0
785
[email protected]ac294a12012-12-06 16:38:43786 # Handle the special first include. If the first include file is
787 # some/path/file.h, the corresponding including file can be some/path/file.cc,
788 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
789 # etc. It's also possible that no special first include exists.
[email protected]3e83618c2013-10-09 22:32:33790 # If the included file is some/path/file_platform.h the including file could
791 # also be some/path/file_xxxtest_platform.h.
792 including_file_base_name = test_file_tag_pattern.sub(
793 '', input_api.os_path.basename(f.LocalPath()))
794
[email protected]ac294a12012-12-06 16:38:43795 for line in contents:
796 line_num += 1
797 if system_include_pattern.match(line):
798 # No special first include -> process the line again along with normal
799 # includes.
800 line_num -= 1
801 break
802 match = custom_include_pattern.match(line)
803 if match:
804 match_dict = match.groupdict()
[email protected]3e83618c2013-10-09 22:32:33805 header_basename = test_file_tag_pattern.sub(
806 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
807
808 if header_basename not in including_file_base_name:
[email protected]2299dcf2012-11-15 19:56:24809 # No special first include -> process the line again along with normal
810 # includes.
811 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43812 break
[email protected]cf9b78f2012-11-14 11:40:28813
814 # Split into scopes: Each region between #if and #endif is its own scope.
815 scopes = []
816 current_scope = []
817 for line in contents[line_num:]:
818 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11819 if uncheckable_includes_pattern.match(line):
[email protected]4436c9e2014-01-07 23:19:54820 continue
[email protected]2309b0fa02012-11-16 12:18:27821 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28822 scopes.append(current_scope)
823 current_scope = []
[email protected]962f117e2012-11-22 18:11:56824 elif ((system_include_pattern.match(line) or
825 custom_include_pattern.match(line)) and
826 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28827 current_scope.append((line_num, line))
828 scopes.append(current_scope)
829
830 for scope in scopes:
831 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
832 changed_linenums))
833 return warnings
834
835
836def _CheckIncludeOrder(input_api, output_api):
837 """Checks that the #include order is correct.
838
839 1. The corresponding header for source files.
840 2. C system files in alphabetical order
841 3. C++ system files in alphabetical order
842 4. Project's .h files in alphabetical order
843
[email protected]ac294a12012-12-06 16:38:43844 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
845 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28846 """
[email protected]e120b012014-08-15 19:08:35847 def FileFilterIncludeOrder(affected_file):
848 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
849 return input_api.FilterSourceFile(affected_file, black_list=black_list)
[email protected]cf9b78f2012-11-14 11:40:28850
851 warnings = []
[email protected]e120b012014-08-15 19:08:35852 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
tapted574f09c2015-05-19 13:08:08853 if f.LocalPath().endswith(('.cc', '.h', '.mm')):
[email protected]ac294a12012-12-06 16:38:43854 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
855 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28856
857 results = []
858 if warnings:
[email protected]f7051d52013-04-02 18:31:42859 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53860 warnings))
[email protected]cf9b78f2012-11-14 11:40:28861 return results
862
863
[email protected]70ca77752012-11-20 03:45:03864def _CheckForVersionControlConflictsInFile(input_api, f):
865 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
866 errors = []
867 for line_num, line in f.ChangedContents():
dbeam95c35a2f2015-06-02 01:40:23868 if f.LocalPath().endswith('.md'):
869 # First-level headers in markdown look a lot like version control
870 # conflict markers. http://daringfireball.net/projects/markdown/basics
871 continue
[email protected]70ca77752012-11-20 03:45:03872 if pattern.match(line):
873 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
874 return errors
875
876
877def _CheckForVersionControlConflicts(input_api, output_api):
878 """Usually this is not intentional and will cause a compile failure."""
879 errors = []
880 for f in input_api.AffectedFiles():
881 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
882
883 results = []
884 if errors:
885 results.append(output_api.PresubmitError(
886 'Version control conflict markers found, please resolve.', errors))
887 return results
888
889
[email protected]06e6d0ff2012-12-11 01:36:44890def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
891 def FilterFile(affected_file):
892 """Filter function for use with input_api.AffectedSourceFiles,
893 below. This filters out everything except non-test files from
894 top-level directories that generally speaking should not hard-code
895 service URLs (e.g. src/android_webview/, src/content/ and others).
896 """
897 return input_api.FilterSourceFile(
898 affected_file,
[email protected]78bb39d62012-12-11 15:11:56899 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44900 black_list=(_EXCLUDED_PATHS +
901 _TEST_CODE_EXCLUDED_PATHS +
902 input_api.DEFAULT_BLACK_LIST))
903
[email protected]de4f7d22013-05-23 14:27:46904 base_pattern = '"[^"]*google\.com[^"]*"'
905 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
906 pattern = input_api.re.compile(base_pattern)
[email protected]06e6d0ff2012-12-11 01:36:44907 problems = [] # items are (filename, line_number, line)
908 for f in input_api.AffectedSourceFiles(FilterFile):
909 for line_num, line in f.ChangedContents():
[email protected]de4f7d22013-05-23 14:27:46910 if not comment_pattern.search(line) and pattern.search(line):
[email protected]06e6d0ff2012-12-11 01:36:44911 problems.append((f.LocalPath(), line_num, line))
912
913 if problems:
[email protected]f7051d52013-04-02 18:31:42914 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44915 'Most layers below src/chrome/ should not hardcode service URLs.\n'
[email protected]b0149772014-03-27 16:47:58916 'Are you sure this is correct?',
[email protected]06e6d0ff2012-12-11 01:36:44917 [' %s:%d: %s' % (
918 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03919 else:
920 return []
[email protected]06e6d0ff2012-12-11 01:36:44921
922
[email protected]d2530012013-01-25 16:39:27923def _CheckNoAbbreviationInPngFileName(input_api, output_api):
924 """Makes sure there are no abbreviations in the name of PNG files.
binji0dcdf342014-12-12 18:32:31925 The native_client_sdk directory is excluded because it has auto-generated PNG
926 files for documentation.
[email protected]d2530012013-01-25 16:39:27927 """
[email protected]d2530012013-01-25 16:39:27928 errors = []
binji0dcdf342014-12-12 18:32:31929 white_list = (r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$',)
930 black_list = (r'^native_client_sdk[\\\/]',)
931 file_filter = lambda f: input_api.FilterSourceFile(
932 f, white_list=white_list, black_list=black_list)
933 for f in input_api.AffectedFiles(include_deletes=False,
934 file_filter=file_filter):
935 errors.append(' %s' % f.LocalPath())
[email protected]d2530012013-01-25 16:39:27936
937 results = []
938 if errors:
939 results.append(output_api.PresubmitError(
940 'The name of PNG files should not have abbreviations. \n'
941 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
942 'Contact [email protected] if you have questions.', errors))
943 return results
944
945
[email protected]14a6131c2014-01-08 01:15:41946def _FilesToCheckForIncomingDeps(re, changed_lines):
[email protected]f32e2d1e2013-07-26 21:39:08947 """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns
[email protected]14a6131c2014-01-08 01:15:41948 a set of DEPS entries that we should look up.
949
950 For a directory (rather than a specific filename) we fake a path to
951 a specific filename by adding /DEPS. This is chosen as a file that
952 will seldom or never be subject to per-file include_rules.
953 """
[email protected]2b438d62013-11-14 17:54:14954 # We ignore deps entries on auto-generated directories.
955 AUTO_GENERATED_DIRS = ['grit', 'jni']
[email protected]f32e2d1e2013-07-26 21:39:08956
957 # This pattern grabs the path without basename in the first
958 # parentheses, and the basename (if present) in the second. It
959 # relies on the simple heuristic that if there is a basename it will
960 # be a header file ending in ".h".
961 pattern = re.compile(
962 r"""['"]\+([^'"]+?)(/[a-zA-Z0-9_]+\.h)?['"].*""")
[email protected]2b438d62013-11-14 17:54:14963 results = set()
[email protected]f32e2d1e2013-07-26 21:39:08964 for changed_line in changed_lines:
965 m = pattern.match(changed_line)
966 if m:
967 path = m.group(1)
[email protected]2b438d62013-11-14 17:54:14968 if path.split('/')[0] not in AUTO_GENERATED_DIRS:
[email protected]14a6131c2014-01-08 01:15:41969 if m.group(2):
970 results.add('%s%s' % (path, m.group(2)))
971 else:
972 results.add('%s/DEPS' % path)
[email protected]f32e2d1e2013-07-26 21:39:08973 return results
974
975
[email protected]e871964c2013-05-13 14:14:55976def _CheckAddedDepsHaveTargetApprovals(input_api, output_api):
977 """When a dependency prefixed with + is added to a DEPS file, we
978 want to make sure that the change is reviewed by an OWNER of the
979 target file or directory, to avoid layering violations from being
980 introduced. This check verifies that this happens.
981 """
982 changed_lines = set()
983 for f in input_api.AffectedFiles():
984 filename = input_api.os_path.basename(f.LocalPath())
985 if filename == 'DEPS':
986 changed_lines |= set(line.strip()
987 for line_num, line
988 in f.ChangedContents())
989 if not changed_lines:
990 return []
991
[email protected]14a6131c2014-01-08 01:15:41992 virtual_depended_on_files = _FilesToCheckForIncomingDeps(input_api.re,
993 changed_lines)
[email protected]e871964c2013-05-13 14:14:55994 if not virtual_depended_on_files:
995 return []
996
997 if input_api.is_committing:
998 if input_api.tbr:
999 return [output_api.PresubmitNotifyResult(
1000 '--tbr was specified, skipping OWNERS check for DEPS additions')]
1001 if not input_api.change.issue:
1002 return [output_api.PresubmitError(
1003 "DEPS approval by OWNERS check failed: this change has "
1004 "no Rietveld issue number, so we can't check it for approvals.")]
1005 output = output_api.PresubmitError
1006 else:
1007 output = output_api.PresubmitNotifyResult
1008
1009 owners_db = input_api.owners_db
1010 owner_email, reviewers = input_api.canned_checks._RietveldOwnerAndReviewers(
1011 input_api,
1012 owners_db.email_regexp,
1013 approval_needed=input_api.is_committing)
1014
1015 owner_email = owner_email or input_api.change.author_email
1016
[email protected]de4f7d22013-05-23 14:27:461017 reviewers_plus_owner = set(reviewers)
[email protected]e71c6082013-05-22 02:28:511018 if owner_email:
[email protected]de4f7d22013-05-23 14:27:461019 reviewers_plus_owner.add(owner_email)
[email protected]e871964c2013-05-13 14:14:551020 missing_files = owners_db.files_not_covered_by(virtual_depended_on_files,
1021 reviewers_plus_owner)
[email protected]14a6131c2014-01-08 01:15:411022
1023 # We strip the /DEPS part that was added by
1024 # _FilesToCheckForIncomingDeps to fake a path to a file in a
1025 # directory.
1026 def StripDeps(path):
1027 start_deps = path.rfind('/DEPS')
1028 if start_deps != -1:
1029 return path[:start_deps]
1030 else:
1031 return path
1032 unapproved_dependencies = ["'+%s'," % StripDeps(path)
[email protected]e871964c2013-05-13 14:14:551033 for path in missing_files]
1034
1035 if unapproved_dependencies:
1036 output_list = [
[email protected]14a6131c2014-01-08 01:15:411037 output('Missing LGTM from OWNERS of dependencies added to DEPS:\n %s' %
[email protected]e871964c2013-05-13 14:14:551038 '\n '.join(sorted(unapproved_dependencies)))]
1039 if not input_api.is_committing:
1040 suggested_owners = owners_db.reviewers_for(missing_files, owner_email)
1041 output_list.append(output(
1042 'Suggested missing target path OWNERS:\n %s' %
1043 '\n '.join(suggested_owners or [])))
1044 return output_list
1045
1046 return []
1047
1048
[email protected]85218562013-11-22 07:41:401049def _CheckSpamLogging(input_api, output_api):
1050 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1051 black_list = (_EXCLUDED_PATHS +
1052 _TEST_CODE_EXCLUDED_PATHS +
1053 input_api.DEFAULT_BLACK_LIST +
[email protected]6f742dd02013-11-26 23:19:501054 (r"^base[\\\/]logging\.h$",
[email protected]80f360a2014-01-23 01:36:191055 r"^base[\\\/]logging\.cc$",
[email protected]8dc338c2013-12-09 16:28:481056 r"^chrome[\\\/]app[\\\/]chrome_main_delegate\.cc$",
[email protected]6e268db2013-12-04 01:41:461057 r"^chrome[\\\/]browser[\\\/]chrome_browser_main\.cc$",
[email protected]4de75262013-12-18 23:16:121058 r"^chrome[\\\/]browser[\\\/]ui[\\\/]startup[\\\/]"
1059 r"startup_browser_creator\.cc$",
[email protected]fe0e6e12013-12-04 05:52:581060 r"^chrome[\\\/]installer[\\\/]setup[\\\/].*",
[email protected]8cf6f842014-08-08 21:33:161061 r"chrome[\\\/]browser[\\\/]diagnostics[\\\/]" +
[email protected]f5b9a3f342014-08-08 22:06:031062 r"diagnostics_writer\.cc$",
[email protected]9f13b602014-08-07 02:59:151063 r"^chrome_elf[\\\/]dll_hash[\\\/]dll_hash_main\.cc$",
1064 r"^chromecast[\\\/]",
1065 r"^cloud_print[\\\/]",
jochen34415e52015-07-10 08:34:311066 r"^components[\\\/]html_viewer[\\\/]"
1067 r"web_test_delegate_impl\.cc$",
peter80739bb2015-10-20 11:17:461068 # TODO(peter): Remove this exception. https://crbug.com/534537
1069 r"^content[\\\/]browser[\\\/]notifications[\\\/]"
1070 r"notification_event_dispatcher_impl\.cc$",
[email protected]9056e732014-01-08 06:25:251071 r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
1072 r"gl_helper_benchmark\.cc$",
thestigc9e38a22014-09-13 01:02:111073 r"^courgette[\\\/]courgette_tool\.cc$",
[email protected]9f13b602014-08-07 02:59:151074 r"^extensions[\\\/]renderer[\\\/]logging_native_handler\.cc$",
prashant.nb0252f62014-11-08 05:02:111075 r"^ipc[\\\/]ipc_logging\.cc$",
[email protected]9c36d922014-03-24 16:47:521076 r"^native_client_sdk[\\\/]",
[email protected]cdbdced2013-11-27 21:35:501077 r"^remoting[\\\/]base[\\\/]logging\.h$",
[email protected]67c96ab2013-12-17 02:05:361078 r"^remoting[\\\/]host[\\\/].*",
[email protected]8232f8fd2013-12-14 00:52:311079 r"^sandbox[\\\/]linux[\\\/].*",
[email protected]0b7a21e2014-02-11 18:38:131080 r"^tools[\\\/]",
thestig22dfc4012014-09-05 08:29:441081 r"^ui[\\\/]aura[\\\/]bench[\\\/]bench_main\.cc$",
vchigrin14251492015-01-12 08:09:021082 r"^storage[\\\/]browser[\\\/]fileapi[\\\/]" +
thestig22dfc4012014-09-05 08:29:441083 r"dump_file_system.cc$",))
[email protected]85218562013-11-22 07:41:401084 source_file_filter = lambda x: input_api.FilterSourceFile(
1085 x, white_list=(file_inclusion_pattern,), black_list=black_list)
1086
1087 log_info = []
1088 printf = []
1089
1090 for f in input_api.AffectedSourceFiles(source_file_filter):
1091 contents = input_api.ReadFile(f, 'rb')
mohan.reddyf21db962014-10-16 12:26:471092 if input_api.re.search(r"\bD?LOG\s*\(\s*INFO\s*\)", contents):
[email protected]85218562013-11-22 07:41:401093 log_info.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471094 elif input_api.re.search(r"\bD?LOG_IF\s*\(\s*INFO\s*,", contents):
[email protected]85210652013-11-28 05:50:131095 log_info.append(f.LocalPath())
[email protected]18b466b2013-12-02 22:01:371096
mohan.reddyf21db962014-10-16 12:26:471097 if input_api.re.search(r"\bprintf\(", contents):
[email protected]18b466b2013-12-02 22:01:371098 printf.append(f.LocalPath())
mohan.reddyf21db962014-10-16 12:26:471099 elif input_api.re.search(r"\bfprintf\((stdout|stderr)", contents):
[email protected]85218562013-11-22 07:41:401100 printf.append(f.LocalPath())
1101
1102 if log_info:
1103 return [output_api.PresubmitError(
1104 'These files spam the console log with LOG(INFO):',
1105 items=log_info)]
1106 if printf:
1107 return [output_api.PresubmitError(
1108 'These files spam the console log with printf/fprintf:',
1109 items=printf)]
1110 return []
1111
1112
[email protected]49aa76a2013-12-04 06:59:161113def _CheckForAnonymousVariables(input_api, output_api):
1114 """These types are all expected to hold locks while in scope and
1115 so should never be anonymous (which causes them to be immediately
1116 destroyed)."""
1117 they_who_must_be_named = [
1118 'base::AutoLock',
1119 'base::AutoReset',
1120 'base::AutoUnlock',
1121 'SkAutoAlphaRestore',
1122 'SkAutoBitmapShaderInstall',
1123 'SkAutoBlitterChoose',
1124 'SkAutoBounderCommit',
1125 'SkAutoCallProc',
1126 'SkAutoCanvasRestore',
1127 'SkAutoCommentBlock',
1128 'SkAutoDescriptor',
1129 'SkAutoDisableDirectionCheck',
1130 'SkAutoDisableOvalCheck',
1131 'SkAutoFree',
1132 'SkAutoGlyphCache',
1133 'SkAutoHDC',
1134 'SkAutoLockColors',
1135 'SkAutoLockPixels',
1136 'SkAutoMalloc',
1137 'SkAutoMaskFreeImage',
1138 'SkAutoMutexAcquire',
1139 'SkAutoPathBoundsUpdate',
1140 'SkAutoPDFRelease',
1141 'SkAutoRasterClipValidate',
1142 'SkAutoRef',
1143 'SkAutoTime',
1144 'SkAutoTrace',
1145 'SkAutoUnref',
1146 ]
1147 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
1148 # bad: base::AutoLock(lock.get());
1149 # not bad: base::AutoLock lock(lock.get());
1150 bad_pattern = input_api.re.compile(anonymous)
1151 # good: new base::AutoLock(lock.get())
1152 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
1153 errors = []
1154
1155 for f in input_api.AffectedFiles():
1156 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
1157 continue
1158 for linenum, line in f.ChangedContents():
1159 if bad_pattern.search(line) and not good_pattern.search(line):
1160 errors.append('%s:%d' % (f.LocalPath(), linenum))
1161
1162 if errors:
1163 return [output_api.PresubmitError(
1164 'These lines create anonymous variables that need to be named:',
1165 items=errors)]
1166 return []
1167
1168
[email protected]5fe0f8742013-11-29 01:04:591169def _CheckCygwinShell(input_api, output_api):
1170 source_file_filter = lambda x: input_api.FilterSourceFile(
1171 x, white_list=(r'.+\.(gyp|gypi)$',))
1172 cygwin_shell = []
1173
1174 for f in input_api.AffectedSourceFiles(source_file_filter):
1175 for linenum, line in f.ChangedContents():
1176 if 'msvs_cygwin_shell' in line:
1177 cygwin_shell.append(f.LocalPath())
1178 break
1179
1180 if cygwin_shell:
1181 return [output_api.PresubmitError(
1182 'These files should not use msvs_cygwin_shell (the default is 0):',
1183 items=cygwin_shell)]
1184 return []
1185
[email protected]85218562013-11-22 07:41:401186
[email protected]999261d2014-03-03 20:08:081187def _CheckUserActionUpdate(input_api, output_api):
1188 """Checks if any new user action has been added."""
[email protected]2f92dec2014-03-07 19:21:521189 if any('actions.xml' == input_api.os_path.basename(f) for f in
[email protected]999261d2014-03-03 20:08:081190 input_api.LocalPaths()):
[email protected]2f92dec2014-03-07 19:21:521191 # If actions.xml is already included in the changelist, the PRESUBMIT
1192 # for actions.xml will do a more complete presubmit check.
[email protected]999261d2014-03-03 20:08:081193 return []
1194
[email protected]999261d2014-03-03 20:08:081195 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm'))
1196 action_re = r'[^a-zA-Z]UserMetricsAction\("([^"]*)'
[email protected]2f92dec2014-03-07 19:21:521197 current_actions = None
[email protected]999261d2014-03-03 20:08:081198 for f in input_api.AffectedFiles(file_filter=file_filter):
1199 for line_num, line in f.ChangedContents():
1200 match = input_api.re.search(action_re, line)
1201 if match:
[email protected]2f92dec2014-03-07 19:21:521202 # Loads contents in tools/metrics/actions/actions.xml to memory. It's
1203 # loaded only once.
1204 if not current_actions:
1205 with open('tools/metrics/actions/actions.xml') as actions_f:
1206 current_actions = actions_f.read()
1207 # Search for the matched user action name in |current_actions|.
[email protected]999261d2014-03-03 20:08:081208 for action_name in match.groups():
[email protected]2f92dec2014-03-07 19:21:521209 action = 'name="{0}"'.format(action_name)
1210 if action not in current_actions:
[email protected]999261d2014-03-03 20:08:081211 return [output_api.PresubmitPromptWarning(
1212 'File %s line %d: %s is missing in '
[email protected]2f92dec2014-03-07 19:21:521213 'tools/metrics/actions/actions.xml. Please run '
1214 'tools/metrics/actions/extract_actions.py to update.'
[email protected]999261d2014-03-03 20:08:081215 % (f.LocalPath(), line_num, action_name))]
1216 return []
1217
1218
[email protected]99171a92014-06-03 08:44:471219def _GetJSONParseError(input_api, filename, eat_comments=True):
1220 try:
1221 contents = input_api.ReadFile(filename)
1222 if eat_comments:
plundblad1f5a4509f2015-07-23 11:31:131223 import sys
1224 original_sys_path = sys.path
1225 try:
1226 sys.path = sys.path + [input_api.os_path.join(
1227 input_api.PresubmitLocalPath(),
1228 'tools', 'json_comment_eater')]
1229 import json_comment_eater
1230 finally:
1231 sys.path = original_sys_path
1232 contents = json_comment_eater.Nom(contents)
[email protected]99171a92014-06-03 08:44:471233
1234 input_api.json.loads(contents)
1235 except ValueError as e:
1236 return e
1237 return None
1238
1239
1240def _GetIDLParseError(input_api, filename):
1241 try:
1242 contents = input_api.ReadFile(filename)
1243 idl_schema = input_api.os_path.join(
1244 input_api.PresubmitLocalPath(),
1245 'tools', 'json_schema_compiler', 'idl_schema.py')
1246 process = input_api.subprocess.Popen(
1247 [input_api.python_executable, idl_schema],
1248 stdin=input_api.subprocess.PIPE,
1249 stdout=input_api.subprocess.PIPE,
1250 stderr=input_api.subprocess.PIPE,
1251 universal_newlines=True)
1252 (_, error) = process.communicate(input=contents)
1253 return error or None
1254 except ValueError as e:
1255 return e
1256
1257
1258def _CheckParseErrors(input_api, output_api):
1259 """Check that IDL and JSON files do not contain syntax errors."""
1260 actions = {
1261 '.idl': _GetIDLParseError,
1262 '.json': _GetJSONParseError,
1263 }
1264 # These paths contain test data and other known invalid JSON files.
1265 excluded_patterns = [
joaodasilva718f87672014-08-30 09:25:491266 r'test[\\\/]data[\\\/]',
1267 r'^components[\\\/]policy[\\\/]resources[\\\/]policy_templates\.json$',
[email protected]99171a92014-06-03 08:44:471268 ]
1269 # Most JSON files are preprocessed and support comments, but these do not.
1270 json_no_comments_patterns = [
joaodasilva718f87672014-08-30 09:25:491271 r'^testing[\\\/]',
[email protected]99171a92014-06-03 08:44:471272 ]
1273 # Only run IDL checker on files in these directories.
1274 idl_included_patterns = [
joaodasilva718f87672014-08-30 09:25:491275 r'^chrome[\\\/]common[\\\/]extensions[\\\/]api[\\\/]',
1276 r'^extensions[\\\/]common[\\\/]api[\\\/]',
[email protected]99171a92014-06-03 08:44:471277 ]
1278
1279 def get_action(affected_file):
1280 filename = affected_file.LocalPath()
1281 return actions.get(input_api.os_path.splitext(filename)[1])
1282
1283 def MatchesFile(patterns, path):
1284 for pattern in patterns:
1285 if input_api.re.search(pattern, path):
1286 return True
1287 return False
1288
1289 def FilterFile(affected_file):
1290 action = get_action(affected_file)
1291 if not action:
1292 return False
1293 path = affected_file.LocalPath()
1294
1295 if MatchesFile(excluded_patterns, path):
1296 return False
1297
1298 if (action == _GetIDLParseError and
1299 not MatchesFile(idl_included_patterns, path)):
1300 return False
1301 return True
1302
1303 results = []
1304 for affected_file in input_api.AffectedFiles(
1305 file_filter=FilterFile, include_deletes=False):
1306 action = get_action(affected_file)
1307 kwargs = {}
1308 if (action == _GetJSONParseError and
1309 MatchesFile(json_no_comments_patterns, affected_file.LocalPath())):
1310 kwargs['eat_comments'] = False
1311 parse_error = action(input_api,
1312 affected_file.AbsoluteLocalPath(),
1313 **kwargs)
1314 if parse_error:
1315 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
1316 (affected_file.LocalPath(), parse_error)))
1317 return results
1318
1319
[email protected]760deea2013-12-10 19:33:491320def _CheckJavaStyle(input_api, output_api):
1321 """Runs checkstyle on changed java files and returns errors if any exist."""
mohan.reddyf21db962014-10-16 12:26:471322 import sys
[email protected]760deea2013-12-10 19:33:491323 original_sys_path = sys.path
1324 try:
1325 sys.path = sys.path + [input_api.os_path.join(
1326 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
1327 import checkstyle
1328 finally:
1329 # Restore sys.path to what it was before.
1330 sys.path = original_sys_path
1331
1332 return checkstyle.RunCheckstyle(
davileen72d76532015-01-20 22:30:091333 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml',
newtd8b7d30e92015-01-23 18:10:511334 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]760deea2013-12-10 19:33:491335
1336
dskiba88634f4e2015-08-14 23:03:291337def _CheckAndroidToastUsage(input_api, output_api):
1338 """Checks that code uses org.chromium.ui.widget.Toast instead of
1339 android.widget.Toast (Chromium Toast doesn't force hardware
1340 acceleration on low-end devices, saving memory).
1341 """
1342 toast_import_pattern = input_api.re.compile(
1343 r'^import android\.widget\.Toast;$')
1344
1345 errors = []
1346
1347 sources = lambda affected_file: input_api.FilterSourceFile(
1348 affected_file,
1349 black_list=(_EXCLUDED_PATHS +
1350 _TEST_CODE_EXCLUDED_PATHS +
1351 input_api.DEFAULT_BLACK_LIST +
1352 (r'^chromecast[\\\/].*',
1353 r'^remoting[\\\/].*')),
1354 white_list=(r'.*\.java$',))
1355
1356 for f in input_api.AffectedSourceFiles(sources):
1357 for line_num, line in f.ChangedContents():
1358 if toast_import_pattern.search(line):
1359 errors.append("%s:%d" % (f.LocalPath(), line_num))
1360
1361 results = []
1362
1363 if errors:
1364 results.append(output_api.PresubmitError(
1365 'android.widget.Toast usage is detected. Android toasts use hardware'
1366 ' acceleration, and can be\ncostly on low-end devices. Please use'
1367 ' org.chromium.ui.widget.Toast instead.\n'
1368 'Contact [email protected] if you have any questions.',
1369 errors))
1370
1371 return results
1372
1373
dgnaa68d5e2015-06-10 10:08:221374def _CheckAndroidCrLogUsage(input_api, output_api):
1375 """Checks that new logs using org.chromium.base.Log:
1376 - Are using 'TAG' as variable name for the tags (warn)
dgn38736db2015-09-18 19:20:511377 - Are using a tag that is shorter than 20 characters (error)
dgnaa68d5e2015-06-10 10:08:221378 """
1379 cr_log_import_pattern = input_api.re.compile(
dgn87d9fb62015-06-12 09:15:121380 r'^import org\.chromium\.base\.Log;$', input_api.re.MULTILINE)
1381 class_in_base_pattern = input_api.re.compile(
1382 r'^package org\.chromium\.base;$', input_api.re.MULTILINE)
1383 has_some_log_import_pattern = input_api.re.compile(
1384 r'^import .*\.Log;$', input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221385 # Extract the tag from lines like `Log.d(TAG, "*");` or `Log.d("TAG", "*");`
dgn87d9fb62015-06-12 09:15:121386 log_call_pattern = input_api.re.compile(r'^\s*Log\.\w\((?P<tag>\"?\w+\"?)\,')
dgnaa68d5e2015-06-10 10:08:221387 log_decl_pattern = input_api.re.compile(
dgn38736db2015-09-18 19:20:511388 r'^\s*private static final String TAG = "(?P<name>(.*))";',
dgnaa68d5e2015-06-10 10:08:221389 input_api.re.MULTILINE)
dgnaa68d5e2015-06-10 10:08:221390
Vincent Scheib16d7b272015-09-15 18:09:071391 REF_MSG = ('See docs/android_logging.md '
dgnaa68d5e2015-06-10 10:08:221392 'or contact [email protected] for more info.')
1393 sources = lambda x: input_api.FilterSourceFile(x, white_list=(r'.*\.java$',))
dgn87d9fb62015-06-12 09:15:121394
dgnaa68d5e2015-06-10 10:08:221395 tag_decl_errors = []
1396 tag_length_errors = []
dgn87d9fb62015-06-12 09:15:121397 tag_errors = []
dgn38736db2015-09-18 19:20:511398 tag_with_dot_errors = []
dgn87d9fb62015-06-12 09:15:121399 util_log_errors = []
dgnaa68d5e2015-06-10 10:08:221400
1401 for f in input_api.AffectedSourceFiles(sources):
1402 file_content = input_api.ReadFile(f)
1403 has_modified_logs = False
1404
1405 # Per line checks
dgn87d9fb62015-06-12 09:15:121406 if (cr_log_import_pattern.search(file_content) or
1407 (class_in_base_pattern.search(file_content) and
1408 not has_some_log_import_pattern.search(file_content))):
1409 # Checks to run for files using cr log
dgnaa68d5e2015-06-10 10:08:221410 for line_num, line in f.ChangedContents():
1411
1412 # Check if the new line is doing some logging
dgn87d9fb62015-06-12 09:15:121413 match = log_call_pattern.search(line)
dgnaa68d5e2015-06-10 10:08:221414 if match:
1415 has_modified_logs = True
1416
1417 # Make sure it uses "TAG"
1418 if not match.group('tag') == 'TAG':
1419 tag_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgn87d9fb62015-06-12 09:15:121420 else:
1421 # Report non cr Log function calls in changed lines
1422 for line_num, line in f.ChangedContents():
1423 if log_call_pattern.search(line):
1424 util_log_errors.append("%s:%d" % (f.LocalPath(), line_num))
dgnaa68d5e2015-06-10 10:08:221425
1426 # Per file checks
1427 if has_modified_logs:
1428 # Make sure the tag is using the "cr" prefix and is not too long
1429 match = log_decl_pattern.search(file_content)
dgn38736db2015-09-18 19:20:511430 tag_name = match.group('name') if match else None
1431 if not tag_name:
dgnaa68d5e2015-06-10 10:08:221432 tag_decl_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511433 elif len(tag_name) > 20:
dgnaa68d5e2015-06-10 10:08:221434 tag_length_errors.append(f.LocalPath())
dgn38736db2015-09-18 19:20:511435 elif '.' in tag_name:
1436 tag_with_dot_errors.append(f.LocalPath())
dgnaa68d5e2015-06-10 10:08:221437
1438 results = []
1439 if tag_decl_errors:
1440 results.append(output_api.PresubmitPromptWarning(
1441 'Please define your tags using the suggested format: .\n'
dgn38736db2015-09-18 19:20:511442 '"private static final String TAG = "<package tag>".\n'
1443 'They will be prepended with "cr_" automatically.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221444 tag_decl_errors))
1445
1446 if tag_length_errors:
1447 results.append(output_api.PresubmitError(
1448 'The tag length is restricted by the system to be at most '
dgn38736db2015-09-18 19:20:511449 '20 characters.\n' + REF_MSG,
dgnaa68d5e2015-06-10 10:08:221450 tag_length_errors))
1451
1452 if tag_errors:
1453 results.append(output_api.PresubmitPromptWarning(
1454 'Please use a variable named "TAG" for your log tags.\n' + REF_MSG,
1455 tag_errors))
1456
dgn87d9fb62015-06-12 09:15:121457 if util_log_errors:
dgn4401aa52015-04-29 16:26:171458 results.append(output_api.PresubmitPromptWarning(
dgn87d9fb62015-06-12 09:15:121459 'Please use org.chromium.base.Log for new logs.\n' + REF_MSG,
1460 util_log_errors))
1461
dgn38736db2015-09-18 19:20:511462 if tag_with_dot_errors:
1463 results.append(output_api.PresubmitPromptWarning(
1464 'Dot in log tags cause them to be elided in crash reports.\n' + REF_MSG,
1465 tag_with_dot_errors))
1466
dgn4401aa52015-04-29 16:26:171467 return results
1468
1469
agrieve7b6479d82015-10-07 14:24:221470def _CheckAndroidNewMdpiAssetLocation(input_api, output_api):
1471 """Checks if MDPI assets are placed in a correct directory."""
1472 file_filter = lambda f: (f.LocalPath().endswith('.png') and
1473 ('/res/drawable/' in f.LocalPath() or
1474 '/res/drawable-ldrtl/' in f.LocalPath()))
1475 errors = []
1476 for f in input_api.AffectedFiles(include_deletes=False,
1477 file_filter=file_filter):
1478 errors.append(' %s' % f.LocalPath())
1479
1480 results = []
1481 if errors:
1482 results.append(output_api.PresubmitError(
1483 'MDPI assets should be placed in /res/drawable-mdpi/ or '
1484 '/res/drawable-ldrtl-mdpi/\ninstead of /res/drawable/ and'
1485 '/res/drawable-ldrtl/.\n'
1486 'Contact [email protected] if you have questions.', errors))
1487 return results
1488
1489
mnaganov9b9b1fe82014-12-11 16:30:361490def _CheckForCopyrightedCode(input_api, output_api):
1491 """Verifies that newly added code doesn't contain copyrighted material
1492 and is properly licensed under the standard Chromium license.
1493
1494 As there can be false positives, we maintain a whitelist file. This check
1495 also verifies that the whitelist file is up to date.
1496 """
1497 import sys
1498 original_sys_path = sys.path
1499 try:
1500 sys.path = sys.path + [input_api.os_path.join(
mnaganovf771be4a2015-06-12 18:13:221501 input_api.PresubmitLocalPath(), 'tools')]
1502 from copyright_scanner import copyright_scanner
mnaganov9b9b1fe82014-12-11 16:30:361503 finally:
1504 # Restore sys.path to what it was before.
1505 sys.path = original_sys_path
1506
1507 return copyright_scanner.ScanAtPresubmit(input_api, output_api)
1508
1509
glidere61efad2015-02-18 17:39:431510def _CheckSingletonInHeaders(input_api, output_api):
1511 """Checks to make sure no header files have |Singleton<|."""
1512 def FileFilter(affected_file):
1513 # It's ok for base/memory/singleton.h to have |Singleton<|.
1514 black_list = (_EXCLUDED_PATHS +
1515 input_api.DEFAULT_BLACK_LIST +
1516 (r"^base[\\\/]memory[\\\/]singleton\.h$",))
1517 return input_api.FilterSourceFile(affected_file, black_list=black_list)
1518
sergeyu34d21222015-09-16 00:11:441519 pattern = input_api.re.compile(r'(?<!class\sbase::)Singleton\s*<')
glidere61efad2015-02-18 17:39:431520 files = []
1521 for f in input_api.AffectedSourceFiles(FileFilter):
1522 if (f.LocalPath().endswith('.h') or f.LocalPath().endswith('.hxx') or
1523 f.LocalPath().endswith('.hpp') or f.LocalPath().endswith('.inl')):
1524 contents = input_api.ReadFile(f)
1525 for line in contents.splitlines(False):
oysteinec430ad42015-10-22 20:55:241526 if (not line.lstrip().startswith('//') and # Strip C++ comment.
glidere61efad2015-02-18 17:39:431527 pattern.search(line)):
1528 files.append(f)
1529 break
1530
1531 if files:
1532 return [ output_api.PresubmitError(
sergeyu34d21222015-09-16 00:11:441533 'Found base::Singleton<T> in the following header files.\n' +
glidere61efad2015-02-18 17:39:431534 'Please move them to an appropriate source file so that the ' +
1535 'template gets instantiated in a single compilation unit.',
1536 files) ]
1537 return []
1538
1539
dbeam3aa38392015-10-16 21:38:031540def _CheckBaseMacrosInHeaders(input_api, output_api):
1541 """Check for base/macros.h if DISALLOW_* macro is used."""
1542
1543 disallows = ('DISALLOW_ASSIGN', 'DISALLOW_COPY', 'DISALLOW_EVIL')
1544 macros = '#include "base/macros.h"'
1545 basictypes = '#include "base/basictypes.h"'
1546
1547 files = []
1548 for f in input_api.AffectedSourceFiles(None):
1549 if not f.LocalPath().endswith('.h'):
1550 continue
1551 for line_num, line in f.ChangedContents():
oysteinec430ad42015-10-22 20:55:241552 if line.lstrip().startswith('//'): # Strip C++ comment.
1553 continue
dbeam3aa38392015-10-16 21:38:031554 if any(d in line for d in disallows):
1555 contents = input_api.ReadFile(f)
1556 if not (macros in contents or basictypes in contents):
1557 files.append(f)
1558 break
1559
1560 msg = ('The following files appear to be using DISALLOW_* macros.\n'
1561 'Please #include "base/macros.h" in them.')
1562 return [output_api.PresubmitError(msg, files)] if files else []
1563
1564
[email protected]fd20b902014-05-09 02:14:531565_DEPRECATED_CSS = [
1566 # Values
1567 ( "-webkit-box", "flex" ),
1568 ( "-webkit-inline-box", "inline-flex" ),
1569 ( "-webkit-flex", "flex" ),
1570 ( "-webkit-inline-flex", "inline-flex" ),
1571 ( "-webkit-min-content", "min-content" ),
1572 ( "-webkit-max-content", "max-content" ),
1573
1574 # Properties
1575 ( "-webkit-background-clip", "background-clip" ),
1576 ( "-webkit-background-origin", "background-origin" ),
1577 ( "-webkit-background-size", "background-size" ),
1578 ( "-webkit-box-shadow", "box-shadow" ),
1579
1580 # Functions
1581 ( "-webkit-gradient", "gradient" ),
1582 ( "-webkit-repeating-gradient", "repeating-gradient" ),
1583 ( "-webkit-linear-gradient", "linear-gradient" ),
1584 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
1585 ( "-webkit-radial-gradient", "radial-gradient" ),
1586 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
1587]
1588
1589def _CheckNoDeprecatedCSS(input_api, output_api):
1590 """ Make sure that we don't use deprecated CSS
[email protected]9a48e3f82014-05-22 00:06:251591 properties, functions or values. Our external
mdjonesae0286c32015-06-10 18:10:341592 documentation and iOS CSS for dom distiller
1593 (reader mode) are ignored by the hooks as it
[email protected]9a48e3f82014-05-22 00:06:251594 needs to be consumed by WebKit. """
[email protected]fd20b902014-05-09 02:14:531595 results = []
dbeam070cfe62014-10-22 06:44:021596 file_inclusion_pattern = (r".+\.css$",)
[email protected]9a48e3f82014-05-22 00:06:251597 black_list = (_EXCLUDED_PATHS +
1598 _TEST_CODE_EXCLUDED_PATHS +
1599 input_api.DEFAULT_BLACK_LIST +
1600 (r"^chrome/common/extensions/docs",
1601 r"^chrome/docs",
mdjonesae0286c32015-06-10 18:10:341602 r"^components/dom_distiller/core/css/distilledpage_ios.css",
[email protected]9a48e3f82014-05-22 00:06:251603 r"^native_client_sdk"))
1604 file_filter = lambda f: input_api.FilterSourceFile(
1605 f, white_list=file_inclusion_pattern, black_list=black_list)
[email protected]fd20b902014-05-09 02:14:531606 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1607 for line_num, line in fpath.ChangedContents():
1608 for (deprecated_value, value) in _DEPRECATED_CSS:
dbeam070cfe62014-10-22 06:44:021609 if deprecated_value in line:
[email protected]fd20b902014-05-09 02:14:531610 results.append(output_api.PresubmitError(
1611 "%s:%d: Use of deprecated CSS %s, use %s instead" %
1612 (fpath.LocalPath(), line_num, deprecated_value, value)))
1613 return results
1614
mohan.reddyf21db962014-10-16 12:26:471615
dbeam070cfe62014-10-22 06:44:021616_DEPRECATED_JS = [
1617 ( "__lookupGetter__", "Object.getOwnPropertyDescriptor" ),
1618 ( "__defineGetter__", "Object.defineProperty" ),
1619 ( "__defineSetter__", "Object.defineProperty" ),
1620]
1621
1622def _CheckNoDeprecatedJS(input_api, output_api):
1623 """Make sure that we don't use deprecated JS in Chrome code."""
1624 results = []
1625 file_inclusion_pattern = (r".+\.js$",) # TODO(dbeam): .html?
1626 black_list = (_EXCLUDED_PATHS + _TEST_CODE_EXCLUDED_PATHS +
1627 input_api.DEFAULT_BLACK_LIST)
1628 file_filter = lambda f: input_api.FilterSourceFile(
1629 f, white_list=file_inclusion_pattern, black_list=black_list)
1630 for fpath in input_api.AffectedFiles(file_filter=file_filter):
1631 for lnum, line in fpath.ChangedContents():
1632 for (deprecated, replacement) in _DEPRECATED_JS:
1633 if deprecated in line:
1634 results.append(output_api.PresubmitError(
1635 "%s:%d: Use of deprecated JS %s, use %s instead" %
1636 (fpath.LocalPath(), lnum, deprecated, replacement)))
1637 return results
1638
1639
dgnaa68d5e2015-06-10 10:08:221640def _AndroidSpecificOnUploadChecks(input_api, output_api):
1641 """Groups checks that target android code."""
1642 results = []
dgnaa68d5e2015-06-10 10:08:221643 results.extend(_CheckAndroidCrLogUsage(input_api, output_api))
agrieve7b6479d82015-10-07 14:24:221644 results.extend(_CheckAndroidNewMdpiAssetLocation(input_api, output_api))
dskiba88634f4e2015-08-14 23:03:291645 results.extend(_CheckAndroidToastUsage(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221646 return results
1647
1648
[email protected]22c9bd72011-03-27 16:47:391649def _CommonChecks(input_api, output_api):
1650 """Checks common to both upload and commit."""
1651 results = []
1652 results.extend(input_api.canned_checks.PanProjectChecks(
[email protected]3de922f2013-12-20 13:27:381653 input_api, output_api,
1654 excluded_paths=_EXCLUDED_PATHS + _TESTRUNNER_PATHS))
[email protected]66daa702011-05-28 14:41:461655 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:191656 results.extend(
[email protected]760deea2013-12-10 19:33:491657 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:541658 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:181659 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
danakj61c1aa22015-10-26 19:55:521660 results.extend(_CheckDCHECK_IS_ONHasBraces(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:221661 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:441662 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:591663 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:061664 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:121665 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:181666 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:221667 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:491668 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:271669 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:031670 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:491671 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:441672 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:271673 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:541674 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
lliabraa35bab3932014-10-01 12:16:441675 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
danakj3c84d0c2014-10-06 15:35:461676 # TODO(danakj): Remove this when base/move.h is removed.
1677 results.extend(_CheckForUsingSideEffectsOfPass(input_api, output_api))
[email protected]e871964c2013-05-13 14:14:551678 results.extend(_CheckAddedDepsHaveTargetApprovals(input_api, output_api))
[email protected]9f919cc2013-07-31 03:04:041679 results.extend(
1680 input_api.canned_checks.CheckChangeHasNoTabs(
1681 input_api,
1682 output_api,
1683 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
[email protected]85218562013-11-22 07:41:401684 results.extend(_CheckSpamLogging(input_api, output_api))
[email protected]49aa76a2013-12-04 06:59:161685 results.extend(_CheckForAnonymousVariables(input_api, output_api))
[email protected]5fe0f8742013-11-29 01:04:591686 results.extend(_CheckCygwinShell(input_api, output_api))
[email protected]999261d2014-03-03 20:08:081687 results.extend(_CheckUserActionUpdate(input_api, output_api))
[email protected]fd20b902014-05-09 02:14:531688 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
dbeam070cfe62014-10-22 06:44:021689 results.extend(_CheckNoDeprecatedJS(input_api, output_api))
[email protected]99171a92014-06-03 08:44:471690 results.extend(_CheckParseErrors(input_api, output_api))
mlamouria82272622014-09-16 18:45:041691 results.extend(_CheckForIPCRules(input_api, output_api))
mnaganov9b9b1fe82014-12-11 16:30:361692 results.extend(_CheckForCopyrightedCode(input_api, output_api))
mostynbb639aca52015-01-07 20:31:231693 results.extend(_CheckForWindowsLineEndings(input_api, output_api))
glidere61efad2015-02-18 17:39:431694 results.extend(_CheckSingletonInHeaders(input_api, output_api))
dbeam3aa38392015-10-16 21:38:031695 results.extend(_CheckBaseMacrosInHeaders(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:241696
1697 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
1698 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
1699 input_api, output_api,
1700 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:381701 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:391702 return results
[email protected]1f7b4172010-01-28 01:17:341703
[email protected]b337cb5b2011-01-23 21:24:051704
[email protected]66daa702011-05-28 14:41:461705def _CheckAuthorizedAuthor(input_api, output_api):
1706 """For non-googler/chromites committers, verify the author's email address is
1707 in AUTHORS.
1708 """
[email protected]9bb9cb82011-06-13 20:43:011709 # TODO(maruel): Add it to input_api?
1710 import fnmatch
1711
[email protected]66daa702011-05-28 14:41:461712 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:011713 if not author:
1714 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:461715 return []
[email protected]c99663292011-05-31 19:46:081716 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:461717 input_api.PresubmitLocalPath(), 'AUTHORS')
1718 valid_authors = (
1719 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
1720 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:181721 valid_authors = [item.group(1).lower() for item in valid_authors if item]
[email protected]d8b50be2011-06-15 14:19:441722 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:231723 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:461724 return [output_api.PresubmitPromptWarning(
1725 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
1726 '\n'
1727 'http://www.chromium.org/developers/contributing-code and read the '
1728 '"Legal" section\n'
1729 'If you are a chromite, verify the contributor signed the CLA.') %
1730 author)]
1731 return []
1732
1733
[email protected]b8079ae4a2012-12-05 19:56:491734def _CheckPatchFiles(input_api, output_api):
1735 problems = [f.LocalPath() for f in input_api.AffectedFiles()
1736 if f.LocalPath().endswith(('.orig', '.rej'))]
1737 if problems:
1738 return [output_api.PresubmitError(
1739 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:031740 else:
1741 return []
[email protected]b8079ae4a2012-12-05 19:56:491742
1743
[email protected]b00342e7f2013-03-26 16:21:541744def _DidYouMeanOSMacro(bad_macro):
1745 try:
1746 return {'A': 'OS_ANDROID',
1747 'B': 'OS_BSD',
1748 'C': 'OS_CHROMEOS',
1749 'F': 'OS_FREEBSD',
1750 'L': 'OS_LINUX',
1751 'M': 'OS_MACOSX',
1752 'N': 'OS_NACL',
1753 'O': 'OS_OPENBSD',
1754 'P': 'OS_POSIX',
1755 'S': 'OS_SOLARIS',
1756 'W': 'OS_WIN'}[bad_macro[3].upper()]
1757 except KeyError:
1758 return ''
1759
1760
1761def _CheckForInvalidOSMacrosInFile(input_api, f):
1762 """Check for sensible looking, totally invalid OS macros."""
1763 preprocessor_statement = input_api.re.compile(r'^\s*#')
1764 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
1765 results = []
1766 for lnum, line in f.ChangedContents():
1767 if preprocessor_statement.search(line):
1768 for match in os_macro.finditer(line):
1769 if not match.group(1) in _VALID_OS_MACROS:
1770 good = _DidYouMeanOSMacro(match.group(1))
1771 did_you_mean = ' (did you mean %s?)' % good if good else ''
1772 results.append(' %s:%d %s%s' % (f.LocalPath(),
1773 lnum,
1774 match.group(1),
1775 did_you_mean))
1776 return results
1777
1778
1779def _CheckForInvalidOSMacros(input_api, output_api):
1780 """Check all affected files for invalid OS macros."""
1781 bad_macros = []
1782 for f in input_api.AffectedFiles():
1783 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css')):
1784 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
1785
1786 if not bad_macros:
1787 return []
1788
1789 return [output_api.PresubmitError(
1790 'Possibly invalid OS macro[s] found. Please fix your code\n'
1791 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
1792
lliabraa35bab3932014-10-01 12:16:441793
1794def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
1795 """Check all affected files for invalid "if defined" macros."""
1796 ALWAYS_DEFINED_MACROS = (
1797 "TARGET_CPU_PPC",
1798 "TARGET_CPU_PPC64",
1799 "TARGET_CPU_68K",
1800 "TARGET_CPU_X86",
1801 "TARGET_CPU_ARM",
1802 "TARGET_CPU_MIPS",
1803 "TARGET_CPU_SPARC",
1804 "TARGET_CPU_ALPHA",
1805 "TARGET_IPHONE_SIMULATOR",
1806 "TARGET_OS_EMBEDDED",
1807 "TARGET_OS_IPHONE",
1808 "TARGET_OS_MAC",
1809 "TARGET_OS_UNIX",
1810 "TARGET_OS_WIN32",
1811 )
1812 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
1813 results = []
1814 for lnum, line in f.ChangedContents():
1815 for match in ifdef_macro.finditer(line):
1816 if match.group(1) in ALWAYS_DEFINED_MACROS:
1817 always_defined = ' %s is always defined. ' % match.group(1)
1818 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
1819 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
1820 lnum,
1821 always_defined,
1822 did_you_mean))
1823 return results
1824
1825
1826def _CheckForInvalidIfDefinedMacros(input_api, output_api):
1827 """Check all affected files for invalid "if defined" macros."""
1828 bad_macros = []
1829 for f in input_api.AffectedFiles():
1830 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1831 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
1832
1833 if not bad_macros:
1834 return []
1835
1836 return [output_api.PresubmitError(
1837 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
1838 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
1839 bad_macros)]
1840
1841
danakj3c84d0c2014-10-06 15:35:461842def _CheckForUsingSideEffectsOfPass(input_api, output_api):
1843 """Check all affected files for using side effects of Pass."""
1844 errors = []
1845 for f in input_api.AffectedFiles():
1846 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1847 for lnum, line in f.ChangedContents():
1848 # Disallow Foo(*my_scoped_thing.Pass()); See crbug.com/418297.
mohan.reddyf21db962014-10-16 12:26:471849 if input_api.re.search(r'\*[a-zA-Z0-9_]+\.Pass\(\)', line):
danakj3c84d0c2014-10-06 15:35:461850 errors.append(output_api.PresubmitError(
1851 ('%s:%d uses *foo.Pass() to delete the contents of scoped_ptr. ' +
1852 'See crbug.com/418297.') % (f.LocalPath(), lnum)))
1853 return errors
1854
1855
mlamouria82272622014-09-16 18:45:041856def _CheckForIPCRules(input_api, output_api):
1857 """Check for same IPC rules described in
1858 http://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
1859 """
1860 base_pattern = r'IPC_ENUM_TRAITS\('
1861 inclusion_pattern = input_api.re.compile(r'(%s)' % base_pattern)
1862 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_pattern)
1863
1864 problems = []
1865 for f in input_api.AffectedSourceFiles(None):
1866 local_path = f.LocalPath()
1867 if not local_path.endswith('.h'):
1868 continue
1869 for line_number, line in f.ChangedContents():
1870 if inclusion_pattern.search(line) and not comment_pattern.search(line):
1871 problems.append(
1872 '%s:%d\n %s' % (local_path, line_number, line.strip()))
1873
1874 if problems:
1875 return [output_api.PresubmitPromptWarning(
1876 _IPC_ENUM_TRAITS_DEPRECATED, problems)]
1877 else:
1878 return []
1879
[email protected]b00342e7f2013-03-26 16:21:541880
mostynbb639aca52015-01-07 20:31:231881def _CheckForWindowsLineEndings(input_api, output_api):
1882 """Check source code and known ascii text files for Windows style line
1883 endings.
1884 """
earthdok1b5e0ee2015-03-10 15:19:101885 known_text_files = r'.*\.(txt|html|htm|mhtml|py|gyp|gypi|gn|isolate)$'
mostynbb639aca52015-01-07 20:31:231886
1887 file_inclusion_pattern = (
1888 known_text_files,
1889 r'.+%s' % _IMPLEMENTATION_EXTENSIONS
1890 )
1891
1892 filter = lambda f: input_api.FilterSourceFile(
1893 f, white_list=file_inclusion_pattern, black_list=None)
1894 files = [f.LocalPath() for f in
1895 input_api.AffectedSourceFiles(filter)]
1896
1897 problems = []
1898
1899 for file in files:
1900 fp = open(file, 'r')
1901 for line in fp:
1902 if line.endswith('\r\n'):
1903 problems.append(file)
1904 break
1905 fp.close()
1906
1907 if problems:
1908 return [output_api.PresubmitPromptWarning('Are you sure that you want '
1909 'these files to contain Windows style line endings?\n' +
1910 '\n'.join(problems))]
1911
1912 return []
1913
1914
[email protected]1f7b4172010-01-28 01:17:341915def CheckChangeOnUpload(input_api, output_api):
1916 results = []
1917 results.extend(_CommonChecks(input_api, output_api))
tandriief664692014-09-23 14:51:471918 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
aurimas8d3bc1c52014-10-15 01:02:171919 results.extend(_CheckJavaStyle(input_api, output_api))
scottmg39b29952014-12-08 18:31:281920 results.extend(
1921 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
mcasasb7440c282015-02-04 14:52:191922 results.extend(_CheckUmaHistogramChanges(input_api, output_api))
dgnaa68d5e2015-06-10 10:08:221923 results.extend(_AndroidSpecificOnUploadChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541924 return results
[email protected]ca8d19842009-02-19 16:33:121925
1926
[email protected]1bfb8322014-04-23 01:02:411927def GetTryServerMasterForBot(bot):
1928 """Returns the Try Server master for the given bot.
1929
[email protected]0bb112362014-07-26 04:38:321930 It tries to guess the master from the bot name, but may still fail
1931 and return None. There is no longer a default master.
1932 """
1933 # Potentially ambiguous bot names are listed explicitly.
1934 master_map = {
[email protected]0bb112362014-07-26 04:38:321935 'chromium_presubmit': 'tryserver.chromium.linux',
1936 'blink_presubmit': 'tryserver.chromium.linux',
1937 'tools_build_presubmit': 'tryserver.chromium.linux',
[email protected]1bfb8322014-04-23 01:02:411938 }
[email protected]0bb112362014-07-26 04:38:321939 master = master_map.get(bot)
1940 if not master:
sergiyb37fd293f2015-02-26 06:55:011941 if 'linux' in bot or 'android' in bot or 'presubmit' in bot:
[email protected]0bb112362014-07-26 04:38:321942 master = 'tryserver.chromium.linux'
1943 elif 'win' in bot:
1944 master = 'tryserver.chromium.win'
1945 elif 'mac' in bot or 'ios' in bot:
1946 master = 'tryserver.chromium.mac'
1947 return master
[email protected]1bfb8322014-04-23 01:02:411948
1949
Paweł Hajdan, Jr55083782014-12-19 20:32:561950def GetDefaultTryConfigs(bots):
1951 """Returns a list of ('bot', set(['tests']), filtered by [bots].
[email protected]38c6a512013-12-18 23:48:011952 """
1953
Paweł Hajdan, Jr55083782014-12-19 20:32:561954 builders_and_tests = dict((bot, set(['defaulttests'])) for bot in bots)
[email protected]1bfb8322014-04-23 01:02:411955
1956 # Build up the mapping from tryserver master to bot/test.
1957 out = dict()
Paweł Hajdan, Jr55083782014-12-19 20:32:561958 for bot, tests in builders_and_tests.iteritems():
[email protected]1bfb8322014-04-23 01:02:411959 out.setdefault(GetTryServerMasterForBot(bot), {})[bot] = tests
1960 return out
[email protected]38c6a512013-12-18 23:48:011961
1962
[email protected]ca8d19842009-02-19 16:33:121963def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:541964 results = []
[email protected]1f7b4172010-01-28 01:17:341965 results.extend(_CommonChecks(input_api, output_api))
[email protected]dd805fe2009-10-01 08:11:511966 # TODO(thestig) temporarily disabled, doesn't work in third_party/
1967 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
1968 # input_api, output_api, sources))
[email protected]fe5f57c52009-06-05 14:25:541969 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:271970 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:341971 input_api,
1972 output_api,
[email protected]2fdd1f362013-01-16 03:56:031973 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:271974
[email protected]3e4eb112011-01-18 03:29:541975 results.extend(input_api.canned_checks.CheckChangeHasBugField(
1976 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:411977 results.extend(input_api.canned_checks.CheckChangeHasDescription(
1978 input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:541979 return results
[email protected]ca8d19842009-02-19 16:33:121980
1981
[email protected]7468ac522014-03-12 23:35:571982def GetPreferredTryMasters(project, change):
Paweł Hajdan, Jref2afd42015-01-07 15:59:521983 import json
sergiyb57a71e32015-06-03 18:44:001984 import os.path
1985 import platform
1986 import subprocess
smut3ef206e12015-03-20 09:30:001987
sergiyb57a71e32015-06-03 18:44:001988 cq_config_path = os.path.join(
1989 change.RepositoryRoot(), 'infra', 'config', 'cq.cfg')
1990 # commit_queue.py below is a script in depot_tools directory, which has a
1991 # 'builders' command to retrieve a list of CQ builders from the CQ config.
1992 is_win = platform.system() == 'Windows'
1993 masters = json.loads(subprocess.check_output(
1994 ['commit_queue', 'builders', cq_config_path], shell=is_win))
[email protected]911753b2012-08-02 12:11:541995
sergiyb6092f742015-06-16 09:00:521996 try_config = {}
1997 for master in masters:
1998 try_config.setdefault(master, {})
1999 for builder in masters[master]:
sergiyb57a71e32015-06-03 18:44:002000 # Do not trigger presubmit builders, since they're likely to fail
2001 # (e.g. OWNERS checks before finished code review), and we're
2002 # running local presubmit anyway.
sergiyb6092f742015-06-16 09:00:522003 if 'presubmit' not in builder:
2004 try_config[master][builder] = ['defaulttests']
Paweł Hajdan, Jr4026dbc2015-01-14 09:22:322005
sergiyb6092f742015-06-16 09:00:522006 return try_config