Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Top-level presubmit script for Chromium. | 5 """Top-level presubmit script for Chromium. |
| 6 | 6 |
| 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts | 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
| 8 for more details about the presubmit API built into gcl. | 8 for more details about the presubmit API built into gcl. |
| 9 """ | 9 """ |
| 10 | 10 |
| 11 | |
| 11 _EXCLUDED_PATHS = ( | 12 _EXCLUDED_PATHS = ( |
| 12 r"^breakpad[\\\/].*", | 13 r"^breakpad[\\\/].*", |
| 13 r"^net/tools/spdyshark/[\\\/].*", | 14 r"^net/tools/spdyshark/[\\\/].*", |
| 14 r"^skia[\\\/].*", | 15 r"^skia[\\\/].*", |
| 15 r"^v8[\\\/].*", | 16 r"^v8[\\\/].*", |
| 16 r".*MakeFile$", | 17 r".*MakeFile$", |
| 17 ) | 18 ) |
| 18 | 19 |
| 19 | 20 |
| 21 _TEST_ONLY_WARNING = ( | |
| 22 'You might be calling functions intended only for testing from\n' | |
| 23 'production code. It is OK to ignore this warning if you know what\n' | |
| 24 'you are doing, as the heuristics used to detect the situation are\n' | |
| 25 'not perfect. The commit queue will not block on this warning.\n' | |
| 26 'Email joi@chromium.org if you have questions.') | |
| 27 | |
| 28 | |
| 29 | |
| 20 def _CheckNoInterfacesInBase(input_api, output_api): | 30 def _CheckNoInterfacesInBase(input_api, output_api): |
| 21 """Checks to make sure no files in libbase.a have |@interface|.""" | 31 """Checks to make sure no files in libbase.a have |@interface|.""" |
| 22 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE) | 32 pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE) |
| 23 files = [] | 33 files = [] |
| 24 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): | 34 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): |
| 25 if (f.LocalPath().startswith('base/') and | 35 if (f.LocalPath().startswith('base/') and |
| 26 not f.LocalPath().endswith('_unittest.mm')): | 36 not f.LocalPath().endswith('_unittest.mm')): |
| 27 contents = input_api.ReadFile(f) | 37 contents = input_api.ReadFile(f) |
| 28 if pattern.search(contents): | 38 if pattern.search(contents): |
| 29 files.append(f) | 39 files.append(f) |
| 30 | 40 |
| 31 if len(files): | 41 if len(files): |
| 32 return [ output_api.PresubmitError( | 42 return [ output_api.PresubmitError( |
| 33 'Objective-C interfaces or categories are forbidden in libbase. ' + | 43 'Objective-C interfaces or categories are forbidden in libbase. ' + |
| 34 'See http://groups.google.com/a/chromium.org/group/chromium-dev/' + | 44 'See http://groups.google.com/a/chromium.org/group/chromium-dev/' + |
| 35 'browse_thread/thread/efb28c10435987fd', | 45 'browse_thread/thread/efb28c10435987fd', |
| 36 files) ] | 46 files) ] |
| 37 return [] | 47 return [] |
| 38 | 48 |
| 39 | 49 |
| 40 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api): | 50 def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, |
| 51 output_api, | |
| 52 committing): | |
| 41 """Attempts to prevent use of functions intended only for testing in | 53 """Attempts to prevent use of functions intended only for testing in |
| 42 non-testing code. For now this is just a best-effort implementation | 54 non-testing code. For now this is just a best-effort implementation |
| 43 that ignores header files and may have some false positives. A | 55 that ignores header files and may have some false positives. A |
| 44 better implementation would probably need a proper C++ parser. | 56 better implementation would probably need a proper C++ parser. |
| 45 """ | 57 """ |
| 46 # We only scan .cc files and the like, as the declaration of | 58 # We only scan .cc files and the like, as the declaration of |
| 47 # for-testing functions in header files are hard to distinguish from | 59 # for-testing functions in header files are hard to distinguish from |
| 48 # calls to such functions without a proper C++ parser. | 60 # calls to such functions without a proper C++ parser. |
| 49 source_extensions = r'\.(cc|cpp|cxx|mm)$' | 61 source_extensions = r'\.(cc|cpp|cxx|mm)$' |
| 50 file_inclusion_pattern = r'.+%s' % source_extensions | 62 file_inclusion_pattern = r'.+%s' % source_extensions |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 80 lines = input_api.ReadFile(f).splitlines() | 92 lines = input_api.ReadFile(f).splitlines() |
| 81 line_number = 0 | 93 line_number = 0 |
| 82 for line in lines: | 94 for line in lines: |
| 83 if (inclusion_pattern.search(line) and | 95 if (inclusion_pattern.search(line) and |
| 84 not exclusion_pattern.search(line)): | 96 not exclusion_pattern.search(line)): |
| 85 problems.append( | 97 problems.append( |
| 86 '%s:%d\n %s' % (local_path, line_number, line.strip())) | 98 '%s:%d\n %s' % (local_path, line_number, line.strip())) |
| 87 line_number += 1 | 99 line_number += 1 |
| 88 | 100 |
| 89 if problems: | 101 if problems: |
| 90 return [output_api.PresubmitPromptWarning( | 102 if not committing: |
|
M-A Ruel
2011/11/17 20:16:58
Use input_api.is_committing instead. It will simpl
| |
| 91 'You might be calling functions intended only for testing from\n' | 103 return [output_api.PresubmitPromptWarning(_TEST_ONLY_WARNING, problems)] |
| 92 'production code. Please verify that the following usages are OK,\n' | 104 else: |
| 93 'and email joi@chromium.org if you are seeing false positives:', | 105 # We don't warn on commit, to avoid stopping commits going through CQ. |
| 94 problems)] | 106 return [output_api.PresubmitNotifyResult(_TEST_ONLY_WARNING, problems)] |
| 95 else: | 107 else: |
| 96 return [] | 108 return [] |
| 97 | 109 |
| 98 | 110 |
| 99 def _CheckNoIOStreamInHeaders(input_api, output_api): | 111 def _CheckNoIOStreamInHeaders(input_api, output_api): |
| 100 """Checks to make sure no .h files include <iostream>.""" | 112 """Checks to make sure no .h files include <iostream>.""" |
| 101 files = [] | 113 files = [] |
| 102 pattern = input_api.re.compile(r'^#include\s*<iostream>', | 114 pattern = input_api.re.compile(r'^#include\s*<iostream>', |
| 103 input_api.re.MULTILINE) | 115 input_api.re.MULTILINE) |
| 104 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): | 116 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 142 input_api.AffectedFiles()): | 154 input_api.AffectedFiles()): |
| 143 return [output_api.PresubmitError( | 155 return [output_api.PresubmitError( |
| 144 'Never commit changes to .DEPS.git. This file is maintained by an\n' | 156 'Never commit changes to .DEPS.git. This file is maintained by an\n' |
| 145 'automated system based on what\'s in DEPS and your changes will be\n' | 157 'automated system based on what\'s in DEPS and your changes will be\n' |
| 146 'overwritten.\n' | 158 'overwritten.\n' |
| 147 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n' | 159 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n' |
| 148 'for more information')] | 160 'for more information')] |
| 149 return [] | 161 return [] |
| 150 | 162 |
| 151 | 163 |
| 152 def _CommonChecks(input_api, output_api): | 164 def _CommonChecks(input_api, output_api, committing=False): |
| 153 """Checks common to both upload and commit.""" | 165 """Checks common to both upload and commit.""" |
| 154 results = [] | 166 results = [] |
| 155 results.extend(input_api.canned_checks.PanProjectChecks( | 167 results.extend(input_api.canned_checks.PanProjectChecks( |
| 156 input_api, output_api, excluded_paths=_EXCLUDED_PATHS)) | 168 input_api, output_api, excluded_paths=_EXCLUDED_PATHS)) |
| 157 results.extend(_CheckNoInterfacesInBase(input_api, output_api)) | 169 results.extend(_CheckNoInterfacesInBase(input_api, output_api)) |
| 158 results.extend(_CheckAuthorizedAuthor(input_api, output_api)) | 170 results.extend(_CheckAuthorizedAuthor(input_api, output_api)) |
| 159 results.extend( | 171 results.extend( |
| 160 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api)) | 172 _CheckNoProductionCodeUsingTestOnlyFunctions( |
| 173 input_api, output_api, committing)) | |
| 161 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) | 174 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api)) |
| 162 results.extend(_CheckNoNewWStrings(input_api, output_api)) | 175 results.extend(_CheckNoNewWStrings(input_api, output_api)) |
| 163 results.extend(_CheckNoDEPSGIT(input_api, output_api)) | 176 results.extend(_CheckNoDEPSGIT(input_api, output_api)) |
| 164 return results | 177 return results |
| 165 | 178 |
| 166 | 179 |
| 167 def _CheckSubversionConfig(input_api, output_api): | 180 def _CheckSubversionConfig(input_api, output_api): |
| 168 """Verifies the subversion config file is correctly setup. | 181 """Verifies the subversion config file is correctly setup. |
| 169 | 182 |
| 170 Checks that autoprops are enabled, returns an error otherwise. | 183 Checks that autoprops are enabled, returns an error otherwise. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 | 252 |
| 240 | 253 |
| 241 def CheckChangeOnUpload(input_api, output_api): | 254 def CheckChangeOnUpload(input_api, output_api): |
| 242 results = [] | 255 results = [] |
| 243 results.extend(_CommonChecks(input_api, output_api)) | 256 results.extend(_CommonChecks(input_api, output_api)) |
| 244 return results | 257 return results |
| 245 | 258 |
| 246 | 259 |
| 247 def CheckChangeOnCommit(input_api, output_api): | 260 def CheckChangeOnCommit(input_api, output_api): |
| 248 results = [] | 261 results = [] |
| 249 results.extend(_CommonChecks(input_api, output_api)) | 262 results.extend(_CommonChecks(input_api, output_api, committing=True)) |
| 250 # TODO(thestig) temporarily disabled, doesn't work in third_party/ | 263 # TODO(thestig) temporarily disabled, doesn't work in third_party/ |
| 251 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories( | 264 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories( |
| 252 # input_api, output_api, sources)) | 265 # input_api, output_api, sources)) |
| 253 # Make sure the tree is 'open'. | 266 # Make sure the tree is 'open'. |
| 254 results.extend(input_api.canned_checks.CheckTreeIsOpen( | 267 results.extend(input_api.canned_checks.CheckTreeIsOpen( |
| 255 input_api, | 268 input_api, |
| 256 output_api, | 269 output_api, |
| 257 json_url='http://chromium-status.appspot.com/current?format=json')) | 270 json_url='http://chromium-status.appspot.com/current?format=json')) |
| 258 results.extend(input_api.canned_checks.CheckRietveldTryJobExecution(input_api, | 271 results.extend(input_api.canned_checks.CheckRietveldTryJobExecution(input_api, |
| 259 output_api, 'http://codereview.chromium.org', ('win', 'linux', 'mac'), | 272 output_api, 'http://codereview.chromium.org', ('win', 'linux', 'mac'), |
| 260 'tryserver@chromium.org')) | 273 'tryserver@chromium.org')) |
| 261 | 274 |
| 262 results.extend(input_api.canned_checks.CheckChangeHasBugField( | 275 results.extend(input_api.canned_checks.CheckChangeHasBugField( |
| 263 input_api, output_api)) | 276 input_api, output_api)) |
| 264 results.extend(input_api.canned_checks.CheckChangeHasTestField( | 277 results.extend(input_api.canned_checks.CheckChangeHasTestField( |
| 265 input_api, output_api)) | 278 input_api, output_api)) |
| 266 results.extend(_CheckSubversionConfig(input_api, output_api)) | 279 results.extend(_CheckSubversionConfig(input_api, output_api)) |
| 267 return results | 280 return results |
| 268 | 281 |
| 269 | 282 |
| 270 def GetPreferredTrySlaves(project, change): | 283 def GetPreferredTrySlaves(project, change): |
| 271 only_objc_files = all( | 284 only_objc_files = all( |
| 272 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles()) | 285 f.LocalPath().endswith(('.mm', '.m')) for f in change.AffectedFiles()) |
| 273 if only_objc_files: | 286 if only_objc_files: |
| 274 return ['mac'] | 287 return ['mac'] |
| 275 return ['win', 'linux', 'mac'] | 288 return ['win', 'linux', 'mac'] |
| OLD | NEW |