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$",
31 # Fragment of a regular expression that matches file name suffixes
32 # used to indicate different platforms.
33 _PLATFORM_SPECIFIERS
= r
'(_(android|chromeos|gtk|mac|posix|win))?'
35 # Fragment of a regular expression that matches C++ and Objective-C++
36 # implementation files.
37 _IMPLEMENTATION_EXTENSIONS
= r
'\.(cc|cpp|cxx|mm)$'
39 # Regular expression that matches code only used for test binaries
41 _TEST_CODE_EXCLUDED_PATHS
= (
42 r
'.*[/\\](fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS
,
43 r
'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS
,
44 r
'.+_(api|browser|perf|unit|ui)?test%s%s' % (_PLATFORM_SPECIFIERS
,
45 _IMPLEMENTATION_EXTENSIONS
),
46 r
'.+profile_sync_service_harness%s' % _IMPLEMENTATION_EXTENSIONS
,
47 r
'.*[/\\](test|tool(s)?)[/\\].*',
48 # At request of folks maintaining this folder.
49 r
'chrome[/\\]browser[/\\]automation[/\\].*',
52 _TEST_ONLY_WARNING
= (
53 'You might be calling functions intended only for testing from\n'
54 'production code. It is OK to ignore this warning if you know what\n'
55 'you are doing, as the heuristics used to detect the situation are\n'
56 'not perfect. The commit queue will not block on this warning.\n'
57 'Email joi@chromium.org if you have questions.')
60 _INCLUDE_ORDER_WARNING
= (
61 'Your #include order seems to be broken. Send mail to\n'
62 'marja@chromium.org if this is not the case.')
65 _BANNED_OBJC_FUNCTIONS
= (
69 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
70 'prohibited. Please use CrTrackingArea instead.',
71 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
78 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
80 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
85 'convertPointFromBase:',
87 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
88 'Please use |convertPoint:(point) fromView:nil| instead.',
89 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
94 'convertPointToBase:',
96 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
97 'Please use |convertPoint:(point) toView:nil| instead.',
98 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
103 'convertRectFromBase:',
105 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
106 'Please use |convertRect:(point) fromView:nil| instead.',
107 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
112 'convertRectToBase:',
114 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
115 'Please use |convertRect:(point) toView:nil| instead.',
116 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
121 'convertSizeFromBase:',
123 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
124 'Please use |convertSize:(point) fromView:nil| instead.',
125 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
130 'convertSizeToBase:',
132 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
133 'Please use |convertSize:(point) toView:nil| instead.',
134 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
141 _BANNED_CPP_FUNCTIONS
= (
142 # Make sure that gtest's FRIEND_TEST() macro is not used; the
143 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
144 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
148 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
149 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
157 'New code should not use ScopedAllowIO. Post a task to the blocking',
158 'pool or the FILE thread instead.',
162 r
"^content[\\\/]shell[\\\/]shell_browser_main\.cc$",
168 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api
, output_api
):
169 """Attempts to prevent use of functions intended only for testing in
170 non-testing code. For now this is just a best-effort implementation
171 that ignores header files and may have some false positives. A
172 better implementation would probably need a proper C++ parser.
174 # We only scan .cc files and the like, as the declaration of
175 # for-testing functions in header files are hard to distinguish from
176 # calls to such functions without a proper C++ parser.
177 file_inclusion_pattern
= r
'.+%s' % _IMPLEMENTATION_EXTENSIONS
179 base_function_pattern
= r
'ForTest(ing)?|for_test(ing)?'
180 inclusion_pattern
= input_api
.re
.compile(r
'(%s)\s*\(' % base_function_pattern
)
181 exclusion_pattern
= input_api
.re
.compile(
182 r
'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
183 base_function_pattern
, base_function_pattern
))
185 def FilterFile(affected_file
):
186 black_list
= (_EXCLUDED_PATHS
+
187 _TEST_CODE_EXCLUDED_PATHS
+
188 input_api
.DEFAULT_BLACK_LIST
)
189 return input_api
.FilterSourceFile(
191 white_list
=(file_inclusion_pattern
, ),
192 black_list
=black_list
)
195 for f
in input_api
.AffectedSourceFiles(FilterFile
):
196 local_path
= f
.LocalPath()
197 lines
= input_api
.ReadFile(f
).splitlines()
200 if (inclusion_pattern
.search(line
) and
201 not exclusion_pattern
.search(line
)):
203 '%s:%d\n %s' % (local_path
, line_number
, line
.strip()))
207 if not input_api
.is_committing
:
208 return [output_api
.PresubmitPromptWarning(_TEST_ONLY_WARNING
, problems
)]
210 # We don't warn on commit, to avoid stopping commits going through CQ.
211 return [output_api
.PresubmitNotifyResult(_TEST_ONLY_WARNING
, problems
)]
216 def _CheckNoIOStreamInHeaders(input_api
, output_api
):
217 """Checks to make sure no .h files include <iostream>."""
219 pattern
= input_api
.re
.compile(r
'^#include\s*<iostream>',
220 input_api
.re
.MULTILINE
)
221 for f
in input_api
.AffectedSourceFiles(input_api
.FilterSourceFile
):
222 if not f
.LocalPath().endswith('.h'):
224 contents
= input_api
.ReadFile(f
)
225 if pattern
.search(contents
):
229 return [ output_api
.PresubmitError(
230 'Do not #include <iostream> in header files, since it inserts static '
231 'initialization into every file including the header. Instead, '
232 '#include <ostream>. See http://crbug.com/94794',
237 def _CheckNoUNIT_TESTInSourceFiles(input_api
, output_api
):
238 """Checks to make sure no source files use UNIT_TEST"""
240 for f
in input_api
.AffectedFiles():
241 if (not f
.LocalPath().endswith(('.cc', '.mm'))):
244 for line_num
, line
in f
.ChangedContents():
245 if 'UNIT_TEST' in line
:
246 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
250 return [output_api
.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
251 '\n'.join(problems
))]
254 def _CheckNoNewWStrings(input_api
, output_api
):
255 """Checks to make sure we don't introduce use of wstrings."""
257 for f
in input_api
.AffectedFiles():
258 if (not f
.LocalPath().endswith(('.cc', '.h')) or
259 f
.LocalPath().endswith('test.cc')):
263 for line_num
, line
in f
.ChangedContents():
264 if 'presubmit: allow wstring' in line
:
266 elif not allowWString
and 'wstring' in line
:
267 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
274 return [output_api
.PresubmitPromptWarning('New code should not use wstrings.'
275 ' If you are calling a cross-platform API that accepts a wstring, '
277 '\n'.join(problems
))]
280 def _CheckNoDEPSGIT(input_api
, output_api
):
281 """Make sure .DEPS.git is never modified manually."""
282 if any(f
.LocalPath().endswith('.DEPS.git') for f
in
283 input_api
.AffectedFiles()):
284 return [output_api
.PresubmitError(
285 'Never commit changes to .DEPS.git. This file is maintained by an\n'
286 'automated system based on what\'s in DEPS and your changes will be\n'
288 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n'
289 'for more information')]
293 def _CheckNoBannedFunctions(input_api
, output_api
):
294 """Make sure that banned functions are not used."""
298 file_filter
= lambda f
: f
.LocalPath().endswith(('.mm', '.m', '.h'))
299 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
300 for line_num
, line
in f
.ChangedContents():
301 for func_name
, message
, error
in _BANNED_OBJC_FUNCTIONS
:
302 if func_name
in line
:
306 problems
.append(' %s:%d:' % (f
.LocalPath(), line_num
))
307 for message_line
in message
:
308 problems
.append(' %s' % message_line
)
310 file_filter
= lambda f
: f
.LocalPath().endswith(('.cc', '.mm', '.h'))
311 for f
in input_api
.AffectedFiles(file_filter
=file_filter
):
312 for line_num
, line
in f
.ChangedContents():
313 for func_name
, message
, error
, excluded_paths
in _BANNED_CPP_FUNCTIONS
:
314 def IsBlacklisted(affected_file
, blacklist
):
315 local_path
= affected_file
.LocalPath()
316 for item
in blacklist
:
317 if input_api
.re
.match(item
, local_path
):
320 if IsBlacklisted(f
, excluded_paths
):
322 if func_name
in line
:
326 problems
.append(' %s:%d:' % (f
.LocalPath(), line_num
))
327 for message_line
in message
:
328 problems
.append(' %s' % message_line
)
332 result
.append(output_api
.PresubmitPromptWarning(
333 'Banned functions were used.\n' + '\n'.join(warnings
)))
335 result
.append(output_api
.PresubmitError(
336 'Banned functions were used.\n' + '\n'.join(errors
)))
340 def _CheckNoPragmaOnce(input_api
, output_api
):
341 """Make sure that banned functions are not used."""
343 pattern
= input_api
.re
.compile(r
'^#pragma\s+once',
344 input_api
.re
.MULTILINE
)
345 for f
in input_api
.AffectedSourceFiles(input_api
.FilterSourceFile
):
346 if not f
.LocalPath().endswith('.h'):
348 contents
= input_api
.ReadFile(f
)
349 if pattern
.search(contents
):
353 return [output_api
.PresubmitError(
354 'Do not use #pragma once in header files.\n'
355 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
360 def _CheckNoTrinaryTrueFalse(input_api
, output_api
):
361 """Checks to make sure we don't introduce use of foo ? true : false."""
363 pattern
= input_api
.re
.compile(r
'\?\s*(true|false)\s*:\s*(true|false)')
364 for f
in input_api
.AffectedFiles():
365 if not f
.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
368 for line_num
, line
in f
.ChangedContents():
369 if pattern
.match(line
):
370 problems
.append(' %s:%d' % (f
.LocalPath(), line_num
))
374 return [output_api
.PresubmitPromptWarning(
375 'Please consider avoiding the "? true : false" pattern if possible.\n' +
376 '\n'.join(problems
))]
379 def _CheckUnwantedDependencies(input_api
, output_api
):
380 """Runs checkdeps on #include statements added in this
381 change. Breaking - rules is an error, breaking ! rules is a
384 # We need to wait until we have an input_api object and use this
385 # roundabout construct to import checkdeps because this file is
386 # eval-ed and thus doesn't have __file__.
387 original_sys_path
= sys
.path
389 sys
.path
= sys
.path
+ [input_api
.os_path
.join(
390 input_api
.PresubmitLocalPath(), 'tools', 'checkdeps')]
392 from cpp_checker
import CppChecker
393 from rules
import Rule
395 # Restore sys.path to what it was before.
396 sys
.path
= original_sys_path
399 for f
in input_api
.AffectedFiles():
400 if not CppChecker
.IsCppFile(f
.LocalPath()):
403 changed_lines
= [line
for line_num
, line
in f
.ChangedContents()]
404 added_includes
.append([f
.LocalPath(), changed_lines
])
406 deps_checker
= checkdeps
.DepsChecker()
408 error_descriptions
= []
409 warning_descriptions
= []
410 for path
, rule_type
, rule_description
in deps_checker
.CheckAddedCppIncludes(
412 description_with_path
= '%s\n %s' % (path
, rule_description
)
413 if rule_type
== Rule
.DISALLOW
:
414 error_descriptions
.append(description_with_path
)
416 warning_descriptions
.append(description_with_path
)
419 if error_descriptions
:
420 results
.append(output_api
.PresubmitError(
421 'You added one or more #includes that violate checkdeps rules.',
423 if warning_descriptions
:
424 if not input_api
.is_committing
:
425 warning_factory
= output_api
.PresubmitPromptWarning
427 # We don't want to block use of the CQ when there is a warning
428 # of this kind, so we only show a message when committing.
429 warning_factory
= output_api
.PresubmitNotifyResult
430 results
.append(warning_factory(
431 'You added one or more #includes of files that are temporarily\n'
432 'allowed but being removed. Can you avoid introducing the\n'
433 '#include? See relevant DEPS file(s) for details and contacts.',
434 warning_descriptions
))
438 def _CheckFilePermissions(input_api
, output_api
):
439 """Check that all files have their permissions properly set."""
440 args
= [sys
.executable
, 'tools/checkperms/checkperms.py', '--root',
441 input_api
.change
.RepositoryRoot()]
442 for f
in input_api
.AffectedFiles():
443 args
+= ['--file', f
.LocalPath()]
445 (errors
, stderrdata
) = subprocess
.Popen(args
).communicate()
449 results
.append(output_api
.PresubmitError('checkperms.py failed.',
454 def _CheckNoAuraWindowPropertyHInHeaders(input_api
, output_api
):
455 """Makes sure we don't include ui/aura/window_property.h
458 pattern
= input_api
.re
.compile(r
'^#include\s*"ui/aura/window_property.h"')
460 for f
in input_api
.AffectedFiles():
461 if not f
.LocalPath().endswith('.h'):
463 for line_num
, line
in f
.ChangedContents():
464 if pattern
.match(line
):
465 errors
.append(' %s:%d' % (f
.LocalPath(), line_num
))
469 results
.append(output_api
.PresubmitError(
470 'Header files should not include ui/aura/window_property.h', errors
))
474 def _CheckIncludeOrderForScope(scope
, input_api
, file_path
, changed_linenums
):
475 """Checks that the lines in scope occur in the right order.
477 1. C system files in alphabetical order
478 2. C++ system files in alphabetical order
479 3. Project's .h files
482 c_system_include_pattern
= input_api
.re
.compile(r
'\s*#include <.*\.h>')
483 cpp_system_include_pattern
= input_api
.re
.compile(r
'\s*#include <.*>')
484 custom_include_pattern
= input_api
.re
.compile(r
'\s*#include ".*')
486 C_SYSTEM_INCLUDES
, CPP_SYSTEM_INCLUDES
, CUSTOM_INCLUDES
= range(3)
488 state
= C_SYSTEM_INCLUDES
491 previous_line_num
= 0
492 problem_linenums
= []
493 for line_num
, line
in scope
:
494 if c_system_include_pattern
.match(line
):
495 if state
!= C_SYSTEM_INCLUDES
:
496 problem_linenums
.append((line_num
, previous_line_num
))
497 elif previous_line
and previous_line
> line
:
498 problem_linenums
.append((line_num
, previous_line_num
))
499 elif cpp_system_include_pattern
.match(line
):
500 if state
== C_SYSTEM_INCLUDES
:
501 state
= CPP_SYSTEM_INCLUDES
502 elif state
== CUSTOM_INCLUDES
:
503 problem_linenums
.append((line_num
, previous_line_num
))
504 elif previous_line
and previous_line
> line
:
505 problem_linenums
.append((line_num
, previous_line_num
))
506 elif custom_include_pattern
.match(line
):
507 if state
!= CUSTOM_INCLUDES
:
508 state
= CUSTOM_INCLUDES
509 elif previous_line
and previous_line
> line
:
510 problem_linenums
.append((line_num
, previous_line_num
))
512 problem_linenums
.append(line_num
)
514 previous_line_num
= line_num
517 for (line_num
, previous_line_num
) in problem_linenums
:
518 if line_num
in changed_linenums
or previous_line_num
in changed_linenums
:
519 warnings
.append(' %s:%d' % (file_path
, line_num
))
523 def _CheckIncludeOrderInFile(input_api
, f
, changed_linenums
):
524 """Checks the #include order for the given file f."""
526 system_include_pattern
= input_api
.re
.compile(r
'\s*#include \<.*')
527 # Exclude #include <.../...> includes from the check; e.g., <sys/...> includes
528 # often need to appear in a specific order.
529 excluded_include_pattern
= input_api
.re
.compile(r
'\s*#include \<.*/.*')
530 custom_include_pattern
= input_api
.re
.compile(r
'\s*#include "(?P<FILE>.*)"')
531 if_pattern
= input_api
.re
.compile(
532 r
'\s*#\s*(if|elif|else|endif|define|undef).*')
533 # Some files need specialized order of includes; exclude such files from this
535 uncheckable_includes_pattern
= input_api
.re
.compile(
537 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
539 contents
= f
.NewContents()
543 # Handle the special first include. If the first include file is
544 # some/path/file.h, the corresponding including file can be some/path/file.cc,
545 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
546 # etc. It's also possible that no special first include exists.
547 for line
in contents
:
549 if system_include_pattern
.match(line
):
550 # No special first include -> process the line again along with normal
554 match
= custom_include_pattern
.match(line
)
556 match_dict
= match
.groupdict()
557 header_basename
= input_api
.os_path
.basename(
558 match_dict
['FILE']).replace('.h', '')
559 if header_basename
not in input_api
.os_path
.basename(f
.LocalPath()):
560 # No special first include -> process the line again along with normal
565 # Split into scopes: Each region between #if and #endif is its own scope.
568 for line
in contents
[line_num
:]:
570 if uncheckable_includes_pattern
.match(line
):
572 if if_pattern
.match(line
):
573 scopes
.append(current_scope
)
575 elif ((system_include_pattern
.match(line
) or
576 custom_include_pattern
.match(line
)) and
577 not excluded_include_pattern
.match(line
)):
578 current_scope
.append((line_num
, line
))
579 scopes
.append(current_scope
)
582 warnings
.extend(_CheckIncludeOrderForScope(scope
, input_api
, f
.LocalPath(),
587 def _CheckIncludeOrder(input_api
, output_api
):
588 """Checks that the #include order is correct.
590 1. The corresponding header for source files.
591 2. C system files in alphabetical order
592 3. C++ system files in alphabetical order
593 4. Project's .h files in alphabetical order
595 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
596 these rules separately.
600 for f
in input_api
.AffectedFiles():
601 if f
.LocalPath().endswith(('.cc', '.h')):
602 changed_linenums
= set(line_num
for line_num
, _
in f
.ChangedContents())
603 warnings
.extend(_CheckIncludeOrderInFile(input_api
, f
, changed_linenums
))
607 if not input_api
.is_committing
:
608 results
.append(output_api
.PresubmitPromptWarning(_INCLUDE_ORDER_WARNING
,
611 # We don't warn on commit, to avoid stopping commits going through CQ.
612 results
.append(output_api
.PresubmitNotifyResult(_INCLUDE_ORDER_WARNING
,
617 def _CheckForVersionControlConflictsInFile(input_api
, f
):
618 pattern
= input_api
.re
.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
620 for line_num
, line
in f
.ChangedContents():
621 if pattern
.match(line
):
622 errors
.append(' %s:%d %s' % (f
.LocalPath(), line_num
, line
))
626 def _CheckForVersionControlConflicts(input_api
, output_api
):
627 """Usually this is not intentional and will cause a compile failure."""
629 for f
in input_api
.AffectedFiles():
630 errors
.extend(_CheckForVersionControlConflictsInFile(input_api
, f
))
634 results
.append(output_api
.PresubmitError(
635 'Version control conflict markers found, please resolve.', errors
))
639 def _CheckHardcodedGoogleHostsInLowerLayers(input_api
, output_api
):
640 def FilterFile(affected_file
):
641 """Filter function for use with input_api.AffectedSourceFiles,
642 below. This filters out everything except non-test files from
643 top-level directories that generally speaking should not hard-code
644 service URLs (e.g. src/android_webview/, src/content/ and others).
646 return input_api
.FilterSourceFile(
648 white_list
=(r
'^(android_webview|base|content|net)[\\\/].*', ),
649 black_list
=(_EXCLUDED_PATHS
+
650 _TEST_CODE_EXCLUDED_PATHS
+
651 input_api
.DEFAULT_BLACK_LIST
))
653 pattern
= input_api
.re
.compile('"[^"]*google\.com[^"]*"')
654 problems
= [] # items are (filename, line_number, line)
655 for f
in input_api
.AffectedSourceFiles(FilterFile
):
656 for line_num
, line
in f
.ChangedContents():
657 if pattern
.search(line
):
658 problems
.append((f
.LocalPath(), line_num
, line
))
661 if not input_api
.is_committing
:
662 warning_factory
= output_api
.PresubmitPromptWarning
664 # We don't want to block use of the CQ when there is a warning
665 # of this kind, so we only show a message when committing.
666 warning_factory
= output_api
.PresubmitNotifyResult
667 return [warning_factory(
668 'Most layers below src/chrome/ should not hardcode service URLs.\n'
669 'Are you sure this is correct? (Contact: joi@chromium.org)',
671 problem
[0], problem
[1], problem
[2]) for problem
in problems
])]
676 def _CheckNoAbbreviationInPngFileName(input_api
, output_api
):
677 """Makes sure there are no abbreviations in the name of PNG files.
679 pattern
= input_api
.re
.compile(r
'.*_[a-z]_.*\.png$|.*_[a-z]\.png$')
681 for f
in input_api
.AffectedFiles(include_deletes
=False):
682 if pattern
.match(f
.LocalPath()):
683 errors
.append(' %s' % f
.LocalPath())
687 results
.append(output_api
.PresubmitError(
688 'The name of PNG files should not have abbreviations. \n'
689 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
690 'Contact oshima@chromium.org if you have questions.', errors
))
694 def _CommonChecks(input_api
, output_api
):
695 """Checks common to both upload and commit."""
697 results
.extend(input_api
.canned_checks
.PanProjectChecks(
698 input_api
, output_api
, excluded_paths
=_EXCLUDED_PATHS
))
699 results
.extend(_CheckAuthorizedAuthor(input_api
, output_api
))
701 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api
, output_api
))
702 results
.extend(_CheckNoIOStreamInHeaders(input_api
, output_api
))
703 results
.extend(_CheckNoUNIT_TESTInSourceFiles(input_api
, output_api
))
704 results
.extend(_CheckNoNewWStrings(input_api
, output_api
))
705 results
.extend(_CheckNoDEPSGIT(input_api
, output_api
))
706 results
.extend(_CheckNoBannedFunctions(input_api
, output_api
))
707 results
.extend(_CheckNoPragmaOnce(input_api
, output_api
))
708 results
.extend(_CheckNoTrinaryTrueFalse(input_api
, output_api
))
709 results
.extend(_CheckUnwantedDependencies(input_api
, output_api
))
710 results
.extend(_CheckFilePermissions(input_api
, output_api
))
711 results
.extend(_CheckNoAuraWindowPropertyHInHeaders(input_api
, output_api
))
712 results
.extend(_CheckIncludeOrder(input_api
, output_api
))
713 results
.extend(_CheckForVersionControlConflicts(input_api
, output_api
))
714 results
.extend(_CheckPatchFiles(input_api
, output_api
))
715 results
.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api
, output_api
))
716 results
.extend(_CheckNoAbbreviationInPngFileName(input_api
, output_api
))
718 if any('PRESUBMIT.py' == f
.LocalPath() for f
in input_api
.AffectedFiles()):
719 results
.extend(input_api
.canned_checks
.RunUnitTestsInDirectory(
720 input_api
, output_api
,
721 input_api
.PresubmitLocalPath(),
722 whitelist
=[r
'^PRESUBMIT_test\.py$']))
726 def _CheckSubversionConfig(input_api
, output_api
):
727 """Verifies the subversion config file is correctly setup.
729 Checks that autoprops are enabled, returns an error otherwise.
731 join
= input_api
.os_path
.join
732 if input_api
.platform
== 'win32':
733 appdata
= input_api
.environ
.get('APPDATA', '')
735 return [output_api
.PresubmitError('%APPDATA% is not configured.')]
736 path
= join(appdata
, 'Subversion', 'config')
738 home
= input_api
.environ
.get('HOME', '')
740 return [output_api
.PresubmitError('$HOME is not configured.')]
741 path
= join(home
, '.subversion', 'config')
744 'Please look at http://dev.chromium.org/developers/coding-style to\n'
745 'configure your subversion configuration file. This enables automatic\n'
746 'properties to simplify the project maintenance.\n'
747 'Pro-tip: just download and install\n'
748 'http://src.chromium.org/viewvc/chrome/trunk/tools/build/slave/config\n')
751 lines
= open(path
, 'r').read().splitlines()
752 # Make sure auto-props is enabled and check for 2 Chromium standard
754 if (not '*.cc = svn:eol-style=LF' in lines
or
755 not '*.pdf = svn:mime-type=application/pdf' in lines
or
756 not 'enable-auto-props = yes' in lines
):
758 output_api
.PresubmitNotifyResult(
759 'It looks like you have not configured your subversion config '
760 'file or it is not up-to-date.\n' + error_msg
)
762 except (OSError, IOError):
764 output_api
.PresubmitNotifyResult(
765 'Can\'t find your subversion config file.\n' + error_msg
)
770 def _CheckAuthorizedAuthor(input_api
, output_api
):
771 """For non-googler/chromites committers, verify the author's email address is
774 # TODO(maruel): Add it to input_api?
777 author
= input_api
.change
.author_email
779 input_api
.logging
.info('No author, skipping AUTHOR check')
781 authors_path
= input_api
.os_path
.join(
782 input_api
.PresubmitLocalPath(), 'AUTHORS')
784 input_api
.re
.match(r
'[^#]+\s+\<(.+?)\>\s*$', line
)
785 for line
in open(authors_path
))
786 valid_authors
= [item
.group(1).lower() for item
in valid_authors
if item
]
787 if not any(fnmatch
.fnmatch(author
.lower(), valid
) for valid
in valid_authors
):
788 input_api
.logging
.info('Valid authors are %s', ', '.join(valid_authors
))
789 return [output_api
.PresubmitPromptWarning(
790 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
792 'http://www.chromium.org/developers/contributing-code and read the '
794 'If you are a chromite, verify the contributor signed the CLA.') %
799 def _CheckPatchFiles(input_api
, output_api
):
800 problems
= [f
.LocalPath() for f
in input_api
.AffectedFiles()
801 if f
.LocalPath().endswith(('.orig', '.rej'))]
803 return [output_api
.PresubmitError(
804 "Don't commit .rej and .orig files.", problems
)]
809 def CheckChangeOnUpload(input_api
, output_api
):
811 results
.extend(_CommonChecks(input_api
, output_api
))
815 def CheckChangeOnCommit(input_api
, output_api
):
817 results
.extend(_CommonChecks(input_api
, output_api
))
818 # TODO(thestig) temporarily disabled, doesn't work in third_party/
819 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
820 # input_api, output_api, sources))
821 # Make sure the tree is 'open'.
822 results
.extend(input_api
.canned_checks
.CheckTreeIsOpen(
825 json_url
='http://chromium-status.appspot.com/current?format=json'))
826 results
.extend(input_api
.canned_checks
.CheckRietveldTryJobExecution(input_api
,
827 output_api
, 'http://codereview.chromium.org',
828 ('win_rel', 'linux_rel', 'mac_rel, win:compile'),
829 'tryserver@chromium.org'))
831 results
.extend(input_api
.canned_checks
.CheckChangeHasBugField(
832 input_api
, output_api
))
833 results
.extend(input_api
.canned_checks
.CheckChangeHasDescription(
834 input_api
, output_api
))
835 results
.extend(_CheckSubversionConfig(input_api
, output_api
))
839 def GetPreferredTrySlaves(project
, change
):
840 files
= change
.LocalPaths()
842 if not files
or all(re
.search(r
'[\\/]OWNERS$', f
) for f
in files
):
845 if all(re
.search('\.(m|mm)$|(^|[/_])mac[/_.]', f
) for f
in files
):
846 return ['mac_rel', 'mac_asan']
847 if all(re
.search('(^|[/_])win[/_.]', f
) for f
in files
):
849 if all(re
.search('(^|[/_])android[/_.]', f
) for f
in files
):
850 return ['android_dbg', 'android_clang_dbg']
851 if all(re
.search('^native_client_sdk', f
) for f
in files
):
852 return ['linux_nacl_sdk', 'win_nacl_sdk', 'mac_nacl_sdk']
853 if all(re
.search('[/_]ios[/_.]', f
) for f
in files
):
854 return ['ios_rel_device', 'ios_dbg_simulator']
864 'linux_clang:compile',
872 # Match things like path/aura/file.cc and path/file_aura.cc.
874 if any(re
.search('[/_](aura|chromeos)', f
) for f
in files
):
875 trybots
+= ['linux_chromeos_clang:compile', 'linux_chromeos_asan']