1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Top-level presubmit script for Chromium.
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8 for more details about the presubmit API built into gcl.
19 r
"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
20 r
"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
21 r
"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
27 r
"^webkit[\\\/]compositor_bindings[\\\/].*",
28 r
".+[\\\/]pnacl_shim\.c$",
32 _TEST_ONLY_WARNING
= (
33 'You might be calling functions intended only for testing from\n'
34 'production code. It is OK to ignore this warning if you know what\n'
35 'you are doing, as the heuristics used to detect the situation are\n'
36 'not perfect. The commit queue will not block on this warning.\n'
37 'Email joi@chromium.org if you have questions.')
40 _INCLUDE_ORDER_WARNING
= (
41 'Your #include order seems to be broken. Send mail to\n'
42 'marja@chromium.org if this is not the case.')
45 _BANNED_OBJC_FUNCTIONS
= (
49 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
50 'prohibited. Please use CrTrackingArea instead.',
51 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
58 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
60 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
65 'convertPointFromBase:',
67 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
68 'Please use |convertPoint:(point) fromView:nil| instead.',
69 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
74 'convertPointToBase:',
76 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
77 'Please use |convertPoint:(point) toView:nil| instead.',
78 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
83 'convertRectFromBase:',
85 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
86 'Please use |convertRect:(point) fromView:nil| instead.',
87 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
94 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
95 'Please use |convertRect:(point) toView:nil| instead.',
96 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
101 'convertSizeFromBase:',
103 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
104 'Please use |convertSize:(point) fromView:nil| instead.',
105 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
110 'convertSizeToBase:',
112 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
113 'Please use |convertSize:(point) toView:nil| instead.',
114 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
121 _BANNED_CPP_FUNCTIONS
= (
122 # Make sure that gtest's FRIEND_TEST() macro is not used; the
123 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
124 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
128 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
129 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
137 'New code should not use ScopedAllowIO. Post a task to the blocking',
138 'pool or the FILE thread instead.',
142 r
"^content[\\\/]shell[\\\/]shell_browser_main\.cc$",
146 'FilePathWatcher::Delegate',
148 'New code should not use FilePathWatcher::Delegate. Use the callback',
149 'interface instead.',
155 'browser::FindOrCreateTabbedBrowser',
157 'This function is deprecated and we\'re working on removing it. Pass',
158 'more context to get a Browser*, like a WebContents, window, or session',
159 'id. Talk to robertshield@ for more information.',
167 'This function is deprecated and we\'re working on removing it. Rename',
177 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api
, output_api
):
178 """Attempts to prevent use of functions intended only for testing in
179 non-testing code. For now this is just a best-effort implementation
180 that ignores header files and may have some false positives. A
181 better implementation would probably need a proper C++ parser.
183 # We only scan .cc files and the like, as the declaration of
184 # for-testing functions in header files are hard to distinguish from
185 # calls to such functions without a proper C++ parser.
186 platform_specifiers
= r
'(_(android|chromeos|gtk|mac|posix|win))?'
187 source_extensions
= r
'\.(cc|cpp|cxx|mm)$'
188 file_inclusion_pattern
= r
'.+%s' % source_extensions
189 file_exclusion_patterns
= (
190 r
'.*[/\\](fake_|test_|mock_).+%s' % source_extensions
,
191 r
'.+_test_(base|support|util)%s' % source_extensions
,
192 r
'.+_(api|browser|perf|unit|ui)?test%s%s' % (platform_specifiers
,
194 r
'.+profile_sync_service_harness%s' % source_extensions
,
196 path_exclusion_patterns
= (
197 r
'.*[/\\](test|tool(s)?)[/\\].*',
198 # At request of folks maintaining this folder.
199 r
'chrome[/\\]browser[/\\]automation[/\\].*',
202 base_function_pattern
= r
'ForTest(ing)?|for_test(ing)?'
203 inclusion_pattern
= input_api
.re
.compile(r
'(%s)\s*\(' % base_function_pattern
)
204 exclusion_pattern
= input_api
.re
.compile(
205 r
'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
206 base_function_pattern
, base_function_pattern
))
208 def FilterFile(affected_file
):
209 black_list
= (file_exclusion_patterns
+ path_exclusion_patterns
+
210 _EXCLUDED_PATHS
+ input_api
.DEFAULT_BLACK_LIST
)
211 return input_api
.FilterSourceFile(
213 white_list
=(file_inclusion_pattern
, ),
214 black_list
=black_list
)
217 for f
in input_api
.AffectedSourceFiles(FilterFile
):
218 local_path
= f
.LocalPath()
219 lines
= input_api
.ReadFile(f
).splitlines()
222 if (inclusion_pattern
.search(line
) and
223 not exclusion_pattern
.search(line
)):
225 '%s:%d\n %s' % (local_path
, line_number
, line
.strip()))
229 if not input_api
.is_committing
:
230 return [output_api
.PresubmitPromptWarning(_TEST_ONLY_WARNING
, problems
)]
232 # We don't warn on commit, to avoid stopping commits going through CQ.
233 return [output_api
.PresubmitNotifyResult(_TEST_ONLY_WARNING
, problems
)]
238 def _CheckNoIOStreamInHeaders(input_api
, output_api
):
239 """Checks to make sure no .h files include <iostream>."""
241 pattern
= input_api
.re
.compile(r
'^#include\s*<iostream>',
242 input_api
.re
.MULTILINE
)
243 for f
in input_api
.AffectedSourceFiles(input_api
.FilterSourceFile
):
244 if not f
.LocalPath().endswith('.h'):
246 contents
= input_api
.ReadFile(f
)
247 if pattern
.search(contents
):
251 return [ output_api
.PresubmitError(
252 'Do not #include <iostream> in header files, since it inserts static '
253 'initialization into every file including the header. Instead, '
254 '#include <ostream>. See http://crbug.com/94794',
259 def _CheckNoUNIT_TESTInSourceFiles(input_api
, output_api
):
260 """Checks to make sure no source files use UNIT_TEST"""
262 for f
in input_api
.AffectedFiles():
263 if (not f
.LocalPath().endswith(('.cc', '.mm'))):
266 for line_num
, line
in f
.ChangedContents():
267 if 'UNIT_TEST' in line
:
268 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
272 return [output_api
.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
273 '\n'.join(problems
))]
276 def _CheckNoNewWStrings(input_api
, output_api
):
277 """Checks to make sure we don't introduce use of wstrings."""
279 for f
in input_api
.AffectedFiles():
280 if (not f
.LocalPath().endswith(('.cc', '.h')) or
281 f
.LocalPath().endswith('test.cc')):
285 for line_num
, line
in f
.ChangedContents():
286 if 'presubmit: allow wstring' in line
:
288 elif not allowWString
and 'wstring' in line
:
289 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
296 return [output_api
.PresubmitPromptWarning('New code should not use wstrings.'
297 ' If you are calling a cross-platform API that accepts a wstring, '
299 '\n'.join(problems
))]
302 def _CheckNoDEPSGIT(input_api
, output_api
):
303 """Make sure .DEPS.git is never modified manually."""
304 if any(f
.LocalPath().endswith('.DEPS.git') for f
in
305 input_api
.AffectedFiles()):
306 return [output_api
.PresubmitError(
307 'Never commit changes to .DEPS.git. This file is maintained by an\n'
308 'automated system based on what\'s in DEPS and your changes will be\n'
310 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n'
311 'for more information')]
315 def _CheckNoBannedFunctions(input_api
, output_api
):
316 """Make sure that banned functions are not used."""
320 file_filter
= lambda f
: f
.LocalPath().endswith(('.mm', '.m', '.h'))
321 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
322 for line_num
, line
in f
.ChangedContents():
323 for func_name
, message
, error
in _BANNED_OBJC_FUNCTIONS
:
324 if func_name
in line
:
328 problems
.append(' %s:%d:' % (f
.LocalPath(), line_num
))
329 for message_line
in message
:
330 problems
.append(' %s' % message_line
)
332 file_filter
= lambda f
: f
.LocalPath().endswith(('.cc', '.mm', '.h'))
333 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
334 for line_num
, line
in f
.ChangedContents():
335 for func_name
, message
, error
, excluded_paths
in _BANNED_CPP_FUNCTIONS
:
336 def IsBlacklisted(affected_file
, blacklist
):
337 local_path
= affected_file
.LocalPath()
338 for item
in blacklist
:
339 if input_api
.re
.match(item
, local_path
):
342 if IsBlacklisted(f
, excluded_paths
):
344 if func_name
in line
:
348 problems
.append(' %s:%d:' % (f
.LocalPath(), line_num
))
349 for message_line
in message
:
350 problems
.append(' %s' % message_line
)
354 result
.append(output_api
.PresubmitPromptWarning(
355 'Banned functions were used.\n' + '\n'.join(warnings
)))
357 result
.append(output_api
.PresubmitError(
358 'Banned functions were used.\n' + '\n'.join(errors
)))
362 def _CheckNoPragmaOnce(input_api
, output_api
):
363 """Make sure that banned functions are not used."""
365 pattern
= input_api
.re
.compile(r
'^#pragma\s+once',
366 input_api
.re
.MULTILINE
)
367 for f
in input_api
.AffectedSourceFiles(input_api
.FilterSourceFile
):
368 if not f
.LocalPath().endswith('.h'):
370 contents
= input_api
.ReadFile(f
)
371 if pattern
.search(contents
):
375 return [output_api
.PresubmitError(
376 'Do not use #pragma once in header files.\n'
377 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
382 def _CheckNoTrinaryTrueFalse(input_api
, output_api
):
383 """Checks to make sure we don't introduce use of foo ? true : false."""
385 pattern
= input_api
.re
.compile(r
'\?\s*(true|false)\s*:\s*(true|false)')
386 for f
in input_api
.AffectedFiles():
387 if not f
.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
390 for line_num
, line
in f
.ChangedContents():
391 if pattern
.match(line
):
392 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
396 return [output_api
.PresubmitPromptWarning(
397 'Please consider avoiding the "? true : false" pattern if possible.\n' +
398 '\n'.join(problems
))]
401 def _CheckUnwantedDependencies(input_api
, output_api
):
402 """Runs checkdeps on #include statements added in this
403 change. Breaking - rules is an error, breaking ! rules is a
406 # We need to wait until we have an input_api object and use this
407 # roundabout construct to import checkdeps because this file is
408 # eval-ed and thus doesn't have __file__.
409 original_sys_path
= sys
.path
411 sys
.path
= sys
.path
+ [input_api
.os_path
.join(
412 input_api
.PresubmitLocalPath(), 'tools', 'checkdeps')]
414 from cpp_checker
import CppChecker
415 from rules
import Rule
417 # Restore sys.path to what it was before.
418 sys
.path
= original_sys_path
421 for f
in input_api
.AffectedFiles():
422 if not CppChecker
.IsCppFile(f
.LocalPath()):
425 changed_lines
= [line
for line_num
, line
in f
.ChangedContents()]
426 added_includes
.append([f
.LocalPath(), changed_lines
])
428 deps_checker
= checkdeps
.DepsChecker()
430 error_descriptions
= []
431 warning_descriptions
= []
432 for path
, rule_type
, rule_description
in deps_checker
.CheckAddedCppIncludes(
434 description_with_path
= '%s\n %s' % (path
, rule_description
)
435 if rule_type
== Rule
.DISALLOW
:
436 error_descriptions
.append(description_with_path
)
438 warning_descriptions
.append(description_with_path
)
441 if error_descriptions
:
442 results
.append(output_api
.PresubmitError(
443 'You added one or more #includes that violate checkdeps rules.',
445 if warning_descriptions
:
446 if not input_api
.is_committing
:
447 warning_factory
= output_api
.PresubmitPromptWarning
449 # We don't want to block use of the CQ when there is a warning
450 # of this kind, so we only show a message when committing.
451 warning_factory
= output_api
.PresubmitNotifyResult
452 results
.append(warning_factory(
453 'You added one or more #includes of files that are temporarily\n'
454 'allowed but being removed. Can you avoid introducing the\n'
455 '#include? See relevant DEPS file(s) for details and contacts.',
456 warning_descriptions
))
460 def _CheckFilePermissions(input_api
, output_api
):
461 """Check that all files have their permissions properly set."""
462 args
= [sys
.executable
, 'tools/checkperms/checkperms.py', '--root',
463 input_api
.change
.RepositoryRoot()]
464 for f
in input_api
.AffectedFiles():
465 args
+= ['--file', f
.LocalPath()]
467 (errors
, stderrdata
) = subprocess
.Popen(args
).communicate()
471 results
.append(output_api
.PresubmitError('checkperms.py failed.',
476 def _CheckNoAuraWindowPropertyHInHeaders(input_api
, output_api
):
477 """Makes sure we don't include ui/aura/window_property.h
480 pattern
= input_api
.re
.compile(r
'^#include\s*"ui/aura/window_property.h"')
482 for f
in input_api
.AffectedFiles():
483 if not f
.LocalPath().endswith('.h'):
485 for line_num
, line
in f
.ChangedContents():
486 if pattern
.match(line
):
487 errors
.append(' %s:%d' % (f
.LocalPath(), line_num
))
491 results
.append(output_api
.PresubmitError(
492 'Header files should not include ui/aura/window_property.h', errors
))
496 def _CheckIncludeOrderForScope(scope
, input_api
, file_path
, changed_linenums
):
497 """Checks that the lines in scope occur in the right order.
499 1. C system files in alphabetical order
500 2. C++ system files in alphabetical order
501 3. Project's .h files
504 c_system_include_pattern
= input_api
.re
.compile(r
'\s*#include <.*\.h>')
505 cpp_system_include_pattern
= input_api
.re
.compile(r
'\s*#include <.*>')
506 custom_include_pattern
= input_api
.re
.compile(r
'\s*#include ".*')
508 C_SYSTEM_INCLUDES
, CPP_SYSTEM_INCLUDES
, CUSTOM_INCLUDES
= range(3)
510 state
= C_SYSTEM_INCLUDES
513 previous_line_num
= 0
514 problem_linenums
= []
515 for line_num
, line
in scope
:
516 if c_system_include_pattern
.match(line
):
517 if state
!= C_SYSTEM_INCLUDES
:
518 problem_linenums
.append((line_num
, previous_line_num
))
519 elif previous_line
and previous_line
> line
:
520 problem_linenums
.append((line_num
, previous_line_num
))
521 elif cpp_system_include_pattern
.match(line
):
522 if state
== C_SYSTEM_INCLUDES
:
523 state
= CPP_SYSTEM_INCLUDES
524 elif state
== CUSTOM_INCLUDES
:
525 problem_linenums
.append((line_num
, previous_line_num
))
526 elif previous_line
and previous_line
> line
:
527 problem_linenums
.append((line_num
, previous_line_num
))
528 elif custom_include_pattern
.match(line
):
529 if state
!= CUSTOM_INCLUDES
:
530 state
= CUSTOM_INCLUDES
531 elif previous_line
and previous_line
> line
:
532 problem_linenums
.append((line_num
, previous_line_num
))
534 problem_linenums
.append(line_num
)
536 previous_line_num
= line_num
539 for (line_num
, previous_line_num
) in problem_linenums
:
540 if line_num
in changed_linenums
or previous_line_num
in changed_linenums
:
541 warnings
.append(' %s:%d' % (file_path
, line_num
))
545 def _CheckIncludeOrderInFile(input_api
, f
, is_source
, changed_linenums
):
546 """Checks the #include order for the given file f."""
548 system_include_pattern
= input_api
.re
.compile(r
'\s*#include \<.*')
549 # Exclude #include <.../...> includes from the check; e.g., <sys/...> includes
550 # often need to appear in a specific order.
551 excluded_include_pattern
= input_api
.re
.compile(r
'\s*#include \<.*/.*')
552 custom_include_pattern
= input_api
.re
.compile(r
'\s*#include "(?P<FILE>.*)"')
553 if_pattern
= input_api
.re
.compile(r
'\s*#\s*(if|elif|else|endif).*')
555 contents
= f
.NewContents()
559 # Handle the special first include for source files. If the header file is
560 # some/path/file.h, the corresponding source file can be some/path/file.cc,
561 # some/other/path/file.cc, some/path/file_platform.cc etc. It's also possible
562 # that no special first include exists.
564 for line
in contents
:
566 if system_include_pattern
.match(line
):
567 # No special first include -> process the line again along with normal
571 match
= custom_include_pattern
.match(line
)
573 match_dict
= match
.groupdict()
574 header_basename
= input_api
.os_path
.basename(
575 match_dict
['FILE']).replace('.h', '')
576 if header_basename
not in input_api
.os_path
.basename(f
.LocalPath()):
577 # No special first include -> process the line again along with normal
582 # Split into scopes: Each region between #if and #endif is its own scope.
585 for line
in contents
[line_num
:]:
587 if if_pattern
.match(line
):
588 scopes
.append(current_scope
)
590 elif ((system_include_pattern
.match(line
) or
591 custom_include_pattern
.match(line
)) and
592 not excluded_include_pattern
.match(line
)):
593 current_scope
.append((line_num
, line
))
594 scopes
.append(current_scope
)
597 warnings
.extend(_CheckIncludeOrderForScope(scope
, input_api
, f
.LocalPath(),
602 def _CheckIncludeOrder(input_api
, output_api
):
603 """Checks that the #include order is correct.
605 1. The corresponding header for source files.
606 2. C system files in alphabetical order
607 3. C++ system files in alphabetical order
608 4. Project's .h files in alphabetical order
610 Each region between #if and #endif follows these rules separately.
614 for f
in input_api
.AffectedFiles():
615 changed_linenums
= set([line_num
for line_num
, _
in f
.ChangedContents()])
616 if f
.LocalPath().endswith('.cc'):
617 warnings
.extend(_CheckIncludeOrderInFile(input_api
, f
, True,
619 elif f
.LocalPath().endswith('.h'):
620 warnings
.extend(_CheckIncludeOrderInFile(input_api
, f
, False,
625 results
.append(output_api
.PresubmitPromptWarning(_INCLUDE_ORDER_WARNING
,
630 def _CheckForVersionControlConflictsInFile(input_api
, f
):
631 pattern
= input_api
.re
.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
633 for line_num
, line
in f
.ChangedContents():
634 if pattern
.match(line
):
635 errors
.append(' %s:%d %s' % (f
.LocalPath(), line_num
, line
))
639 def _CheckForVersionControlConflicts(input_api
, output_api
):
640 """Usually this is not intentional and will cause a compile failure."""
642 for f
in input_api
.AffectedFiles():
643 errors
.extend(_CheckForVersionControlConflictsInFile(input_api
, f
))
647 results
.append(output_api
.PresubmitError(
648 'Version control conflict markers found, please resolve.', errors
))
652 def _CommonChecks(input_api
, output_api
):
653 """Checks common to both upload and commit."""
655 results
.extend(input_api
.canned_checks
.PanProjectChecks(
656 input_api
, output_api
, excluded_paths
=_EXCLUDED_PATHS
))
657 results
.extend(_CheckAuthorizedAuthor(input_api
, output_api
))
659 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api
, output_api
))
660 results
.extend(_CheckNoIOStreamInHeaders(input_api
, output_api
))
661 results
.extend(_CheckNoUNIT_TESTInSourceFiles(input_api
, output_api
))
662 results
.extend(_CheckNoNewWStrings(input_api
, output_api
))
663 results
.extend(_CheckNoDEPSGIT(input_api
, output_api
))
664 results
.extend(_CheckNoBannedFunctions(input_api
, output_api
))
665 results
.extend(_CheckNoPragmaOnce(input_api
, output_api
))
666 results
.extend(_CheckNoTrinaryTrueFalse(input_api
, output_api
))
667 results
.extend(_CheckUnwantedDependencies(input_api
, output_api
))
668 results
.extend(_CheckFilePermissions(input_api
, output_api
))
669 results
.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api
, output_api
))
670 results
.extend(_CheckIncludeOrder(input_api
, output_api
))
671 results
.extend(_CheckForVersionControlConflicts(input_api
, output_api
))
673 if any('PRESUBMIT.py' == f
.LocalPath() for f
in input_api
.AffectedFiles()):
674 results
.extend(input_api
.canned_checks
.RunUnitTestsInDirectory(
675 input_api
, output_api
,
676 input_api
.PresubmitLocalPath(),
677 whitelist
=[r
'.+_test\.py$']))
681 def _CheckSubversionConfig(input_api
, output_api
):
682 """Verifies the subversion config file is correctly setup.
684 Checks that autoprops are enabled, returns an error otherwise.
686 join
= input_api
.os_path
.join
687 if input_api
.platform
== 'win32':
688 appdata
= input_api
.environ
.get('APPDATA', '')
690 return [output_api
.PresubmitError('%APPDATA% is not configured.')]
691 path
= join(appdata
, 'Subversion', 'config')
693 home
= input_api
.environ
.get('HOME', '')
695 return [output_api
.PresubmitError('$HOME is not configured.')]
696 path
= join(home
, '.subversion', 'config')
699 'Please look at http://dev.chromium.org/developers/coding-style to\n'
700 'configure your subversion configuration file. This enables automatic\n'
701 'properties to simplify the project maintenance.\n'
702 'Pro-tip: just download and install\n'
703 'http://src.chromium.org/viewvc/chrome/trunk/tools/build/slave/config\n')
706 lines
= open(path
, 'r').read().splitlines()
707 # Make sure auto-props is enabled and check for 2 Chromium standard
709 if (not '*.cc = svn:eol-style=LF' in lines
or
710 not '*.pdf = svn:mime-type=application/pdf' in lines
or
711 not 'enable-auto-props = yes' in lines
):
713 output_api
.PresubmitNotifyResult(
714 'It looks like you have not configured your subversion config '
715 'file or it is not up-to-date.\n' + error_msg
)
717 except (OSError, IOError):
719 output_api
.PresubmitNotifyResult(
720 'Can\'t find your subversion config file.\n' + error_msg
)
725 def _CheckAuthorizedAuthor(input_api
, output_api
):
726 """For non-googler/chromites committers, verify the author's email address is
729 # TODO(maruel): Add it to input_api?
732 author
= input_api
.change
.author_email
734 input_api
.logging
.info('No author, skipping AUTHOR check')
736 authors_path
= input_api
.os_path
.join(
737 input_api
.PresubmitLocalPath(), 'AUTHORS')
739 input_api
.re
.match(r
'[^#]+\s+\<(.+?)\>\s*$', line
)
740 for line
in open(authors_path
))
741 valid_authors
= [item
.group(1).lower() for item
in valid_authors
if item
]
742 if input_api
.verbose
:
743 print 'Valid authors are %s' % ', '.join(valid_authors
)
744 if not any(fnmatch
.fnmatch(author
.lower(), valid
) for valid
in valid_authors
):
745 return [output_api
.PresubmitPromptWarning(
746 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
748 'http://www.chromium.org/developers/contributing-code and read the '
750 'If you are a chromite, verify the contributor signed the CLA.') %
755 def CheckChangeOnUpload(input_api
, output_api
):
757 results
.extend(_CommonChecks(input_api
, output_api
))
761 def CheckChangeOnCommit(input_api
, output_api
):
763 results
.extend(_CommonChecks(input_api
, output_api
))
764 # TODO(thestig) temporarily disabled, doesn't work in third_party/
765 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
766 # input_api, output_api, sources))
767 # Make sure the tree is 'open'.
768 results
.extend(input_api
.canned_checks
.CheckTreeIsOpen(
771 json_url
='http://chromium-status.appspot.com/current?format=json'))
772 results
.extend(input_api
.canned_checks
.CheckRietveldTryJobExecution(input_api
,
773 output_api
, 'http://codereview.chromium.org',
774 ('win_rel', 'linux_rel', 'mac_rel, win:compile'),
775 'tryserver@chromium.org'))
777 results
.extend(input_api
.canned_checks
.CheckChangeHasBugField(
778 input_api
, output_api
))
779 results
.extend(input_api
.canned_checks
.CheckChangeHasDescription(
780 input_api
, output_api
))
781 results
.extend(_CheckSubversionConfig(input_api
, output_api
))
785 def GetPreferredTrySlaves(project
, change
):
786 files
= change
.LocalPaths()
791 if all(re
.search('\.(m|mm)$|(^|[/_])mac[/_.]', f
) for f
in files
):
792 return ['mac_rel', 'mac_asan']
793 if all(re
.search('(^|[/_])win[/_.]', f
) for f
in files
):
795 if all(re
.search('(^|[/_])android[/_.]', f
) for f
in files
):
796 return ['android_dbg', 'android_clang_dbg']
797 if all(re
.search('^native_client_sdk', f
) for f
in files
):
798 return ['linux_nacl_sdk', 'win_nacl_sdk', 'mac_nacl_sdk']
799 if all(re
.search('[/_]ios[/_.]', f
) for f
in files
):
800 return ['ios_rel_device', 'ios_dbg_simulator']
810 'linux_clang:compile',
818 # Match things like path/aura/file.cc and path/file_aura.cc.
820 if any(re
.search('[/_](aura|chromeos)', f
) for f
in files
):
821 trybots
+= ['linux_chromeos_clang:compile', 'linux_chromeos_asan']