blob: c593b16479cb0f875f1a0b6b435c9f36a4c64cbf [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
[email protected]50d7d721e2009-11-15 17:56:188for more details about the presubmit API built into gcl.
[email protected]ca8d19842009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]9d16ad12011-12-14 20:49:4712import re
[email protected]fbcafe5a2012-08-08 15:31:2213import subprocess
[email protected]55f9f382012-07-31 11:02:1814import sys
[email protected]9d16ad12011-12-14 20:49:4715
16
[email protected]379e7dd2010-01-28 17:39:2117_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5418 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0019 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
20 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]8886ffcb2013-02-12 04:56:2821 r"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
[email protected]a18130a2012-01-03 17:52:0822 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5423 r"^skia[\\\/].*",
24 r"^v8[\\\/].*",
25 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5326 r".+_autogen\.h$",
[email protected]ce145c02012-09-06 09:49:3427 r".+[\\\/]pnacl_shim\.c$",
[email protected]4306417642009-06-11 00:33:4028)
[email protected]ca8d19842009-02-19 16:33:1229
[email protected]06e6d0ff2012-12-11 01:36:4430# Fragment of a regular expression that matches file name suffixes
31# used to indicate different platforms.
32_PLATFORM_SPECIFIERS = r'(_(android|chromeos|gtk|mac|posix|win))?'
33
34# Fragment of a regular expression that matches C++ and Objective-C++
35# implementation files.
36_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
37
38# Regular expression that matches code only used for test binaries
39# (best effort).
40_TEST_CODE_EXCLUDED_PATHS = (
41 r'.*[/\\](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
42 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
43 r'.+_(api|browser|perf|unit|ui)?test%s%s' % (_PLATFORM_SPECIFIERS,
44 _IMPLEMENTATION_EXTENSIONS),
45 r'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS,
46 r'.*[/\\](test|tool(s)?)[/\\].*',
47 # At request of folks maintaining this folder.
48 r'chrome[/\\]browser[/\\]automation[/\\].*',
49)
[email protected]ca8d19842009-02-19 16:33:1250
[email protected]eea609a2011-11-18 13:10:1251_TEST_ONLY_WARNING = (
52 'You might be calling functions intended only for testing from\n'
53 'production code. It is OK to ignore this warning if you know what\n'
54 'you are doing, as the heuristics used to detect the situation are\n'
55 'not perfect. The commit queue will not block on this warning.\n'
56 'Email [email protected] if you have questions.')
57
58
[email protected]cf9b78f2012-11-14 11:40:2859_INCLUDE_ORDER_WARNING = (
60 'Your #include order seems to be broken. Send mail to\n'
61 '[email protected] if this is not the case.')
62
63
[email protected]127f18ec2012-06-16 05:05:5964_BANNED_OBJC_FUNCTIONS = (
65 (
66 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2067 (
68 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5969 'prohibited. Please use CrTrackingArea instead.',
70 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
71 ),
72 False,
73 ),
74 (
75 'NSTrackingArea',
[email protected]23e6cbc2012-06-16 18:51:2076 (
77 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5978 'instead.',
79 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
80 ),
81 False,
82 ),
83 (
84 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2085 (
86 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5987 'Please use |convertPoint:(point) fromView:nil| instead.',
88 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
89 ),
90 True,
91 ),
92 (
93 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2094 (
95 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5996 'Please use |convertPoint:(point) toView:nil| instead.',
97 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
98 ),
99 True,
100 ),
101 (
102 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20103 (
104 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59105 'Please use |convertRect:(point) fromView:nil| instead.',
106 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
107 ),
108 True,
109 ),
110 (
111 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:20112 (
113 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59114 'Please use |convertRect:(point) toView:nil| instead.',
115 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
116 ),
117 True,
118 ),
119 (
120 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:20121 (
122 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59123 'Please use |convertSize:(point) fromView:nil| instead.',
124 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
125 ),
126 True,
127 ),
128 (
129 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20130 (
131 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59132 'Please use |convertSize:(point) toView:nil| instead.',
133 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
134 ),
135 True,
136 ),
137)
138
139
140_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20141 # Make sure that gtest's FRIEND_TEST() macro is not used; the
142 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
[email protected]e00ccc92012-11-01 17:32:30143 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
[email protected]23e6cbc2012-06-16 18:51:20144 (
145 'FRIEND_TEST(',
146 (
[email protected]e3c945502012-06-26 20:01:49147 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20148 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
149 ),
150 False,
[email protected]7345da02012-11-27 14:31:49151 (),
[email protected]23e6cbc2012-06-16 18:51:20152 ),
153 (
154 'ScopedAllowIO',
155 (
[email protected]e3c945502012-06-26 20:01:49156 'New code should not use ScopedAllowIO. Post a task to the blocking',
157 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20158 ),
[email protected]e3c945502012-06-26 20:01:49159 True,
[email protected]7345da02012-11-27 14:31:49160 (
161 r"^content[\\\/]shell[\\\/]shell_browser_main\.cc$",
[email protected]398ad132013-04-02 15:11:01162 r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
[email protected]7345da02012-11-27 14:31:49163 ),
[email protected]23e6cbc2012-06-16 18:51:20164 ),
[email protected]127f18ec2012-06-16 05:05:59165)
166
167
[email protected]b00342e7f2013-03-26 16:21:54168_VALID_OS_MACROS = (
169 # Please keep sorted.
170 'OS_ANDROID',
171 'OS_BSD',
172 'OS_CAT', # For testing.
173 'OS_CHROMEOS',
174 'OS_FREEBSD',
175 'OS_IOS',
176 'OS_LINUX',
177 'OS_MACOSX',
178 'OS_NACL',
179 'OS_OPENBSD',
180 'OS_POSIX',
181 'OS_SOLARIS',
182 'OS_SUN', # Not in build/build_config.h but in skia.
183 'OS_WIN',
184)
185
186
[email protected]55459852011-08-10 15:17:19187def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
188 """Attempts to prevent use of functions intended only for testing in
189 non-testing code. For now this is just a best-effort implementation
190 that ignores header files and may have some false positives. A
191 better implementation would probably need a proper C++ parser.
192 """
193 # We only scan .cc files and the like, as the declaration of
194 # for-testing functions in header files are hard to distinguish from
195 # calls to such functions without a proper C++ parser.
[email protected]06e6d0ff2012-12-11 01:36:44196 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
[email protected]55459852011-08-10 15:17:19197
198 base_function_pattern = r'ForTest(ing)?|for_test(ing)?'
199 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
200 exclusion_pattern = input_api.re.compile(
201 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
202 base_function_pattern, base_function_pattern))
203
204 def FilterFile(affected_file):
[email protected]06e6d0ff2012-12-11 01:36:44205 black_list = (_EXCLUDED_PATHS +
206 _TEST_CODE_EXCLUDED_PATHS +
207 input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19208 return input_api.FilterSourceFile(
209 affected_file,
210 white_list=(file_inclusion_pattern, ),
211 black_list=black_list)
212
213 problems = []
214 for f in input_api.AffectedSourceFiles(FilterFile):
215 local_path = f.LocalPath()
[email protected]2fdd1f362013-01-16 03:56:03216 lines = input_api.ReadFile(f).splitlines()
217 line_number = 0
218 for line in lines:
219 if (inclusion_pattern.search(line) and
220 not exclusion_pattern.search(line)):
[email protected]55459852011-08-10 15:17:19221 problems.append(
[email protected]2fdd1f362013-01-16 03:56:03222 '%s:%d\n %s' % (local_path, line_number, line.strip()))
223 line_number += 1
[email protected]55459852011-08-10 15:17:19224
225 if problems:
[email protected]f7051d52013-04-02 18:31:42226 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
[email protected]2fdd1f362013-01-16 03:56:03227 else:
228 return []
[email protected]55459852011-08-10 15:17:19229
230
[email protected]10689ca2011-09-02 02:31:54231def _CheckNoIOStreamInHeaders(input_api, output_api):
232 """Checks to make sure no .h files include <iostream>."""
233 files = []
234 pattern = input_api.re.compile(r'^#include\s*<iostream>',
235 input_api.re.MULTILINE)
236 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
237 if not f.LocalPath().endswith('.h'):
238 continue
239 contents = input_api.ReadFile(f)
240 if pattern.search(contents):
241 files.append(f)
242
243 if len(files):
244 return [ output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06245 'Do not #include <iostream> in header files, since it inserts static '
246 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54247 '#include <ostream>. See http://crbug.com/94794',
248 files) ]
249 return []
250
251
[email protected]72df4e782012-06-21 16:28:18252def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
253 """Checks to make sure no source files use UNIT_TEST"""
254 problems = []
255 for f in input_api.AffectedFiles():
256 if (not f.LocalPath().endswith(('.cc', '.mm'))):
257 continue
258
259 for line_num, line in f.ChangedContents():
260 if 'UNIT_TEST' in line:
261 problems.append(' %s:%d' % (f.LocalPath(), line_num))
262
263 if not problems:
264 return []
265 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
266 '\n'.join(problems))]
267
268
[email protected]8ea5d4b2011-09-13 21:49:22269def _CheckNoNewWStrings(input_api, output_api):
270 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27271 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22272 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20273 if (not f.LocalPath().endswith(('.cc', '.h')) or
274 f.LocalPath().endswith('test.cc')):
275 continue
[email protected]8ea5d4b2011-09-13 21:49:22276
[email protected]a11dbe9b2012-08-07 01:32:58277 allowWString = False
[email protected]b5c24292011-11-28 14:38:20278 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58279 if 'presubmit: allow wstring' in line:
280 allowWString = True
281 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27282 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58283 allowWString = False
284 else:
285 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22286
[email protected]55463aa62011-10-12 00:48:27287 if not problems:
288 return []
289 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58290 ' If you are calling a cross-platform API that accepts a wstring, '
291 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27292 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22293
294
[email protected]2a8ac9c2011-10-19 17:20:44295def _CheckNoDEPSGIT(input_api, output_api):
296 """Make sure .DEPS.git is never modified manually."""
297 if any(f.LocalPath().endswith('.DEPS.git') for f in
298 input_api.AffectedFiles()):
299 return [output_api.PresubmitError(
300 'Never commit changes to .DEPS.git. This file is maintained by an\n'
301 'automated system based on what\'s in DEPS and your changes will be\n'
302 'overwritten.\n'
303 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n'
304 'for more information')]
305 return []
306
307
[email protected]127f18ec2012-06-16 05:05:59308def _CheckNoBannedFunctions(input_api, output_api):
309 """Make sure that banned functions are not used."""
310 warnings = []
311 errors = []
312
313 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
314 for f in input_api.AffectedFiles(file_filter=file_filter):
315 for line_num, line in f.ChangedContents():
316 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
317 if func_name in line:
318 problems = warnings;
319 if error:
320 problems = errors;
321 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
322 for message_line in message:
323 problems.append(' %s' % message_line)
324
325 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
326 for f in input_api.AffectedFiles(file_filter=file_filter):
327 for line_num, line in f.ChangedContents():
[email protected]7345da02012-11-27 14:31:49328 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
329 def IsBlacklisted(affected_file, blacklist):
330 local_path = affected_file.LocalPath()
331 for item in blacklist:
332 if input_api.re.match(item, local_path):
333 return True
334 return False
335 if IsBlacklisted(f, excluded_paths):
336 continue
[email protected]127f18ec2012-06-16 05:05:59337 if func_name in line:
338 problems = warnings;
339 if error:
340 problems = errors;
341 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
342 for message_line in message:
343 problems.append(' %s' % message_line)
344
345 result = []
346 if (warnings):
347 result.append(output_api.PresubmitPromptWarning(
348 'Banned functions were used.\n' + '\n'.join(warnings)))
349 if (errors):
350 result.append(output_api.PresubmitError(
351 'Banned functions were used.\n' + '\n'.join(errors)))
352 return result
353
354
[email protected]6c063c62012-07-11 19:11:06355def _CheckNoPragmaOnce(input_api, output_api):
356 """Make sure that banned functions are not used."""
357 files = []
358 pattern = input_api.re.compile(r'^#pragma\s+once',
359 input_api.re.MULTILINE)
360 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
361 if not f.LocalPath().endswith('.h'):
362 continue
363 contents = input_api.ReadFile(f)
364 if pattern.search(contents):
365 files.append(f)
366
367 if files:
368 return [output_api.PresubmitError(
369 'Do not use #pragma once in header files.\n'
370 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
371 files)]
372 return []
373
[email protected]127f18ec2012-06-16 05:05:59374
[email protected]e7479052012-09-19 00:26:12375def _CheckNoTrinaryTrueFalse(input_api, output_api):
376 """Checks to make sure we don't introduce use of foo ? true : false."""
377 problems = []
378 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
379 for f in input_api.AffectedFiles():
380 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
381 continue
382
383 for line_num, line in f.ChangedContents():
384 if pattern.match(line):
385 problems.append(' %s:%d' % (f.LocalPath(), line_num))
386
387 if not problems:
388 return []
389 return [output_api.PresubmitPromptWarning(
390 'Please consider avoiding the "? true : false" pattern if possible.\n' +
391 '\n'.join(problems))]
392
393
[email protected]55f9f382012-07-31 11:02:18394def _CheckUnwantedDependencies(input_api, output_api):
395 """Runs checkdeps on #include statements added in this
396 change. Breaking - rules is an error, breaking ! rules is a
397 warning.
398 """
399 # We need to wait until we have an input_api object and use this
400 # roundabout construct to import checkdeps because this file is
401 # eval-ed and thus doesn't have __file__.
402 original_sys_path = sys.path
403 try:
404 sys.path = sys.path + [input_api.os_path.join(
405 input_api.PresubmitLocalPath(), 'tools', 'checkdeps')]
406 import checkdeps
407 from cpp_checker import CppChecker
408 from rules import Rule
409 finally:
410 # Restore sys.path to what it was before.
411 sys.path = original_sys_path
412
413 added_includes = []
414 for f in input_api.AffectedFiles():
415 if not CppChecker.IsCppFile(f.LocalPath()):
416 continue
417
418 changed_lines = [line for line_num, line in f.ChangedContents()]
419 added_includes.append([f.LocalPath(), changed_lines])
420
421 deps_checker = checkdeps.DepsChecker()
422
423 error_descriptions = []
424 warning_descriptions = []
425 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
426 added_includes):
427 description_with_path = '%s\n %s' % (path, rule_description)
428 if rule_type == Rule.DISALLOW:
429 error_descriptions.append(description_with_path)
430 else:
431 warning_descriptions.append(description_with_path)
432
433 results = []
434 if error_descriptions:
435 results.append(output_api.PresubmitError(
436 'You added one or more #includes that violate checkdeps rules.',
437 error_descriptions))
438 if warning_descriptions:
[email protected]f7051d52013-04-02 18:31:42439 results.append(output_api.PresubmitPromptOrNotify(
[email protected]55f9f382012-07-31 11:02:18440 'You added one or more #includes of files that are temporarily\n'
441 'allowed but being removed. Can you avoid introducing the\n'
442 '#include? See relevant DEPS file(s) for details and contacts.',
443 warning_descriptions))
444 return results
445
446
[email protected]fbcafe5a2012-08-08 15:31:22447def _CheckFilePermissions(input_api, output_api):
448 """Check that all files have their permissions properly set."""
449 args = [sys.executable, 'tools/checkperms/checkperms.py', '--root',
450 input_api.change.RepositoryRoot()]
451 for f in input_api.AffectedFiles():
452 args += ['--file', f.LocalPath()]
453 errors = []
454 (errors, stderrdata) = subprocess.Popen(args).communicate()
455
456 results = []
457 if errors:
[email protected]c8278b32012-10-30 20:35:49458 results.append(output_api.PresubmitError('checkperms.py failed.',
[email protected]fbcafe5a2012-08-08 15:31:22459 errors))
460 return results
461
462
[email protected]c8278b32012-10-30 20:35:49463def _CheckNoAuraWindowPropertyHInHeaders(input_api, output_api):
464 """Makes sure we don't include ui/aura/window_property.h
465 in header files.
466 """
467 pattern = input_api.re.compile(r'^#include\s*"ui/aura/window_property.h"')
468 errors = []
469 for f in input_api.AffectedFiles():
470 if not f.LocalPath().endswith('.h'):
471 continue
472 for line_num, line in f.ChangedContents():
473 if pattern.match(line):
474 errors.append(' %s:%d' % (f.LocalPath(), line_num))
475
476 results = []
477 if errors:
478 results.append(output_api.PresubmitError(
479 'Header files should not include ui/aura/window_property.h', errors))
480 return results
481
482
[email protected]cf9b78f2012-11-14 11:40:28483def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
484 """Checks that the lines in scope occur in the right order.
485
486 1. C system files in alphabetical order
487 2. C++ system files in alphabetical order
488 3. Project's .h files
489 """
490
491 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
492 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
493 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
494
495 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
496
497 state = C_SYSTEM_INCLUDES
498
499 previous_line = ''
[email protected]728b9bb2012-11-14 20:38:57500 previous_line_num = 0
[email protected]cf9b78f2012-11-14 11:40:28501 problem_linenums = []
502 for line_num, line in scope:
503 if c_system_include_pattern.match(line):
504 if state != C_SYSTEM_INCLUDES:
[email protected]728b9bb2012-11-14 20:38:57505 problem_linenums.append((line_num, previous_line_num))
[email protected]cf9b78f2012-11-14 11:40:28506 elif previous_line and previous_line > line:
[email protected]728b9bb2012-11-14 20:38:57507 problem_linenums.append((line_num, previous_line_num))
[email protected]cf9b78f2012-11-14 11:40:28508 elif cpp_system_include_pattern.match(line):
509 if state == C_SYSTEM_INCLUDES:
510 state = CPP_SYSTEM_INCLUDES
511 elif state == CUSTOM_INCLUDES:
[email protected]728b9bb2012-11-14 20:38:57512 problem_linenums.append((line_num, previous_line_num))
[email protected]cf9b78f2012-11-14 11:40:28513 elif previous_line and previous_line > line:
[email protected]728b9bb2012-11-14 20:38:57514 problem_linenums.append((line_num, previous_line_num))
[email protected]cf9b78f2012-11-14 11:40:28515 elif custom_include_pattern.match(line):
516 if state != CUSTOM_INCLUDES:
517 state = CUSTOM_INCLUDES
518 elif previous_line and previous_line > line:
[email protected]728b9bb2012-11-14 20:38:57519 problem_linenums.append((line_num, previous_line_num))
[email protected]cf9b78f2012-11-14 11:40:28520 else:
521 problem_linenums.append(line_num)
522 previous_line = line
[email protected]728b9bb2012-11-14 20:38:57523 previous_line_num = line_num
[email protected]cf9b78f2012-11-14 11:40:28524
525 warnings = []
[email protected]728b9bb2012-11-14 20:38:57526 for (line_num, previous_line_num) in problem_linenums:
527 if line_num in changed_linenums or previous_line_num in changed_linenums:
[email protected]cf9b78f2012-11-14 11:40:28528 warnings.append(' %s:%d' % (file_path, line_num))
529 return warnings
530
531
[email protected]ac294a12012-12-06 16:38:43532def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
[email protected]cf9b78f2012-11-14 11:40:28533 """Checks the #include order for the given file f."""
534
[email protected]2299dcf2012-11-15 19:56:24535 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
[email protected]962f117e2012-11-22 18:11:56536 # Exclude #include <.../...> includes from the check; e.g., <sys/...> includes
537 # often need to appear in a specific order.
538 excluded_include_pattern = input_api.re.compile(r'\s*#include \<.*/.*')
[email protected]2299dcf2012-11-15 19:56:24539 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
[email protected]0e5c1852012-12-18 20:17:11540 if_pattern = input_api.re.compile(
541 r'\s*#\s*(if|elif|else|endif|define|undef).*')
542 # Some files need specialized order of includes; exclude such files from this
543 # check.
544 uncheckable_includes_pattern = input_api.re.compile(
545 r'\s*#include '
546 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
[email protected]cf9b78f2012-11-14 11:40:28547
548 contents = f.NewContents()
549 warnings = []
550 line_num = 0
551
[email protected]ac294a12012-12-06 16:38:43552 # Handle the special first include. If the first include file is
553 # some/path/file.h, the corresponding including file can be some/path/file.cc,
554 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
555 # etc. It's also possible that no special first include exists.
556 for line in contents:
557 line_num += 1
558 if system_include_pattern.match(line):
559 # No special first include -> process the line again along with normal
560 # includes.
561 line_num -= 1
562 break
563 match = custom_include_pattern.match(line)
564 if match:
565 match_dict = match.groupdict()
566 header_basename = input_api.os_path.basename(
567 match_dict['FILE']).replace('.h', '')
568 if header_basename not in input_api.os_path.basename(f.LocalPath()):
[email protected]2299dcf2012-11-15 19:56:24569 # No special first include -> process the line again along with normal
570 # includes.
571 line_num -= 1
[email protected]ac294a12012-12-06 16:38:43572 break
[email protected]cf9b78f2012-11-14 11:40:28573
574 # Split into scopes: Each region between #if and #endif is its own scope.
575 scopes = []
576 current_scope = []
577 for line in contents[line_num:]:
578 line_num += 1
[email protected]0e5c1852012-12-18 20:17:11579 if uncheckable_includes_pattern.match(line):
580 return []
[email protected]2309b0fa02012-11-16 12:18:27581 if if_pattern.match(line):
[email protected]cf9b78f2012-11-14 11:40:28582 scopes.append(current_scope)
583 current_scope = []
[email protected]962f117e2012-11-22 18:11:56584 elif ((system_include_pattern.match(line) or
585 custom_include_pattern.match(line)) and
586 not excluded_include_pattern.match(line)):
[email protected]cf9b78f2012-11-14 11:40:28587 current_scope.append((line_num, line))
588 scopes.append(current_scope)
589
590 for scope in scopes:
591 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
592 changed_linenums))
593 return warnings
594
595
596def _CheckIncludeOrder(input_api, output_api):
597 """Checks that the #include order is correct.
598
599 1. The corresponding header for source files.
600 2. C system files in alphabetical order
601 3. C++ system files in alphabetical order
602 4. Project's .h files in alphabetical order
603
[email protected]ac294a12012-12-06 16:38:43604 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
605 these rules separately.
[email protected]cf9b78f2012-11-14 11:40:28606 """
607
608 warnings = []
609 for f in input_api.AffectedFiles():
[email protected]ac294a12012-12-06 16:38:43610 if f.LocalPath().endswith(('.cc', '.h')):
611 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
612 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
[email protected]cf9b78f2012-11-14 11:40:28613
614 results = []
615 if warnings:
[email protected]f7051d52013-04-02 18:31:42616 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
[email protected]120cf540d2012-12-10 17:55:53617 warnings))
[email protected]cf9b78f2012-11-14 11:40:28618 return results
619
620
[email protected]70ca77752012-11-20 03:45:03621def _CheckForVersionControlConflictsInFile(input_api, f):
622 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
623 errors = []
624 for line_num, line in f.ChangedContents():
625 if pattern.match(line):
626 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
627 return errors
628
629
630def _CheckForVersionControlConflicts(input_api, output_api):
631 """Usually this is not intentional and will cause a compile failure."""
632 errors = []
633 for f in input_api.AffectedFiles():
634 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
635
636 results = []
637 if errors:
638 results.append(output_api.PresubmitError(
639 'Version control conflict markers found, please resolve.', errors))
640 return results
641
642
[email protected]06e6d0ff2012-12-11 01:36:44643def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
644 def FilterFile(affected_file):
645 """Filter function for use with input_api.AffectedSourceFiles,
646 below. This filters out everything except non-test files from
647 top-level directories that generally speaking should not hard-code
648 service URLs (e.g. src/android_webview/, src/content/ and others).
649 """
650 return input_api.FilterSourceFile(
651 affected_file,
[email protected]78bb39d62012-12-11 15:11:56652 white_list=(r'^(android_webview|base|content|net)[\\\/].*', ),
[email protected]06e6d0ff2012-12-11 01:36:44653 black_list=(_EXCLUDED_PATHS +
654 _TEST_CODE_EXCLUDED_PATHS +
655 input_api.DEFAULT_BLACK_LIST))
656
657 pattern = input_api.re.compile('"[^"]*google\.com[^"]*"')
658 problems = [] # items are (filename, line_number, line)
659 for f in input_api.AffectedSourceFiles(FilterFile):
660 for line_num, line in f.ChangedContents():
661 if pattern.search(line):
662 problems.append((f.LocalPath(), line_num, line))
663
664 if problems:
[email protected]f7051d52013-04-02 18:31:42665 return [output_api.PresubmitPromptOrNotify(
[email protected]06e6d0ff2012-12-11 01:36:44666 'Most layers below src/chrome/ should not hardcode service URLs.\n'
667 'Are you sure this is correct? (Contact: [email protected])',
668 [' %s:%d: %s' % (
669 problem[0], problem[1], problem[2]) for problem in problems])]
[email protected]2fdd1f362013-01-16 03:56:03670 else:
671 return []
[email protected]06e6d0ff2012-12-11 01:36:44672
673
[email protected]d2530012013-01-25 16:39:27674def _CheckNoAbbreviationInPngFileName(input_api, output_api):
675 """Makes sure there are no abbreviations in the name of PNG files.
676 """
[email protected]4053a48e2013-01-25 21:43:04677 pattern = input_api.re.compile(r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$')
[email protected]d2530012013-01-25 16:39:27678 errors = []
679 for f in input_api.AffectedFiles(include_deletes=False):
680 if pattern.match(f.LocalPath()):
681 errors.append(' %s' % f.LocalPath())
682
683 results = []
684 if errors:
685 results.append(output_api.PresubmitError(
686 'The name of PNG files should not have abbreviations. \n'
687 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
688 'Contact [email protected] if you have questions.', errors))
689 return results
690
691
[email protected]22c9bd72011-03-27 16:47:39692def _CommonChecks(input_api, output_api):
693 """Checks common to both upload and commit."""
694 results = []
695 results.extend(input_api.canned_checks.PanProjectChecks(
696 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
[email protected]66daa702011-05-28 14:41:46697 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:19698 results.extend(
699 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:54700 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:18701 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:22702 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:44703 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:59704 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:06705 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:12706 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:18707 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:22708 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]c8278b32012-10-30 20:35:49709 results.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api, output_api))
[email protected]2309b0fa02012-11-16 12:18:27710 results.extend(_CheckIncludeOrder(input_api, output_api))
[email protected]70ca77752012-11-20 03:45:03711 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
[email protected]b8079ae4a2012-12-05 19:56:49712 results.extend(_CheckPatchFiles(input_api, output_api))
[email protected]06e6d0ff2012-12-11 01:36:44713 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
[email protected]d2530012013-01-25 16:39:27714 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
[email protected]b00342e7f2013-03-26 16:21:54715 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
[email protected]2299dcf2012-11-15 19:56:24716
717 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
718 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
719 input_api, output_api,
720 input_api.PresubmitLocalPath(),
[email protected]6be63382013-01-21 15:42:38721 whitelist=[r'^PRESUBMIT_test\.py$']))
[email protected]22c9bd72011-03-27 16:47:39722 return results
[email protected]1f7b4172010-01-28 01:17:34723
[email protected]b337cb5b2011-01-23 21:24:05724
725def _CheckSubversionConfig(input_api, output_api):
726 """Verifies the subversion config file is correctly setup.
727
728 Checks that autoprops are enabled, returns an error otherwise.
729 """
730 join = input_api.os_path.join
731 if input_api.platform == 'win32':
732 appdata = input_api.environ.get('APPDATA', '')
733 if not appdata:
734 return [output_api.PresubmitError('%APPDATA% is not configured.')]
735 path = join(appdata, 'Subversion', 'config')
736 else:
737 home = input_api.environ.get('HOME', '')
738 if not home:
739 return [output_api.PresubmitError('$HOME is not configured.')]
740 path = join(home, '.subversion', 'config')
741
742 error_msg = (
743 'Please look at http://dev.chromium.org/developers/coding-style to\n'
744 'configure your subversion configuration file. This enables automatic\n'
[email protected]c6a3c10b2011-01-24 16:14:20745 'properties to simplify the project maintenance.\n'
746 'Pro-tip: just download and install\n'
747 'http://src.chromium.org/viewvc/chrome/trunk/tools/build/slave/config\n')
[email protected]b337cb5b2011-01-23 21:24:05748
749 try:
750 lines = open(path, 'r').read().splitlines()
751 # Make sure auto-props is enabled and check for 2 Chromium standard
752 # auto-prop.
753 if (not '*.cc = svn:eol-style=LF' in lines or
754 not '*.pdf = svn:mime-type=application/pdf' in lines or
755 not 'enable-auto-props = yes' in lines):
756 return [
[email protected]79ed7e62011-02-21 21:08:53757 output_api.PresubmitNotifyResult(
[email protected]b337cb5b2011-01-23 21:24:05758 'It looks like you have not configured your subversion config '
[email protected]b5359c02011-02-01 20:29:56759 'file or it is not up-to-date.\n' + error_msg)
[email protected]b337cb5b2011-01-23 21:24:05760 ]
761 except (OSError, IOError):
762 return [
[email protected]79ed7e62011-02-21 21:08:53763 output_api.PresubmitNotifyResult(
[email protected]b337cb5b2011-01-23 21:24:05764 'Can\'t find your subversion config file.\n' + error_msg)
765 ]
766 return []
767
768
[email protected]66daa702011-05-28 14:41:46769def _CheckAuthorizedAuthor(input_api, output_api):
770 """For non-googler/chromites committers, verify the author's email address is
771 in AUTHORS.
772 """
[email protected]9bb9cb82011-06-13 20:43:01773 # TODO(maruel): Add it to input_api?
774 import fnmatch
775
[email protected]66daa702011-05-28 14:41:46776 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:01777 if not author:
778 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:46779 return []
[email protected]c99663292011-05-31 19:46:08780 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:46781 input_api.PresubmitLocalPath(), 'AUTHORS')
782 valid_authors = (
783 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
784 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:18785 valid_authors = [item.group(1).lower() for item in valid_authors if item]
[email protected]d8b50be2011-06-15 14:19:44786 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
[email protected]5861efb2013-01-07 18:33:23787 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
[email protected]66daa702011-05-28 14:41:46788 return [output_api.PresubmitPromptWarning(
789 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
790 '\n'
791 'http://www.chromium.org/developers/contributing-code and read the '
792 '"Legal" section\n'
793 'If you are a chromite, verify the contributor signed the CLA.') %
794 author)]
795 return []
796
797
[email protected]b8079ae4a2012-12-05 19:56:49798def _CheckPatchFiles(input_api, output_api):
799 problems = [f.LocalPath() for f in input_api.AffectedFiles()
800 if f.LocalPath().endswith(('.orig', '.rej'))]
801 if problems:
802 return [output_api.PresubmitError(
803 "Don't commit .rej and .orig files.", problems)]
[email protected]2fdd1f362013-01-16 03:56:03804 else:
805 return []
[email protected]b8079ae4a2012-12-05 19:56:49806
807
[email protected]b00342e7f2013-03-26 16:21:54808def _DidYouMeanOSMacro(bad_macro):
809 try:
810 return {'A': 'OS_ANDROID',
811 'B': 'OS_BSD',
812 'C': 'OS_CHROMEOS',
813 'F': 'OS_FREEBSD',
814 'L': 'OS_LINUX',
815 'M': 'OS_MACOSX',
816 'N': 'OS_NACL',
817 'O': 'OS_OPENBSD',
818 'P': 'OS_POSIX',
819 'S': 'OS_SOLARIS',
820 'W': 'OS_WIN'}[bad_macro[3].upper()]
821 except KeyError:
822 return ''
823
824
825def _CheckForInvalidOSMacrosInFile(input_api, f):
826 """Check for sensible looking, totally invalid OS macros."""
827 preprocessor_statement = input_api.re.compile(r'^\s*#')
828 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
829 results = []
830 for lnum, line in f.ChangedContents():
831 if preprocessor_statement.search(line):
832 for match in os_macro.finditer(line):
833 if not match.group(1) in _VALID_OS_MACROS:
834 good = _DidYouMeanOSMacro(match.group(1))
835 did_you_mean = ' (did you mean %s?)' % good if good else ''
836 results.append(' %s:%d %s%s' % (f.LocalPath(),
837 lnum,
838 match.group(1),
839 did_you_mean))
840 return results
841
842
843def _CheckForInvalidOSMacros(input_api, output_api):
844 """Check all affected files for invalid OS macros."""
845 bad_macros = []
846 for f in input_api.AffectedFiles():
847 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css')):
848 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
849
850 if not bad_macros:
851 return []
852
853 return [output_api.PresubmitError(
854 'Possibly invalid OS macro[s] found. Please fix your code\n'
855 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
856
857
[email protected]1f7b4172010-01-28 01:17:34858def CheckChangeOnUpload(input_api, output_api):
859 results = []
860 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:54861 return results
[email protected]ca8d19842009-02-19 16:33:12862
863
864def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:54865 results = []
[email protected]1f7b4172010-01-28 01:17:34866 results.extend(_CommonChecks(input_api, output_api))
[email protected]dd805fe2009-10-01 08:11:51867 # TODO(thestig) temporarily disabled, doesn't work in third_party/
868 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
869 # input_api, output_api, sources))
[email protected]fe5f57c52009-06-05 14:25:54870 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:27871 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:34872 input_api,
873 output_api,
[email protected]2fdd1f362013-01-16 03:56:03874 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:27875 results.extend(input_api.canned_checks.CheckRietveldTryJobExecution(input_api,
[email protected]2fdd1f362013-01-16 03:56:03876 output_api, 'http://codereview.chromium.org',
[email protected]c1ba4c52012-03-09 14:23:28877 ('win_rel', 'linux_rel', 'mac_rel, win:compile'),
878 '[email protected]'))
[email protected]806e98e2010-03-19 17:49:27879
[email protected]3e4eb112011-01-18 03:29:54880 results.extend(input_api.canned_checks.CheckChangeHasBugField(
881 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:41882 results.extend(input_api.canned_checks.CheckChangeHasDescription(
883 input_api, output_api))
[email protected]b337cb5b2011-01-23 21:24:05884 results.extend(_CheckSubversionConfig(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:54885 return results
[email protected]ca8d19842009-02-19 16:33:12886
887
[email protected]5efb2a822011-09-27 23:06:13888def GetPreferredTrySlaves(project, change):
[email protected]4ce995ea2012-06-27 02:13:10889 files = change.LocalPaths()
890
[email protected]751b05f2013-01-10 23:12:17891 if not files or all(re.search(r'[\\/]OWNERS$', f) for f in files):
[email protected]3019c902012-06-29 00:09:03892 return []
893
[email protected]d668899a2012-09-06 18:16:59894 if all(re.search('\.(m|mm)$|(^|[/_])mac[/_.]', f) for f in files):
[email protected]7fab6202013-02-21 17:54:35895 return ['mac_rel', 'mac_asan', 'mac:compile']
[email protected]d668899a2012-09-06 18:16:59896 if all(re.search('(^|[/_])win[/_.]', f) for f in files):
[email protected]7fab6202013-02-21 17:54:35897 return ['win_rel', 'win7_aura', 'win:compile']
[email protected]d668899a2012-09-06 18:16:59898 if all(re.search('(^|[/_])android[/_.]', f) for f in files):
[email protected]3e2f0402012-11-02 16:28:01899 return ['android_dbg', 'android_clang_dbg']
[email protected]356aa542012-09-19 23:31:29900 if all(re.search('^native_client_sdk', f) for f in files):
901 return ['linux_nacl_sdk', 'win_nacl_sdk', 'mac_nacl_sdk']
[email protected]de142152012-10-03 23:02:45902 if all(re.search('[/_]ios[/_.]', f) for f in files):
903 return ['ios_rel_device', 'ios_dbg_simulator']
[email protected]4ce995ea2012-06-27 02:13:10904
[email protected]3e2f0402012-11-02 16:28:01905 trybots = [
906 'android_clang_dbg',
907 'android_dbg',
908 'ios_dbg_simulator',
909 'ios_rel_device',
910 'linux_asan',
[email protected]95c989162012-11-29 05:58:25911 'linux_aura',
[email protected]3e2f0402012-11-02 16:28:01912 'linux_chromeos',
913 'linux_clang:compile',
914 'linux_rel',
915 'mac_asan',
916 'mac_rel',
[email protected]7fab6202013-02-21 17:54:35917 'mac:compile',
[email protected]aa85c8b2013-01-11 04:20:28918 'win7_aura',
[email protected]3e2f0402012-11-02 16:28:01919 'win_rel',
[email protected]7fab6202013-02-21 17:54:35920 'win:compile',
[email protected]3e2f0402012-11-02 16:28:01921 ]
[email protected]911753b2012-08-02 12:11:54922
923 # Match things like path/aura/file.cc and path/file_aura.cc.
[email protected]95c989162012-11-29 05:58:25924 # Same for chromeos.
925 if any(re.search('[/_](aura|chromeos)', f) for f in files):
[email protected]3e2f0402012-11-02 16:28:01926 trybots += ['linux_chromeos_clang:compile', 'linux_chromeos_asan']
[email protected]4ce995ea2012-06-27 02:13:10927
[email protected]4ce995ea2012-06-27 02:13:10928 return trybots