blob: c671419ab143a05e7e010c494882c3bcf6d4b936 [file] [log] [blame]
[email protected]a18130a2012-01-03 17:52:081# Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ca8d1982009-02-19 16:33:122# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Top-level presubmit script for Chromium.
6
[email protected]f1293792009-07-31 18:09:567See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
[email protected]50d7d721e2009-11-15 17:56:188for more details about the presubmit API built into gcl.
[email protected]ca8d1982009-02-19 16:33:129"""
10
[email protected]eea609a2011-11-18 13:10:1211
[email protected]9d16ad12011-12-14 20:49:4712import re
[email protected]fbcafe5a2012-08-08 15:31:2213import subprocess
[email protected]55f9f382012-07-31 11:02:1814import sys
[email protected]9d16ad12011-12-14 20:49:4715
16
[email protected]379e7dd2010-01-28 17:39:2117_EXCLUDED_PATHS = (
[email protected]3e4eb112011-01-18 03:29:5418 r"^breakpad[\\\/].*",
[email protected]40d1dbb2012-10-26 07:18:0019 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_rules.py",
20 r"^native_client_sdk[\\\/]src[\\\/]build_tools[\\\/]make_simple.py",
[email protected]a18130a2012-01-03 17:52:0821 r"^net[\\\/]tools[\\\/]spdyshark[\\\/].*",
[email protected]3e4eb112011-01-18 03:29:5422 r"^skia[\\\/].*",
23 r"^v8[\\\/].*",
24 r".*MakeFile$",
[email protected]1084ccc2012-03-14 03:22:5325 r".+_autogen\.h$",
[email protected]94f206c12012-08-25 00:09:1426 r"^cc[\\\/].*",
[email protected]39849c6c2012-09-14 22:15:5927 r"^webkit[\\\/]compositor_bindings[\\\/].*",
[email protected]ce145c02012-09-06 09:49:3428 r".+[\\\/]pnacl_shim\.c$",
[email protected]4306417642009-06-11 00:33:4029)
[email protected]ca8d1982009-02-19 16:33:1230
[email protected]ca8d1982009-02-19 16:33:1231
[email protected]eea609a2011-11-18 13:10:1232_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 [email protected] if you have questions.')
38
39
[email protected]127f18ec2012-06-16 05:05:5940_BANNED_OBJC_FUNCTIONS = (
41 (
42 'addTrackingRect:',
[email protected]23e6cbc2012-06-16 18:51:2043 (
44 'The use of -[NSView addTrackingRect:owner:userData:assumeInside:] is'
[email protected]127f18ec2012-06-16 05:05:5945 'prohibited. Please use CrTrackingArea instead.',
46 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
47 ),
48 False,
49 ),
50 (
51 'NSTrackingArea',
[email protected]23e6cbc2012-06-16 18:51:2052 (
53 'The use of NSTrackingAreas is prohibited. Please use CrTrackingArea',
[email protected]127f18ec2012-06-16 05:05:5954 'instead.',
55 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
56 ),
57 False,
58 ),
59 (
60 'convertPointFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2061 (
62 'The use of -[NSView convertPointFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5963 'Please use |convertPoint:(point) fromView:nil| instead.',
64 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
65 ),
66 True,
67 ),
68 (
69 'convertPointToBase:',
[email protected]23e6cbc2012-06-16 18:51:2070 (
71 'The use of -[NSView convertPointToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5972 'Please use |convertPoint:(point) toView:nil| instead.',
73 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
74 ),
75 True,
76 ),
77 (
78 'convertRectFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2079 (
80 'The use of -[NSView convertRectFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5981 'Please use |convertRect:(point) fromView:nil| instead.',
82 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
83 ),
84 True,
85 ),
86 (
87 'convertRectToBase:',
[email protected]23e6cbc2012-06-16 18:51:2088 (
89 'The use of -[NSView convertRectToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5990 'Please use |convertRect:(point) toView:nil| instead.',
91 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
92 ),
93 True,
94 ),
95 (
96 'convertSizeFromBase:',
[email protected]23e6cbc2012-06-16 18:51:2097 (
98 'The use of -[NSView convertSizeFromBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:5999 'Please use |convertSize:(point) fromView:nil| instead.',
100 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
101 ),
102 True,
103 ),
104 (
105 'convertSizeToBase:',
[email protected]23e6cbc2012-06-16 18:51:20106 (
107 'The use of -[NSView convertSizeToBase:] is almost certainly wrong.',
[email protected]127f18ec2012-06-16 05:05:59108 'Please use |convertSize:(point) toView:nil| instead.',
109 'http://dev.chromium.org/developers/coding-style/cocoa-dos-and-donts',
110 ),
111 True,
112 ),
113)
114
115
116_BANNED_CPP_FUNCTIONS = (
[email protected]23e6cbc2012-06-16 18:51:20117 # Make sure that gtest's FRIEND_TEST() macro is not used; the
118 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
119 # used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes.
120 (
121 'FRIEND_TEST(',
122 (
[email protected]e3c945502012-06-26 20:01:49123 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
[email protected]23e6cbc2012-06-16 18:51:20124 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
125 ),
126 False,
127 ),
128 (
129 'ScopedAllowIO',
130 (
[email protected]e3c945502012-06-26 20:01:49131 'New code should not use ScopedAllowIO. Post a task to the blocking',
132 'pool or the FILE thread instead.',
[email protected]23e6cbc2012-06-16 18:51:20133 ),
[email protected]e3c945502012-06-26 20:01:49134 True,
[email protected]23e6cbc2012-06-16 18:51:20135 ),
136 (
137 'FilePathWatcher::Delegate',
138 (
[email protected]e3c945502012-06-26 20:01:49139 'New code should not use FilePathWatcher::Delegate. Use the callback',
[email protected]23e6cbc2012-06-16 18:51:20140 'interface instead.',
141 ),
142 False,
143 ),
[email protected]e3c945502012-06-26 20:01:49144 (
145 'browser::FindLastActiveWithProfile',
146 (
147 'This function is deprecated and we\'re working on removing it. Pass',
148 'more context to get a Browser*, like a WebContents, window, or session',
149 'id. Talk to ben@ or jam@ for more information.',
150 ),
151 True,
152 ),
153 (
[email protected]e3c945502012-06-26 20:01:49154 'browser::FindAnyBrowser',
155 (
156 'This function is deprecated and we\'re working on removing it. Pass',
157 'more context to get a Browser*, like a WebContents, window, or session',
158 'id. Talk to ben@ or jam@ for more information.',
159 ),
160 True,
161 ),
162 (
163 'browser::FindOrCreateTabbedBrowser',
164 (
165 'This function is deprecated and we\'re working on removing it. Pass',
166 'more context to get a Browser*, like a WebContents, window, or session',
167 'id. Talk to ben@ or jam@ for more information.',
168 ),
169 True,
170 ),
171 (
172 'browser::FindTabbedBrowser',
173 (
174 'This function is deprecated and we\'re working on removing it. Pass',
175 'more context to get a Browser*, like a WebContents, window, or session',
176 'id. Talk to ben@ or jam@ for more information.',
177 ),
178 True,
179 ),
[email protected]127f18ec2012-06-16 05:05:59180)
181
182
[email protected]eea609a2011-11-18 13:10:12183
[email protected]55459852011-08-10 15:17:19184def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
185 """Attempts to prevent use of functions intended only for testing in
186 non-testing code. For now this is just a best-effort implementation
187 that ignores header files and may have some false positives. A
188 better implementation would probably need a proper C++ parser.
189 """
190 # We only scan .cc files and the like, as the declaration of
191 # for-testing functions in header files are hard to distinguish from
192 # calls to such functions without a proper C++ parser.
[email protected]403bfbc92012-06-11 23:30:09193 platform_specifiers = r'(_(android|chromeos|gtk|mac|posix|win))?'
[email protected]55459852011-08-10 15:17:19194 source_extensions = r'\.(cc|cpp|cxx|mm)$'
195 file_inclusion_pattern = r'.+%s' % source_extensions
[email protected]19e77fd2011-10-20 05:24:05196 file_exclusion_patterns = (
[email protected]e21ce382012-01-04 18:48:25197 r'.*[/\\](test_|mock_).+%s' % source_extensions,
[email protected]c762d252012-02-28 02:07:24198 r'.+_test_(base|support|util)%s' % source_extensions,
[email protected]403bfbc92012-06-11 23:30:09199 r'.+_(api|browser|perf|unit|ui)?test%s%s' % (platform_specifiers,
200 source_extensions),
[email protected]19e77fd2011-10-20 05:24:05201 r'.+profile_sync_service_harness%s' % source_extensions,
202 )
203 path_exclusion_patterns = (
204 r'.*[/\\](test|tool(s)?)[/\\].*',
205 # At request of folks maintaining this folder.
206 r'chrome[/\\]browser[/\\]automation[/\\].*',
207 )
[email protected]55459852011-08-10 15:17:19208
209 base_function_pattern = r'ForTest(ing)?|for_test(ing)?'
210 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
211 exclusion_pattern = input_api.re.compile(
212 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
213 base_function_pattern, base_function_pattern))
214
215 def FilterFile(affected_file):
[email protected]19e77fd2011-10-20 05:24:05216 black_list = (file_exclusion_patterns + path_exclusion_patterns +
[email protected]3afb12a42011-08-15 13:48:33217 _EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
[email protected]55459852011-08-10 15:17:19218 return input_api.FilterSourceFile(
219 affected_file,
220 white_list=(file_inclusion_pattern, ),
221 black_list=black_list)
222
223 problems = []
224 for f in input_api.AffectedSourceFiles(FilterFile):
225 local_path = f.LocalPath()
226 lines = input_api.ReadFile(f).splitlines()
227 line_number = 0
228 for line in lines:
229 if (inclusion_pattern.search(line) and
230 not exclusion_pattern.search(line)):
231 problems.append(
232 '%s:%d\n %s' % (local_path, line_number, line.strip()))
233 line_number += 1
234
235 if problems:
[email protected]eea609a2011-11-18 13:10:12236 if not input_api.is_committing:
237 return [output_api.PresubmitPromptWarning(_TEST_ONLY_WARNING, problems)]
238 else:
239 # We don't warn on commit, to avoid stopping commits going through CQ.
240 return [output_api.PresubmitNotifyResult(_TEST_ONLY_WARNING, problems)]
[email protected]55459852011-08-10 15:17:19241 else:
242 return []
243
244
[email protected]10689ca2011-09-02 02:31:54245def _CheckNoIOStreamInHeaders(input_api, output_api):
246 """Checks to make sure no .h files include <iostream>."""
247 files = []
248 pattern = input_api.re.compile(r'^#include\s*<iostream>',
249 input_api.re.MULTILINE)
250 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
251 if not f.LocalPath().endswith('.h'):
252 continue
253 contents = input_api.ReadFile(f)
254 if pattern.search(contents):
255 files.append(f)
256
257 if len(files):
258 return [ output_api.PresubmitError(
[email protected]6c063c62012-07-11 19:11:06259 'Do not #include <iostream> in header files, since it inserts static '
260 'initialization into every file including the header. Instead, '
[email protected]10689ca2011-09-02 02:31:54261 '#include <ostream>. See http://crbug.com/94794',
262 files) ]
263 return []
264
265
[email protected]72df4e782012-06-21 16:28:18266def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
267 """Checks to make sure no source files use UNIT_TEST"""
268 problems = []
269 for f in input_api.AffectedFiles():
270 if (not f.LocalPath().endswith(('.cc', '.mm'))):
271 continue
272
273 for line_num, line in f.ChangedContents():
274 if 'UNIT_TEST' in line:
275 problems.append(' %s:%d' % (f.LocalPath(), line_num))
276
277 if not problems:
278 return []
279 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
280 '\n'.join(problems))]
281
282
[email protected]8ea5d4b2011-09-13 21:49:22283def _CheckNoNewWStrings(input_api, output_api):
284 """Checks to make sure we don't introduce use of wstrings."""
[email protected]55463aa62011-10-12 00:48:27285 problems = []
[email protected]8ea5d4b2011-09-13 21:49:22286 for f in input_api.AffectedFiles():
[email protected]b5c24292011-11-28 14:38:20287 if (not f.LocalPath().endswith(('.cc', '.h')) or
288 f.LocalPath().endswith('test.cc')):
289 continue
[email protected]8ea5d4b2011-09-13 21:49:22290
[email protected]a11dbe9b2012-08-07 01:32:58291 allowWString = False
[email protected]b5c24292011-11-28 14:38:20292 for line_num, line in f.ChangedContents():
[email protected]a11dbe9b2012-08-07 01:32:58293 if 'presubmit: allow wstring' in line:
294 allowWString = True
295 elif not allowWString and 'wstring' in line:
[email protected]55463aa62011-10-12 00:48:27296 problems.append(' %s:%d' % (f.LocalPath(), line_num))
[email protected]a11dbe9b2012-08-07 01:32:58297 allowWString = False
298 else:
299 allowWString = False
[email protected]8ea5d4b2011-09-13 21:49:22300
[email protected]55463aa62011-10-12 00:48:27301 if not problems:
302 return []
303 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
[email protected]a11dbe9b2012-08-07 01:32:58304 ' If you are calling a cross-platform API that accepts a wstring, '
305 'fix the API.\n' +
[email protected]55463aa62011-10-12 00:48:27306 '\n'.join(problems))]
[email protected]8ea5d4b2011-09-13 21:49:22307
308
[email protected]2a8ac9c2011-10-19 17:20:44309def _CheckNoDEPSGIT(input_api, output_api):
310 """Make sure .DEPS.git is never modified manually."""
311 if any(f.LocalPath().endswith('.DEPS.git') for f in
312 input_api.AffectedFiles()):
313 return [output_api.PresubmitError(
314 'Never commit changes to .DEPS.git. This file is maintained by an\n'
315 'automated system based on what\'s in DEPS and your changes will be\n'
316 'overwritten.\n'
317 'See http://code.google.com/p/chromium/wiki/UsingNewGit#Rolling_DEPS\n'
318 'for more information')]
319 return []
320
321
[email protected]127f18ec2012-06-16 05:05:59322def _CheckNoBannedFunctions(input_api, output_api):
323 """Make sure that banned functions are not used."""
324 warnings = []
325 errors = []
326
327 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h'))
328 for f in input_api.AffectedFiles(file_filter=file_filter):
329 for line_num, line in f.ChangedContents():
330 for func_name, message, error in _BANNED_OBJC_FUNCTIONS:
331 if func_name in line:
332 problems = warnings;
333 if error:
334 problems = errors;
335 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
336 for message_line in message:
337 problems.append(' %s' % message_line)
338
339 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
340 for f in input_api.AffectedFiles(file_filter=file_filter):
341 for line_num, line in f.ChangedContents():
342 for func_name, message, error in _BANNED_CPP_FUNCTIONS:
343 if func_name in line:
344 problems = warnings;
345 if error:
346 problems = errors;
347 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
348 for message_line in message:
349 problems.append(' %s' % message_line)
350
351 result = []
352 if (warnings):
353 result.append(output_api.PresubmitPromptWarning(
354 'Banned functions were used.\n' + '\n'.join(warnings)))
355 if (errors):
356 result.append(output_api.PresubmitError(
357 'Banned functions were used.\n' + '\n'.join(errors)))
358 return result
359
360
[email protected]6c063c62012-07-11 19:11:06361def _CheckNoPragmaOnce(input_api, output_api):
362 """Make sure that banned functions are not used."""
363 files = []
364 pattern = input_api.re.compile(r'^#pragma\s+once',
365 input_api.re.MULTILINE)
366 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
367 if not f.LocalPath().endswith('.h'):
368 continue
369 contents = input_api.ReadFile(f)
370 if pattern.search(contents):
371 files.append(f)
372
373 if files:
374 return [output_api.PresubmitError(
375 'Do not use #pragma once in header files.\n'
376 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
377 files)]
378 return []
379
[email protected]127f18ec2012-06-16 05:05:59380
[email protected]e7479052012-09-19 00:26:12381def _CheckNoTrinaryTrueFalse(input_api, output_api):
382 """Checks to make sure we don't introduce use of foo ? true : false."""
383 problems = []
384 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
385 for f in input_api.AffectedFiles():
386 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
387 continue
388
389 for line_num, line in f.ChangedContents():
390 if pattern.match(line):
391 problems.append(' %s:%d' % (f.LocalPath(), line_num))
392
393 if not problems:
394 return []
395 return [output_api.PresubmitPromptWarning(
396 'Please consider avoiding the "? true : false" pattern if possible.\n' +
397 '\n'.join(problems))]
398
399
[email protected]55f9f382012-07-31 11:02:18400def _CheckUnwantedDependencies(input_api, output_api):
401 """Runs checkdeps on #include statements added in this
402 change. Breaking - rules is an error, breaking ! rules is a
403 warning.
404 """
405 # We need to wait until we have an input_api object and use this
406 # roundabout construct to import checkdeps because this file is
407 # eval-ed and thus doesn't have __file__.
408 original_sys_path = sys.path
409 try:
410 sys.path = sys.path + [input_api.os_path.join(
411 input_api.PresubmitLocalPath(), 'tools', 'checkdeps')]
412 import checkdeps
413 from cpp_checker import CppChecker
414 from rules import Rule
415 finally:
416 # Restore sys.path to what it was before.
417 sys.path = original_sys_path
418
419 added_includes = []
420 for f in input_api.AffectedFiles():
421 if not CppChecker.IsCppFile(f.LocalPath()):
422 continue
423
424 changed_lines = [line for line_num, line in f.ChangedContents()]
425 added_includes.append([f.LocalPath(), changed_lines])
426
427 deps_checker = checkdeps.DepsChecker()
428
429 error_descriptions = []
430 warning_descriptions = []
431 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
432 added_includes):
433 description_with_path = '%s\n %s' % (path, rule_description)
434 if rule_type == Rule.DISALLOW:
435 error_descriptions.append(description_with_path)
436 else:
437 warning_descriptions.append(description_with_path)
438
439 results = []
440 if error_descriptions:
441 results.append(output_api.PresubmitError(
442 'You added one or more #includes that violate checkdeps rules.',
443 error_descriptions))
444 if warning_descriptions:
[email protected]779caa52012-08-21 17:05:59445 if not input_api.is_committing:
446 warning_factory = output_api.PresubmitPromptWarning
447 else:
448 # We don't want to block use of the CQ when there is a warning
449 # of this kind, so we only show a message when committing.
450 warning_factory = output_api.PresubmitNotifyResult
451 results.append(warning_factory(
[email protected]55f9f382012-07-31 11:02:18452 'You added one or more #includes of files that are temporarily\n'
453 'allowed but being removed. Can you avoid introducing the\n'
454 '#include? See relevant DEPS file(s) for details and contacts.',
455 warning_descriptions))
456 return results
457
458
[email protected]fbcafe5a2012-08-08 15:31:22459def _CheckFilePermissions(input_api, output_api):
460 """Check that all files have their permissions properly set."""
461 args = [sys.executable, 'tools/checkperms/checkperms.py', '--root',
462 input_api.change.RepositoryRoot()]
463 for f in input_api.AffectedFiles():
464 args += ['--file', f.LocalPath()]
465 errors = []
466 (errors, stderrdata) = subprocess.Popen(args).communicate()
467
468 results = []
469 if errors:
470 results.append(output_api.PreSubmitError('checkperms.py failed.',
471 errors))
472 return results
473
474
[email protected]22c9bd72011-03-27 16:47:39475def _CommonChecks(input_api, output_api):
476 """Checks common to both upload and commit."""
477 results = []
478 results.extend(input_api.canned_checks.PanProjectChecks(
479 input_api, output_api, excluded_paths=_EXCLUDED_PATHS))
[email protected]66daa702011-05-28 14:41:46480 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
[email protected]55459852011-08-10 15:17:19481 results.extend(
482 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
[email protected]10689ca2011-09-02 02:31:54483 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
[email protected]72df4e782012-06-21 16:28:18484 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
[email protected]8ea5d4b2011-09-13 21:49:22485 results.extend(_CheckNoNewWStrings(input_api, output_api))
[email protected]2a8ac9c2011-10-19 17:20:44486 results.extend(_CheckNoDEPSGIT(input_api, output_api))
[email protected]127f18ec2012-06-16 05:05:59487 results.extend(_CheckNoBannedFunctions(input_api, output_api))
[email protected]6c063c62012-07-11 19:11:06488 results.extend(_CheckNoPragmaOnce(input_api, output_api))
[email protected]e7479052012-09-19 00:26:12489 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
[email protected]55f9f382012-07-31 11:02:18490 results.extend(_CheckUnwantedDependencies(input_api, output_api))
[email protected]fbcafe5a2012-08-08 15:31:22491 results.extend(_CheckFilePermissions(input_api, output_api))
[email protected]22c9bd72011-03-27 16:47:39492 return results
[email protected]1f7b4172010-01-28 01:17:34493
[email protected]b337cb5b2011-01-23 21:24:05494
495def _CheckSubversionConfig(input_api, output_api):
496 """Verifies the subversion config file is correctly setup.
497
498 Checks that autoprops are enabled, returns an error otherwise.
499 """
500 join = input_api.os_path.join
501 if input_api.platform == 'win32':
502 appdata = input_api.environ.get('APPDATA', '')
503 if not appdata:
504 return [output_api.PresubmitError('%APPDATA% is not configured.')]
505 path = join(appdata, 'Subversion', 'config')
506 else:
507 home = input_api.environ.get('HOME', '')
508 if not home:
509 return [output_api.PresubmitError('$HOME is not configured.')]
510 path = join(home, '.subversion', 'config')
511
512 error_msg = (
513 'Please look at http://dev.chromium.org/developers/coding-style to\n'
514 'configure your subversion configuration file. This enables automatic\n'
[email protected]c6a3c10b2011-01-24 16:14:20515 'properties to simplify the project maintenance.\n'
516 'Pro-tip: just download and install\n'
517 'http://src.chromium.org/viewvc/chrome/trunk/tools/build/slave/config\n')
[email protected]b337cb5b2011-01-23 21:24:05518
519 try:
520 lines = open(path, 'r').read().splitlines()
521 # Make sure auto-props is enabled and check for 2 Chromium standard
522 # auto-prop.
523 if (not '*.cc = svn:eol-style=LF' in lines or
524 not '*.pdf = svn:mime-type=application/pdf' in lines or
525 not 'enable-auto-props = yes' in lines):
526 return [
[email protected]79ed7e62011-02-21 21:08:53527 output_api.PresubmitNotifyResult(
[email protected]b337cb5b2011-01-23 21:24:05528 'It looks like you have not configured your subversion config '
[email protected]b5359c02011-02-01 20:29:56529 'file or it is not up-to-date.\n' + error_msg)
[email protected]b337cb5b2011-01-23 21:24:05530 ]
531 except (OSError, IOError):
532 return [
[email protected]79ed7e62011-02-21 21:08:53533 output_api.PresubmitNotifyResult(
[email protected]b337cb5b2011-01-23 21:24:05534 'Can\'t find your subversion config file.\n' + error_msg)
535 ]
536 return []
537
538
[email protected]66daa702011-05-28 14:41:46539def _CheckAuthorizedAuthor(input_api, output_api):
540 """For non-googler/chromites committers, verify the author's email address is
541 in AUTHORS.
542 """
[email protected]9bb9cb82011-06-13 20:43:01543 # TODO(maruel): Add it to input_api?
544 import fnmatch
545
[email protected]66daa702011-05-28 14:41:46546 author = input_api.change.author_email
[email protected]9bb9cb82011-06-13 20:43:01547 if not author:
548 input_api.logging.info('No author, skipping AUTHOR check')
[email protected]66daa702011-05-28 14:41:46549 return []
[email protected]c99663292011-05-31 19:46:08550 authors_path = input_api.os_path.join(
[email protected]66daa702011-05-28 14:41:46551 input_api.PresubmitLocalPath(), 'AUTHORS')
552 valid_authors = (
553 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
554 for line in open(authors_path))
[email protected]ac54b132011-06-06 18:11:18555 valid_authors = [item.group(1).lower() for item in valid_authors if item]
[email protected]9bb9cb82011-06-13 20:43:01556 if input_api.verbose:
557 print 'Valid authors are %s' % ', '.join(valid_authors)
[email protected]d8b50be2011-06-15 14:19:44558 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
[email protected]66daa702011-05-28 14:41:46559 return [output_api.PresubmitPromptWarning(
560 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
561 '\n'
562 'http://www.chromium.org/developers/contributing-code and read the '
563 '"Legal" section\n'
564 'If you are a chromite, verify the contributor signed the CLA.') %
565 author)]
566 return []
567
568
[email protected]1f7b4172010-01-28 01:17:34569def CheckChangeOnUpload(input_api, output_api):
570 results = []
571 results.extend(_CommonChecks(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:54572 return results
[email protected]ca8d1982009-02-19 16:33:12573
574
575def CheckChangeOnCommit(input_api, output_api):
[email protected]fe5f57c52009-06-05 14:25:54576 results = []
[email protected]1f7b4172010-01-28 01:17:34577 results.extend(_CommonChecks(input_api, output_api))
[email protected]dd805fe2009-10-01 08:11:51578 # TODO(thestig) temporarily disabled, doesn't work in third_party/
579 #results.extend(input_api.canned_checks.CheckSvnModifiedDirectories(
580 # input_api, output_api, sources))
[email protected]fe5f57c52009-06-05 14:25:54581 # Make sure the tree is 'open'.
[email protected]806e98e2010-03-19 17:49:27582 results.extend(input_api.canned_checks.CheckTreeIsOpen(
[email protected]7f238152009-08-12 19:00:34583 input_api,
584 output_api,
[email protected]4efa42142010-08-26 01:29:26585 json_url='http://chromium-status.appspot.com/current?format=json'))
[email protected]806e98e2010-03-19 17:49:27586 results.extend(input_api.canned_checks.CheckRietveldTryJobExecution(input_api,
[email protected]4ddc5df2011-12-12 03:05:04587 output_api, 'http://codereview.chromium.org',
[email protected]c1ba4c52012-03-09 14:23:28588 ('win_rel', 'linux_rel', 'mac_rel, win:compile'),
589 '[email protected]'))
[email protected]806e98e2010-03-19 17:49:27590
[email protected]3e4eb112011-01-18 03:29:54591 results.extend(input_api.canned_checks.CheckChangeHasBugField(
592 input_api, output_api))
[email protected]c4b47562011-12-05 23:39:41593 results.extend(input_api.canned_checks.CheckChangeHasDescription(
594 input_api, output_api))
[email protected]b337cb5b2011-01-23 21:24:05595 results.extend(_CheckSubversionConfig(input_api, output_api))
[email protected]fe5f57c52009-06-05 14:25:54596 return results
[email protected]ca8d1982009-02-19 16:33:12597
598
[email protected]5efb2a822011-09-27 23:06:13599def GetPreferredTrySlaves(project, change):
[email protected]4ce995ea2012-06-27 02:13:10600 files = change.LocalPaths()
601
[email protected]3019c902012-06-29 00:09:03602 if not files:
603 return []
604
[email protected]d668899a2012-09-06 18:16:59605 if all(re.search('\.(m|mm)$|(^|[/_])mac[/_.]', f) for f in files):
[email protected]641f2e3e2012-09-03 11:16:24606 return ['mac_rel', 'mac_asan']
[email protected]d668899a2012-09-06 18:16:59607 if all(re.search('(^|[/_])win[/_.]', f) for f in files):
[email protected]4ce995ea2012-06-27 02:13:10608 return ['win_rel']
[email protected]d668899a2012-09-06 18:16:59609 if all(re.search('(^|[/_])android[/_.]', f) for f in files):
[email protected]c4781e52012-09-13 18:24:38610 return ['android_dbg']
[email protected]356aa542012-09-19 23:31:29611 if all(re.search('^native_client_sdk', f) for f in files):
612 return ['linux_nacl_sdk', 'win_nacl_sdk', 'mac_nacl_sdk']
[email protected]de142152012-10-03 23:02:45613 if all(re.search('[/_]ios[/_.]', f) for f in files):
614 return ['ios_rel_device', 'ios_dbg_simulator']
[email protected]4ce995ea2012-06-27 02:13:10615
[email protected]d602b902012-07-19 16:30:31616 trybots = ['win_rel', 'linux_rel', 'mac_rel', 'linux_clang:compile',
[email protected]de142152012-10-03 23:02:45617 'linux_chromeos', 'android_dbg', 'linux_asan', 'mac_asan',
618 'ios_rel_device', 'ios_dbg_simulator']
[email protected]911753b2012-08-02 12:11:54619
620 # Match things like path/aura/file.cc and path/file_aura.cc.
[email protected]0be9553a2012-08-10 00:14:45621 # Same for ash and chromeos.
622 if any(re.search('[/_](ash|aura)', f) for f in files):
[email protected]641f2e3e2012-09-03 11:16:24623 trybots += ['linux_chromeos', 'linux_chromeos_clang:compile', 'win_aura',
624 'linux_chromeos_asan']
[email protected]0be9553a2012-08-10 00:14:45625 else:
626 if any(re.search('[/_]chromeos', f) for f in files):
[email protected]641f2e3e2012-09-03 11:16:24627 trybots += ['linux_chromeos', 'linux_chromeos_clang:compile',
628 'linux_chromeos_asan']
[email protected]4ce995ea2012-06-27 02:13:10629
[email protected]4ce995ea2012-06-27 02:13:10630 return trybots