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
"^native_client_sdk[\\\/]src[\\\/]tools[\\\/].*.mk",
22 r
"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
28 r
"^webkit[\\\/]compositor_bindings[\\\/].*",
29 r
".+[\\\/]pnacl_shim\.c$",
32 # Fragment of a regular expression that matches file name suffixes
33 # used to indicate different platforms.
34 _PLATFORM_SPECIFIERS
= r
'(_(android|chromeos|gtk|mac|posix|win))?'
36 # Fragment of a regular expression that matches C++ and Objective-C++
37 # implementation files.
38 _IMPLEMENTATION_EXTENSIONS
= r
'\.(cc|cpp|cxx|mm)$'
40 # Regular expression that matches code only used for test binaries
42 _TEST_CODE_EXCLUDED_PATHS
= (
43 r
'.*[/\\](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS
,
44 r
'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS
,
45 r
'.+_(api|browser|perf|unit|ui)?test%s%s' % (_PLATFORM_SPECIFIERS
,
46 _IMPLEMENTATION_EXTENSIONS
),
47 r
'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS
,
48 r
'.*[/\\](test|tool(s)?)[/\\].*',
49 # At request of folks maintaining this folder.
50 r
'chrome[/\\]browser[/\\]automation[/\\].*',
53 _TEST_ONLY_WARNING
= (
54 'You might be calling functions intended only for testing from\n'
55 'production code. It is OK to ignore this warning if you know what\n'
56 'you are doing, as the heuristics used to detect the situation are\n'
57 'not perfect. The commit queue will not block on this warning.\n'
58 'Email joi@chromium.org if you have questions.')
61 _INCLUDE_ORDER_WARNING
= (
62 'Your #include order seems to be broken. Send mail to\n'
63 'marja@chromium.org if this is not the case.')
66 _BANNED_OBJC_FUNCTIONS
= (
70 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
71 'prohibited. Please use CrTrackingArea instead.',
72 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
79 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
81 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
86 'convertPointFromBase:',
88 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
89 'Please use |convertPoint:(point) fromView:nil| instead.',
90 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
95 'convertPointToBase:',
97 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
98 'Please use |convertPoint:(point) toView:nil| instead.',
99 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
104 'convertRectFromBase:',
106 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
107 'Please use |convertRect:(point) fromView:nil| instead.',
108 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
113 'convertRectToBase:',
115 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
116 'Please use |convertRect:(point) toView:nil| instead.',
117 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
122 'convertSizeFromBase:',
124 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
125 'Please use |convertSize:(point) fromView:nil| instead.',
126 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
131 'convertSizeToBase:',
133 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
134 'Please use |convertSize:(point) toView:nil| instead.',
135 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
142 _BANNED_CPP_FUNCTIONS
= (
143 # Make sure that gtest's FRIEND_TEST() macro is not used; the
144 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
145 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
149 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
150 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
158 'New code should not use ScopedAllowIO. Post a task to the blocking',
159 'pool or the FILE thread instead.',
163 r
"^content[\\\/]shell[\\\/]shell_browser_main\.cc$",
169 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api
, output_api
):
170 """Attempts to prevent use of functions intended only for testing in
171 non-testing code. For now this is just a best-effort implementation
172 that ignores header files and may have some false positives. A
173 better implementation would probably need a proper C++ parser.
175 # We only scan .cc files and the like, as the declaration of
176 # for-testing functions in header files are hard to distinguish from
177 # calls to such functions without a proper C++ parser.
178 file_inclusion_pattern
= r
'.+%s' % _IMPLEMENTATION_EXTENSIONS
180 base_function_pattern
= r
'ForTest(ing)?|for_test(ing)?'
181 inclusion_pattern
= input_api
.re
.compile(r
'(%s)\s*\(' % base_function_pattern
)
182 exclusion_pattern
= input_api
.re
.compile(
183 r
'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
184 base_function_pattern
, base_function_pattern
))
186 def FilterFile(affected_file
):
187 black_list
= (_EXCLUDED_PATHS
+
188 _TEST_CODE_EXCLUDED_PATHS
+
189 input_api
.DEFAULT_BLACK_LIST
)
190 return input_api
.FilterSourceFile(
192 white_list
=(file_inclusion_pattern
, ),
193 black_list
=black_list
)
196 for f
in input_api
.AffectedSourceFiles(FilterFile
):
197 local_path
= f
.LocalPath()
198 lines
= input_api
.ReadFile(f
).splitlines()
201 if (inclusion_pattern
.search(line
) and
202 not exclusion_pattern
.search(line
)):
204 '%s:%d\n %s' % (local_path
, line_number
, line
.strip()))
208 if not input_api
.is_committing
:
209 return [output_api
.PresubmitPromptWarning(_TEST_ONLY_WARNING
, problems
)]
211 # We don't warn on commit, to avoid stopping commits going through CQ.
212 return [output_api
.PresubmitNotifyResult(_TEST_ONLY_WARNING
, problems
)]
217 def _CheckNoIOStreamInHeaders(input_api
, output_api
):
218 """Checks to make sure no .h files include <iostream>."""
220 pattern
= input_api
.re
.compile(r
'^#include\s*<iostream>',
221 input_api
.re
.MULTILINE
)
222 for f
in input_api
.AffectedSourceFiles(input_api
.FilterSourceFile
):
223 if not f
.LocalPath().endswith('.h'):
225 contents
= input_api
.ReadFile(f
)
226 if pattern
.search(contents
):
230 return [ output_api
.PresubmitError(
231 'Do not #include <iostream> in header files, since it inserts static '
232 'initialization into every file including the header. Instead, '
233 '#include <ostream>. See http://crbug.com/94794',
238 def _CheckNoUNIT_TESTInSourceFiles(input_api
, output_api
):
239 """Checks to make sure no source files use UNIT_TEST"""
241 for f
in input_api
.AffectedFiles():
242 if (not f
.LocalPath().endswith(('.cc', '.mm'))):
245 for line_num
, line
in f
.ChangedContents():
246 if 'UNIT_TEST' in line
:
247 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
251 return [output_api
.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
252 '\n'.join(problems
))]
255 def _CheckNoNewWStrings(input_api
, output_api
):
256 """Checks to make sure we don't introduce use of wstrings."""
258 for f
in input_api
.AffectedFiles():
259 if (not f
.LocalPath().endswith(('.cc', '.h')) or
260 f
.LocalPath().endswith('test.cc')):
264 for line_num
, line
in f
.ChangedContents():
265 if 'presubmit: allow wstring' in line
:
267 elif not allowWString
and 'wstring' in line
:
268 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
275 return [output_api
.PresubmitPromptWarning('New code should not use wstrings.'
276 ' If you are calling a cross-platform API that accepts a wstring, '
278 '\n'.join(problems
))]
281 def _CheckNoDEPSGIT(input_api
, output_api
):
282 """Make sure .DEPS.git is never modified manually."""
283 if any(f
.LocalPath().endswith('.DEPS.git') for f
in
284 input_api
.AffectedFiles()):
285 return [output_api
.PresubmitError(
286 'Never commit changes to .DEPS.git. This file is maintained by an\n'
287 'automated system based on what\'s in DEPS and your changes will be\n'
289 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n'
290 'for more information')]
294 def _CheckNoBannedFunctions(input_api
, output_api
):
295 """Make sure that banned functions are not used."""
299 file_filter
= lambda f
: f
.LocalPath().endswith(('.mm', '.m', '.h'))
300 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
301 for line_num
, line
in f
.ChangedContents():
302 for func_name
, message
, error
in _BANNED_OBJC_FUNCTIONS
:
303 if func_name
in line
:
307 problems
.append(' %s:%d:' % (f
.LocalPath(), line_num
))
308 for message_line
in message
:
309 problems
.append(' %s' % message_line
)
311 file_filter
= lambda f
: f
.LocalPath().endswith(('.cc', '.mm', '.h'))
312 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
313 for line_num
, line
in f
.ChangedContents():
314 for func_name
, message
, error
, excluded_paths
in _BANNED_CPP_FUNCTIONS
:
315 def IsBlacklisted(affected_file
, blacklist
):
316 local_path
= affected_file
.LocalPath()
317 for item
in blacklist
:
318 if input_api
.re
.match(item
, local_path
):
321 if IsBlacklisted(f
, excluded_paths
):
323 if func_name
in line
:
327 problems
.append(' %s:%d:' % (f
.LocalPath(), line_num
))
328 for message_line
in message
:
329 problems
.append(' %s' % message_line
)
333 result
.append(output_api
.PresubmitPromptWarning(
334 'Banned functions were used.\n' + '\n'.join(warnings
)))
336 result
.append(output_api
.PresubmitError(
337 'Banned functions were used.\n' + '\n'.join(errors
)))
341 def _CheckNoPragmaOnce(input_api
, output_api
):
342 """Make sure that banned functions are not used."""
344 pattern
= input_api
.re
.compile(r
'^#pragma\s+once',
345 input_api
.re
.MULTILINE
)
346 for f
in input_api
.AffectedSourceFiles(input_api
.FilterSourceFile
):
347 if not f
.LocalPath().endswith('.h'):
349 contents
= input_api
.ReadFile(f
)
350 if pattern
.search(contents
):
354 return [output_api
.PresubmitError(
355 'Do not use #pragma once in header files.\n'
356 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
361 def _CheckNoTrinaryTrueFalse(input_api
, output_api
):
362 """Checks to make sure we don't introduce use of foo ? true : false."""
364 pattern
= input_api
.re
.compile(r
'\?\s*(true|false)\s*:\s*(true|false)')
365 for f
in input_api
.AffectedFiles():
366 if not f
.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
369 for line_num
, line
in f
.ChangedContents():
370 if pattern
.match(line
):
371 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
375 return [output_api
.PresubmitPromptWarning(
376 'Please consider avoiding the "? true : false" pattern if possible.\n' +
377 '\n'.join(problems
))]
380 def _CheckUnwantedDependencies(input_api
, output_api
):
381 """Runs checkdeps on #include statements added in this
382 change. Breaking - rules is an error, breaking ! rules is a
385 # We need to wait until we have an input_api object and use this
386 # roundabout construct to import checkdeps because this file is
387 # eval-ed and thus doesn't have __file__.
388 original_sys_path
= sys
.path
390 sys
.path
= sys
.path
+ [input_api
.os_path
.join(
391 input_api
.PresubmitLocalPath(), 'tools', 'checkdeps')]
393 from cpp_checker
import CppChecker
394 from rules
import Rule
396 # Restore sys.path to what it was before.
397 sys
.path
= original_sys_path
400 for f
in input_api
.AffectedFiles():
401 if not CppChecker
.IsCppFile(f
.LocalPath()):
404 changed_lines
= [line
for line_num
, line
in f
.ChangedContents()]
405 added_includes
.append([f
.LocalPath(), changed_lines
])
407 deps_checker
= checkdeps
.DepsChecker()
409 error_descriptions
= []
410 warning_descriptions
= []
411 for path
, rule_type
, rule_description
in deps_checker
.CheckAddedCppIncludes(
413 description_with_path
= '%s\n %s' % (path
, rule_description
)
414 if rule_type
== Rule
.DISALLOW
:
415 error_descriptions
.append(description_with_path
)
417 warning_descriptions
.append(description_with_path
)
420 if error_descriptions
:
421 results
.append(output_api
.PresubmitError(
422 'You added one or more #includes that violate checkdeps rules.',
424 if warning_descriptions
:
425 if not input_api
.is_committing
:
426 warning_factory
= output_api
.PresubmitPromptWarning
428 # We don't want to block use of the CQ when there is a warning
429 # of this kind, so we only show a message when committing.
430 warning_factory
= output_api
.PresubmitNotifyResult
431 results
.append(warning_factory(
432 'You added one or more #includes of files that are temporarily\n'
433 'allowed but being removed. Can you avoid introducing the\n'
434 '#include? See relevant DEPS file(s) for details and contacts.',
435 warning_descriptions
))
439 def _CheckFilePermissions(input_api
, output_api
):
440 """Check that all files have their permissions properly set."""
441 args
= [sys
.executable
, 'tools/checkperms/checkperms.py', '--root',
442 input_api
.change
.RepositoryRoot()]
443 for f
in input_api
.AffectedFiles():
444 args
+= ['--file', f
.LocalPath()]
446 (errors
, stderrdata
) = subprocess
.Popen(args
).communicate()
450 results
.append(output_api
.PresubmitError('checkperms.py failed.',
455 def _CheckNoAuraWindowPropertyHInHeaders(input_api
, output_api
):
456 """Makes sure we don't include ui/aura/window_property.h
459 pattern
= input_api
.re
.compile(r
'^#include\s*"ui/aura/window_property.h"')
461 for f
in input_api
.AffectedFiles():
462 if not f
.LocalPath().endswith('.h'):
464 for line_num
, line
in f
.ChangedContents():
465 if pattern
.match(line
):
466 errors
.append(' %s:%d' % (f
.LocalPath(), line_num
))
470 results
.append(output_api
.PresubmitError(
471 'Header files should not include ui/aura/window_property.h', errors
))
475 def _CheckIncludeOrderForScope(scope
, input_api
, file_path
, changed_linenums
):
476 """Checks that the lines in scope occur in the right order.
478 1. C system files in alphabetical order
479 2. C++ system files in alphabetical order
480 3. Project's .h files
483 c_system_include_pattern
= input_api
.re
.compile(r
'\s*#include <.*\.h>')
484 cpp_system_include_pattern
= input_api
.re
.compile(r
'\s*#include <.*>')
485 custom_include_pattern
= input_api
.re
.compile(r
'\s*#include ".*')
487 C_SYSTEM_INCLUDES
, CPP_SYSTEM_INCLUDES
, CUSTOM_INCLUDES
= range(3)
489 state
= C_SYSTEM_INCLUDES
492 previous_line_num
= 0
493 problem_linenums
= []
494 for line_num
, line
in scope
:
495 if c_system_include_pattern
.match(line
):
496 if state
!= C_SYSTEM_INCLUDES
:
497 problem_linenums
.append((line_num
, previous_line_num
))
498 elif previous_line
and previous_line
> line
:
499 problem_linenums
.append((line_num
, previous_line_num
))
500 elif cpp_system_include_pattern
.match(line
):
501 if state
== C_SYSTEM_INCLUDES
:
502 state
= CPP_SYSTEM_INCLUDES
503 elif state
== CUSTOM_INCLUDES
:
504 problem_linenums
.append((line_num
, previous_line_num
))
505 elif previous_line
and previous_line
> line
:
506 problem_linenums
.append((line_num
, previous_line_num
))
507 elif custom_include_pattern
.match(line
):
508 if state
!= CUSTOM_INCLUDES
:
509 state
= CUSTOM_INCLUDES
510 elif previous_line
and previous_line
> line
:
511 problem_linenums
.append((line_num
, previous_line_num
))
513 problem_linenums
.append(line_num
)
515 previous_line_num
= line_num
518 for (line_num
, previous_line_num
) in problem_linenums
:
519 if line_num
in changed_linenums
or previous_line_num
in changed_linenums
:
520 warnings
.append(' %s:%d' % (file_path
, line_num
))
524 def _CheckIncludeOrderInFile(input_api
, f
, changed_linenums
):
525 """Checks the #include order for the given file f."""
527 system_include_pattern
= input_api
.re
.compile(r
'\s*#include \<.*')
528 # Exclude #include <.../...> includes from the check; e.g., <sys/...> includes
529 # often need to appear in a specific order.
530 excluded_include_pattern
= input_api
.re
.compile(r
'\s*#include \<.*/.*')
531 custom_include_pattern
= input_api
.re
.compile(r
'\s*#include "(?P<FILE>.*)"')
532 if_pattern
= input_api
.re
.compile(
533 r
'\s*#\s*(if|elif|else|endif|define|undef).*')
534 # Some files need specialized order of includes; exclude such files from this
536 uncheckable_includes_pattern
= input_api
.re
.compile(
538 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
540 contents
= f
.NewContents()
544 # Handle the special first include. If the first include file is
545 # some/path/file.h, the corresponding including file can be some/path/file.cc,
546 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
547 # etc. It's also possible that no special first include exists.
548 for line
in contents
:
550 if system_include_pattern
.match(line
):
551 # No special first include -> process the line again along with normal
555 match
= custom_include_pattern
.match(line
)
557 match_dict
= match
.groupdict()
558 header_basename
= input_api
.os_path
.basename(
559 match_dict
['FILE']).replace('.h', '')
560 if header_basename
not in input_api
.os_path
.basename(f
.LocalPath()):
561 # No special first include -> process the line again along with normal
566 # Split into scopes: Each region between #if and #endif is its own scope.
569 for line
in contents
[line_num
:]:
571 if uncheckable_includes_pattern
.match(line
):
573 if if_pattern
.match(line
):
574 scopes
.append(current_scope
)
576 elif ((system_include_pattern
.match(line
) or
577 custom_include_pattern
.match(line
)) and
578 not excluded_include_pattern
.match(line
)):
579 current_scope
.append((line_num
, line
))
580 scopes
.append(current_scope
)
583 warnings
.extend(_CheckIncludeOrderForScope(scope
, input_api
, f
.LocalPath(),
588 def _CheckIncludeOrder(input_api
, output_api
):
589 """Checks that the #include order is correct.
591 1. The corresponding header for source files.
592 2. C system files in alphabetical order
593 3. C++ system files in alphabetical order
594 4. Project's .h files in alphabetical order
596 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
597 these rules separately.
601 for f
in input_api
.AffectedFiles():
602 if f
.LocalPath().endswith(('.cc', '.h')):
603 changed_linenums
= set(line_num
for line_num
, _
in f
.ChangedContents())
604 warnings
.extend(_CheckIncludeOrderInFile(input_api
, f
, changed_linenums
))
608 if not input_api
.is_committing
:
609 results
.append(output_api
.PresubmitPromptWarning(_INCLUDE_ORDER_WARNING
,
612 # We don't warn on commit, to avoid stopping commits going through CQ.
613 results
.append(output_api
.PresubmitNotifyResult(_INCLUDE_ORDER_WARNING
,
618 def _CheckForVersionControlConflictsInFile(input_api
, f
):
619 pattern
= input_api
.re
.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
621 for line_num
, line
in f
.ChangedContents():
622 if pattern
.match(line
):
623 errors
.append(' %s:%d %s' % (f
.LocalPath(), line_num
, line
))
627 def _CheckForVersionControlConflicts(input_api
, output_api
):
628 """Usually this is not intentional and will cause a compile failure."""
630 for f
in input_api
.AffectedFiles():
631 errors
.extend(_CheckForVersionControlConflictsInFile(input_api
, f
))
635 results
.append(output_api
.PresubmitError(
636 'Version control conflict markers found, please resolve.', errors
))
640 def _CheckHardcodedGoogleHostsInLowerLayers(input_api
, output_api
):
641 def FilterFile(affected_file
):
642 """Filter function for use with input_api.AffectedSourceFiles,
643 below. This filters out everything except non-test files from
644 top-level directories that generally speaking should not hard-code
645 service URLs (e.g. src/android_webview/, src/content/ and others).
647 return input_api
.FilterSourceFile(
649 white_list
=(r
'^(android_webview|base|content|net)[\\\/].*', ),
650 black_list
=(_EXCLUDED_PATHS
+
651 _TEST_CODE_EXCLUDED_PATHS
+
652 input_api
.DEFAULT_BLACK_LIST
))
654 pattern
= input_api
.re
.compile('"[^"]*google\.com[^"]*"')
655 problems
= [] # items are (filename, line_number, line)
656 for f
in input_api
.AffectedSourceFiles(FilterFile
):
657 for line_num
, line
in f
.ChangedContents():
658 if pattern
.search(line
):
659 problems
.append((f
.LocalPath(), line_num
, line
))
662 if not input_api
.is_committing
:
663 warning_factory
= output_api
.PresubmitPromptWarning
665 # We don't want to block use of the CQ when there is a warning
666 # of this kind, so we only show a message when committing.
667 warning_factory
= output_api
.PresubmitNotifyResult
668 return [warning_factory(
669 'Most layers below src/chrome/ should not hardcode service URLs.\n'
670 'Are you sure this is correct? (Contact: joi@chromium.org)',
672 problem
[0], problem
[1], problem
[2]) for problem
in problems
])]
677 def _CheckNoAbbreviationInPngFileName(input_api
, output_api
):
678 """Makes sure there are no abbreviations in the name of PNG files.
680 pattern
= input_api
.re
.compile(r
'.*_[a-z]_.*\.png$|.*_[a-z]\.png$')
682 for f
in input_api
.AffectedFiles(include_deletes
=False):
683 if pattern
.match(f
.LocalPath()):
684 errors
.append(' %s' % f
.LocalPath())
688 results
.append(output_api
.PresubmitError(
689 'The name of PNG files should not have abbreviations. \n'
690 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
691 'Contact oshima@chromium.org if you have questions.', errors
))
695 def _CommonChecks(input_api
, output_api
):
696 """Checks common to both upload and commit."""
698 results
.extend(input_api
.canned_checks
.PanProjectChecks(
699 input_api
, output_api
, excluded_paths
=_EXCLUDED_PATHS
))
700 results
.extend(_CheckAuthorizedAuthor(input_api
, output_api
))
702 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api
, output_api
))
703 results
.extend(_CheckNoIOStreamInHeaders(input_api
, output_api
))
704 results
.extend(_CheckNoUNIT_TESTInSourceFiles(input_api
, output_api
))
705 results
.extend(_CheckNoNewWStrings(input_api
, output_api
))
706 results
.extend(_CheckNoDEPSGIT(input_api
, output_api
))
707 results
.extend(_CheckNoBannedFunctions(input_api
, output_api
))
708 results
.extend(_CheckNoPragmaOnce(input_api
, output_api
))
709 results
.extend(_CheckNoTrinaryTrueFalse(input_api
, output_api
))
710 results
.extend(_CheckUnwantedDependencies(input_api
, output_api
))
711 results
.extend(_CheckFilePermissions(input_api
, output_api
))
712 results
.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api
, output_api
))
713 results
.extend(_CheckIncludeOrder(input_api
, output_api
))
714 results
.extend(_CheckForVersionControlConflicts(input_api
, output_api
))
715 results
.extend(_CheckPatchFiles(input_api
, output_api
))
716 results
.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api
, output_api
))
717 results
.extend(_CheckNoAbbreviationInPngFileName(input_api
, output_api
))
719 if any('PRESUBMIT.py' == f
.LocalPath() for f
in input_api
.AffectedFiles()):
720 results
.extend(input_api
.canned_checks
.RunUnitTestsInDirectory(
721 input_api
, output_api
,
722 input_api
.PresubmitLocalPath(),
723 whitelist
=[r
'^PRESUBMIT_test\.py$']))
727 def _CheckSubversionConfig(input_api
, output_api
):
728 """Verifies the subversion config file is correctly setup.
730 Checks that autoprops are enabled, returns an error otherwise.
732 join
= input_api
.os_path
.join
733 if input_api
.platform
== 'win32':
734 appdata
= input_api
.environ
.get('APPDATA', '')
736 return [output_api
.PresubmitError('%APPDATA% is not configured.')]
737 path
= join(appdata
, 'Subversion', 'config')
739 home
= input_api
.environ
.get('HOME', '')
741 return [output_api
.PresubmitError('$HOME is not configured.')]
742 path
= join(home
, '.subversion', 'config')
745 'Please look at http://dev.chromium.org/developers/coding-style to\n'
746 'configure your subversion configuration file. This enables automatic\n'
747 'properties to simplify the project maintenance.\n'
748 'Pro-tip: just download and install\n'
749 'http://src.chromium.org/viewvc/chrome/trunk/tools/build/slave/config\n')
752 lines
= open(path
, 'r').read().splitlines()
753 # Make sure auto-props is enabled and check for 2 Chromium standard
755 if (not '*.cc = svn:eol-style=LF' in lines
or
756 not '*.pdf = svn:mime-type=application/pdf' in lines
or
757 not 'enable-auto-props = yes' in lines
):
759 output_api
.PresubmitNotifyResult(
760 'It looks like you have not configured your subversion config '
761 'file or it is not up-to-date.\n' + error_msg
)
763 except (OSError, IOError):
765 output_api
.PresubmitNotifyResult(
766 'Can\'t find your subversion config file.\n' + error_msg
)
771 def _CheckAuthorizedAuthor(input_api
, output_api
):
772 """For non-googler/chromites committers, verify the author's email address is
775 # TODO(maruel): Add it to input_api?
778 author
= input_api
.change
.author_email
780 input_api
.logging
.info('No author, skipping AUTHOR check')
782 authors_path
= input_api
.os_path
.join(
783 input_api
.PresubmitLocalPath(), 'AUTHORS')
785 input_api
.re
.match(r
'[^#]+\s+\<(.+?)\>\s*$', line
)
786 for line
in open(authors_path
))
787 valid_authors
= [item
.group(1).lower() for item
in valid_authors
if item
]
788 if not any(fnmatch
.fnmatch(author
.lower(), valid
) for valid
in valid_authors
):
789 input_api
.logging
.info('Valid authors are %s', ', '.join(valid_authors
))
790 return [output_api
.PresubmitPromptWarning(
791 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
793 'http://www.chromium.org/developers/contributing-code and read the '
795 'If you are a chromite, verify the contributor signed the CLA.') %
800 def _CheckPatchFiles(input_api
, output_api
):
801 problems
= [f
.LocalPath() for f
in input_api
.AffectedFiles()
802 if f
.LocalPath().endswith(('.orig', '.rej'))]
804 return [output_api
.PresubmitError(
805 "Don't commit .rej and .orig files.", problems
)]
810 def CheckChangeOnUpload(input_api
, output_api
):
812 results
.extend(_CommonChecks(input_api
, output_api
))
816 def CheckChangeOnCommit(input_api
, output_api
):
818 results
.extend(_CommonChecks(input_api
, output_api
))
819 # TODO(thestig) temporarily disabled, doesn't work in third_party/
820 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
821 # input_api, output_api, sources))
822 # Make sure the tree is 'open'.
823 results
.extend(input_api
.canned_checks
.CheckTreeIsOpen(
826 json_url
='http://chromium-status.appspot.com/current?format=json'))
827 results
.extend(input_api
.canned_checks
.CheckRietveldTryJobExecution(input_api
,
828 output_api
, 'http://codereview.chromium.org',
829 ('win_rel', 'linux_rel', 'mac_rel, win:compile'),
830 'tryserver@chromium.org'))
832 results
.extend(input_api
.canned_checks
.CheckChangeHasBugField(
833 input_api
, output_api
))
834 results
.extend(input_api
.canned_checks
.CheckChangeHasDescription(
835 input_api
, output_api
))
836 results
.extend(_CheckSubversionConfig(input_api
, output_api
))
840 def GetPreferredTrySlaves(project
, change
):
841 files
= change
.LocalPaths()
843 if not files
or all(re
.search(r
'[\\/]OWNERS$', f
) for f
in files
):
846 if all(re
.search('\.(m|mm)$|(^|[/_])mac[/_.]', f
) for f
in files
):
847 return ['mac_rel', 'mac_asan']
848 if all(re
.search('(^|[/_])win[/_.]', f
) for f
in files
):
850 if all(re
.search('(^|[/_])android[/_.]', f
) for f
in files
):
851 return ['android_dbg', 'android_clang_dbg']
852 if all(re
.search('^native_client_sdk', f
) for f
in files
):
853 return ['linux_nacl_sdk', 'win_nacl_sdk', 'mac_nacl_sdk']
854 if all(re
.search('[/_]ios[/_.]', f
) for f
in files
):
855 return ['ios_rel_device', 'ios_dbg_simulator']
865 'linux_clang:compile',
873 # Match things like path/aura/file.cc and path/file_aura.cc.
875 if any(re
.search('[/_](aura|chromeos)', f
) for f
in files
):
876 trybots
+= ['linux_chromeos_clang:compile', 'linux_chromeos_asan']