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 |