blob: abde0260b6f3de5621ed1a56fb62c4225fa43ada [file] [log] [blame]
James Robinson646469d2014-10-03 15:33:28 -07001# 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.
4
5"""Top-level presubmit script for Chromium.
6
7See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8for more details about the presubmit API built into gcl.
9"""
10
11
James Robinson646469d2014-10-03 15:33:28 -070012_EXCLUDED_PATHS = (
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070013 r"^native_client_sdk/src/build_tools/make_rules.py",
14 r"^native_client_sdk/src/build_tools/make_simple.py",
15 r"^native_client_sdk/src/tools/.*.mk",
16 r"^skia/.*",
17 r"^v8/.*",
James Robinson646469d2014-10-03 15:33:28 -070018 r".*MakeFile$",
19 r".+_autogen\.h$",
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070020 r".+/pnacl_shim\.c$",
21 r"^gpu/config/.*_list_json\.cc$",
22 r"^tools/android_stack_parser/.*"
James Robinson646469d2014-10-03 15:33:28 -070023)
24
Adam Barth76aebe62014-10-23 14:10:21 -070025_SKY_PATHS = (
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070026 r"^sky/.*",
Adam Barth76aebe62014-10-23 14:10:21 -070027)
28
James Robinson646469d2014-10-03 15:33:28 -070029# Fragment of a regular expression that matches C++ and Objective-C++
30# implementation files.
31_IMPLEMENTATION_EXTENSIONS = r'\.(cc|cpp|cxx|mm)$'
32
33# Regular expression that matches code only used for test binaries
34# (best effort).
35_TEST_CODE_EXCLUDED_PATHS = (
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070036 r'.*/(fake_|test_|mock_).+%s' % _IMPLEMENTATION_EXTENSIONS,
James Robinson646469d2014-10-03 15:33:28 -070037 r'.+_test_(base|support|util)%s' % _IMPLEMENTATION_EXTENSIONS,
Viet-Trung Luu24cd9f02015-02-11 10:56:59 -080038 r'.+_(app|browser|perf|pixel|unit)?test(_[a-z]+)?%s' %
James Robinson646469d2014-10-03 15:33:28 -070039 _IMPLEMENTATION_EXTENSIONS,
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070040 r'.*/(test|tool(s)?)/.*',
James Robinson646469d2014-10-03 15:33:28 -070041 # Non-production example code.
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070042 r'mojo/examples/.*',
James Robinson646469d2014-10-03 15:33:28 -070043 # Launcher for running iOS tests on the simulator.
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070044 r'testing/iossim/iossim\.mm$',
James Robinson646469d2014-10-03 15:33:28 -070045)
46
47_TEST_ONLY_WARNING = (
48 'You might be calling functions intended only for testing from\n'
49 'production code. It is OK to ignore this warning if you know what\n'
50 'you are doing, as the heuristics used to detect the situation are\n'
51 'not perfect. The commit queue will not block on this warning.')
52
53
54_INCLUDE_ORDER_WARNING = (
55 'Your #include order seems to be broken. Send mail to\n'
56 'marja@chromium.org if this is not the case.')
57
58
James Robinson646469d2014-10-03 15:33:28 -070059_BANNED_CPP_FUNCTIONS = (
60 # Make sure that gtest's FRIEND_TEST() macro is not used; the
61 # FRIEND_TEST_ALL_PREFIXES() macro from base/gtest_prod_util.h should be
62 # used instead since that allows for FLAKY_ and DISABLED_ prefixes.
63 (
64 'FRIEND_TEST(',
65 (
66 'Chromium code should not use gtest\'s FRIEND_TEST() macro. Include',
67 'base/gtest_prod_util.h and use FRIEND_TEST_ALL_PREFIXES() instead.',
68 ),
69 False,
Viet-Trung Luu5c465e82016-02-09 10:42:07 -080070 (
71 r"^mojo/edk/util/gtest_prod_utils\.h$",
72 ),
James Robinson646469d2014-10-03 15:33:28 -070073 ),
74 (
75 'ScopedAllowIO',
76 (
77 'New code should not use ScopedAllowIO. Post a task to the blocking',
78 'pool or the FILE thread instead.',
79 ),
80 True,
81 (
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -070082 r"^base/process/process_metrics_linux\.cc$",
83 r"^mojo/edk/embedder/simple_platform_shared_buffer_posix\.cc$",
James Robinson646469d2014-10-03 15:33:28 -070084 ),
85 ),
86 (
87 'SkRefPtr',
88 (
89 'The use of SkRefPtr is prohibited. ',
90 'Please use skia::RefPtr instead.'
91 ),
92 True,
93 (),
94 ),
95 (
96 'SkAutoRef',
97 (
98 'The indirect use of SkRefPtr via SkAutoRef is prohibited. ',
99 'Please use skia::RefPtr instead.'
100 ),
101 True,
102 (),
103 ),
104 (
105 'SkAutoTUnref',
106 (
107 'The use of SkAutoTUnref is dangerous because it implicitly ',
108 'converts to a raw pointer. Please use skia::RefPtr instead.'
109 ),
110 True,
111 (),
112 ),
113 (
114 'SkAutoUnref',
115 (
116 'The indirect use of SkAutoTUnref through SkAutoUnref is dangerous ',
117 'because it implicitly converts to a raw pointer. ',
118 'Please use skia::RefPtr instead.'
119 ),
120 True,
121 (),
122 ),
123 (
124 r'/HANDLE_EINTR\(.*close',
125 (
126 'HANDLE_EINTR(close) is invalid. If close fails with EINTR, the file',
127 'descriptor will be closed, and it is incorrect to retry the close.',
128 'Either call close directly and ignore its return value, or wrap close',
129 'in IGNORE_EINTR to use its return value. See http://crbug.com/269623'
130 ),
131 True,
132 (),
133 ),
134 (
135 r'/IGNORE_EINTR\((?!.*close)',
136 (
137 'IGNORE_EINTR is only valid when wrapping close. To wrap other system',
138 'calls, use HANDLE_EINTR. See http://crbug.com/269623',
139 ),
140 True,
141 (
142 # Files that #define IGNORE_EINTR.
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700143 r'^base/posix/eintr_wrapper\.h$',
James Robinson646469d2014-10-03 15:33:28 -0700144 ),
145 ),
146 (
147 r'/v8::Extension\(',
148 (
149 'Do not introduce new v8::Extensions into the code base, use',
150 'gin::Wrappable instead. See http://crbug.com/334679',
151 ),
152 True,
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700153 (),
James Robinson646469d2014-10-03 15:33:28 -0700154 ),
155)
156
James Robinson646469d2014-10-03 15:33:28 -0700157
158_VALID_OS_MACROS = (
159 # Please keep sorted.
160 'OS_ANDROID',
161 'OS_ANDROID_HOST',
162 'OS_BSD',
163 'OS_CAT', # For testing.
164 'OS_CHROMEOS',
165 'OS_FREEBSD',
166 'OS_IOS',
167 'OS_LINUX',
168 'OS_MACOSX',
169 'OS_NACL',
Julien Tinnes06f35a62015-08-24 10:42:09 -0700170 'OS_NACL_NONSFI',
James Robinson646469d2014-10-03 15:33:28 -0700171 'OS_OPENBSD',
172 'OS_POSIX',
173 'OS_QNX',
174 'OS_SOLARIS',
175 'OS_WIN',
176)
177
178
179def _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api):
180 """Attempts to prevent use of functions intended only for testing in
181 non-testing code. For now this is just a best-effort implementation
182 that ignores header files and may have some false positives. A
183 better implementation would probably need a proper C++ parser.
184 """
185 # We only scan .cc files and the like, as the declaration of
186 # for-testing functions in header files are hard to distinguish from
187 # calls to such functions without a proper C++ parser.
188 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
189
190 base_function_pattern = r'[ :]test::[^\s]+|ForTest(ing)?|for_test(ing)?'
191 inclusion_pattern = input_api.re.compile(r'(%s)\s*\(' % base_function_pattern)
192 comment_pattern = input_api.re.compile(r'//.*(%s)' % base_function_pattern)
193 exclusion_pattern = input_api.re.compile(
194 r'::[A-Za-z0-9_]+(%s)|(%s)[^;]+\{' % (
195 base_function_pattern, base_function_pattern))
196
197 def FilterFile(affected_file):
198 black_list = (_EXCLUDED_PATHS +
199 _TEST_CODE_EXCLUDED_PATHS +
200 input_api.DEFAULT_BLACK_LIST)
201 return input_api.FilterSourceFile(
202 affected_file,
203 white_list=(file_inclusion_pattern, ),
204 black_list=black_list)
205
206 problems = []
207 for f in input_api.AffectedSourceFiles(FilterFile):
208 local_path = f.LocalPath()
209 for line_number, line in f.ChangedContents():
210 if (inclusion_pattern.search(line) and
211 not comment_pattern.search(line) and
212 not exclusion_pattern.search(line)):
213 problems.append(
214 '%s:%d\n %s' % (local_path, line_number, line.strip()))
215
216 if problems:
217 return [output_api.PresubmitPromptOrNotify(_TEST_ONLY_WARNING, problems)]
218 else:
219 return []
220
221
222def _CheckNoIOStreamInHeaders(input_api, output_api):
223 """Checks to make sure no .h files include <iostream>."""
224 files = []
225 pattern = input_api.re.compile(r'^#include\s*<iostream>',
226 input_api.re.MULTILINE)
227 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
228 if not f.LocalPath().endswith('.h'):
229 continue
230 contents = input_api.ReadFile(f)
231 if pattern.search(contents):
232 files.append(f)
233
234 if len(files):
235 return [ output_api.PresubmitError(
236 'Do not #include <iostream> in header files, since it inserts static '
237 'initialization into every file including the header. Instead, '
238 '#include <ostream>. See http://crbug.com/94794',
239 files) ]
240 return []
241
242
243def _CheckNoUNIT_TESTInSourceFiles(input_api, output_api):
244 """Checks to make sure no source files use UNIT_TEST"""
245 problems = []
246 for f in input_api.AffectedFiles():
247 if (not f.LocalPath().endswith(('.cc', '.mm'))):
248 continue
249
250 for line_num, line in f.ChangedContents():
251 if 'UNIT_TEST ' in line or line.endswith('UNIT_TEST'):
252 problems.append(' %s:%d' % (f.LocalPath(), line_num))
253
254 if not problems:
255 return []
256 return [output_api.PresubmitPromptWarning('UNIT_TEST is only for headers.\n' +
257 '\n'.join(problems))]
258
259
260def _CheckNoNewWStrings(input_api, output_api):
261 """Checks to make sure we don't introduce use of wstrings."""
262 problems = []
263 for f in input_api.AffectedFiles():
264 if (not f.LocalPath().endswith(('.cc', '.h')) or
265 f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h'))):
266 continue
267
268 allowWString = False
269 for line_num, line in f.ChangedContents():
270 if 'presubmit: allow wstring' in line:
271 allowWString = True
272 elif not allowWString and 'wstring' in line:
273 problems.append(' %s:%d' % (f.LocalPath(), line_num))
274 allowWString = False
275 else:
276 allowWString = False
277
278 if not problems:
279 return []
280 return [output_api.PresubmitPromptWarning('New code should not use wstrings.'
281 ' If you are calling a cross-platform API that accepts a wstring, '
282 'fix the API.\n' +
283 '\n'.join(problems))]
284
285
286def _CheckNoDEPSGIT(input_api, output_api):
287 """Make sure .DEPS.git is never modified manually."""
288 if any(f.LocalPath().endswith('.DEPS.git') for f in
289 input_api.AffectedFiles()):
290 return [output_api.PresubmitError(
291 'Never commit changes to .DEPS.git. This file is maintained by an\n'
292 'automated system based on what\'s in DEPS and your changes will be\n'
293 'overwritten.\n'
294 'See https://sites.google.com/a/chromium.org/dev/developers/how-tos/get-the-code#Rolling_DEPS\n'
295 'for more information')]
296 return []
297
298
299def _CheckValidHostsInDEPS(input_api, output_api):
300 """Checks that DEPS file deps are from allowed_hosts."""
301 # Run only if DEPS file has been modified to annoy fewer bystanders.
302 if all(f.LocalPath() != 'DEPS' for f in input_api.AffectedFiles()):
303 return []
304 # Outsource work to gclient verify
305 try:
306 input_api.subprocess.check_output(['gclient', 'verify'])
307 return []
308 except input_api.subprocess.CalledProcessError, error:
309 return [output_api.PresubmitError(
310 'DEPS file must have only git dependencies.',
311 long_text=error.output)]
312
313
314def _CheckNoBannedFunctions(input_api, output_api):
315 """Make sure that banned functions are not used."""
316 warnings = []
317 errors = []
318
James Robinson646469d2014-10-03 15:33:28 -0700319 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.mm', '.h'))
320 for f in input_api.AffectedFiles(file_filter=file_filter):
321 for line_num, line in f.ChangedContents():
322 for func_name, message, error, excluded_paths in _BANNED_CPP_FUNCTIONS:
323 def IsBlacklisted(affected_file, blacklist):
324 local_path = affected_file.LocalPath()
325 for item in blacklist:
326 if input_api.re.match(item, local_path):
327 return True
328 return False
329 if IsBlacklisted(f, excluded_paths):
330 continue
331 matched = False
332 if func_name[0:1] == '/':
333 regex = func_name[1:]
334 if input_api.re.search(regex, line):
335 matched = True
336 elif func_name in line:
337 matched = True
338 if matched:
339 problems = warnings;
340 if error:
341 problems = errors;
342 problems.append(' %s:%d:' % (f.LocalPath(), line_num))
343 for message_line in message:
344 problems.append(' %s' % message_line)
345
346 result = []
347 if (warnings):
348 result.append(output_api.PresubmitPromptWarning(
349 'Banned functions were used.\n' + '\n'.join(warnings)))
350 if (errors):
351 result.append(output_api.PresubmitError(
352 'Banned functions were used.\n' + '\n'.join(errors)))
353 return result
354
355
356def _CheckNoPragmaOnce(input_api, output_api):
357 """Make sure that banned functions are not used."""
358 files = []
359 pattern = input_api.re.compile(r'^#pragma\s+once',
360 input_api.re.MULTILINE)
361 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
362 if not f.LocalPath().endswith('.h'):
363 continue
364 contents = input_api.ReadFile(f)
365 if pattern.search(contents):
366 files.append(f)
367
368 if files:
369 return [output_api.PresubmitError(
370 'Do not use #pragma once in header files.\n'
371 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
372 files)]
373 return []
374
375
376def _CheckNoTrinaryTrueFalse(input_api, output_api):
377 """Checks to make sure we don't introduce use of foo ? true : false."""
378 problems = []
379 pattern = input_api.re.compile(r'\?\s*(true|false)\s*:\s*(true|false)')
380 for f in input_api.AffectedFiles():
381 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
382 continue
383
384 for line_num, line in f.ChangedContents():
385 if pattern.match(line):
386 problems.append(' %s:%d' % (f.LocalPath(), line_num))
387
388 if not problems:
389 return []
390 return [output_api.PresubmitPromptWarning(
391 'Please consider avoiding the "? true : false" pattern if possible.\n' +
392 '\n'.join(problems))]
393
394
James Robinson646469d2014-10-03 15:33:28 -0700395def _CheckFilePermissions(input_api, output_api):
396 """Check that all files have their permissions properly set."""
397 if input_api.platform == 'win32':
398 return []
James Robinson80d418c2014-10-16 16:00:02 -0700399 args = [input_api.python_executable, 'tools/checkperms/checkperms.py',
400 '--root', input_api.change.RepositoryRoot()]
James Robinson646469d2014-10-03 15:33:28 -0700401 for f in input_api.AffectedFiles():
402 args += ['--file', f.LocalPath()]
403 checkperms = input_api.subprocess.Popen(args,
404 stdout=input_api.subprocess.PIPE)
405 errors = checkperms.communicate()[0].strip()
406 if errors:
407 return [output_api.PresubmitError('checkperms.py failed.',
408 errors.splitlines())]
409 return []
410
411
James Robinson646469d2014-10-03 15:33:28 -0700412def _CheckIncludeOrderForScope(scope, input_api, file_path, changed_linenums):
413 """Checks that the lines in scope occur in the right order.
414
415 1. C system files in alphabetical order
416 2. C++ system files in alphabetical order
417 3. Project's .h files
418 """
419
420 c_system_include_pattern = input_api.re.compile(r'\s*#include <.*\.h>')
421 cpp_system_include_pattern = input_api.re.compile(r'\s*#include <.*>')
422 custom_include_pattern = input_api.re.compile(r'\s*#include ".*')
423
424 C_SYSTEM_INCLUDES, CPP_SYSTEM_INCLUDES, CUSTOM_INCLUDES = range(3)
425
426 state = C_SYSTEM_INCLUDES
427
428 previous_line = ''
429 previous_line_num = 0
430 problem_linenums = []
431 for line_num, line in scope:
432 if c_system_include_pattern.match(line):
433 if state != C_SYSTEM_INCLUDES:
434 problem_linenums.append((line_num, previous_line_num))
435 elif previous_line and previous_line > line:
436 problem_linenums.append((line_num, previous_line_num))
437 elif cpp_system_include_pattern.match(line):
438 if state == C_SYSTEM_INCLUDES:
439 state = CPP_SYSTEM_INCLUDES
440 elif state == CUSTOM_INCLUDES:
441 problem_linenums.append((line_num, previous_line_num))
442 elif previous_line and previous_line > line:
443 problem_linenums.append((line_num, previous_line_num))
444 elif custom_include_pattern.match(line):
445 if state != CUSTOM_INCLUDES:
446 state = CUSTOM_INCLUDES
447 elif previous_line and previous_line > line:
448 problem_linenums.append((line_num, previous_line_num))
449 else:
450 problem_linenums.append(line_num)
451 previous_line = line
452 previous_line_num = line_num
453
454 warnings = []
455 for (line_num, previous_line_num) in problem_linenums:
456 if line_num in changed_linenums or previous_line_num in changed_linenums:
457 warnings.append(' %s:%d' % (file_path, line_num))
458 return warnings
459
460
461def _CheckIncludeOrderInFile(input_api, f, changed_linenums):
462 """Checks the #include order for the given file f."""
463
464 system_include_pattern = input_api.re.compile(r'\s*#include \<.*')
465 # Exclude the following includes from the check:
466 # 1) #include <.../...>, e.g., <sys/...> includes often need to appear in a
467 # specific order.
Viet-Trung Luu864b4f82015-11-11 14:40:05 -0800468 # 2) "build/build_config.h"
James Robinson646469d2014-10-03 15:33:28 -0700469 excluded_include_pattern = input_api.re.compile(
Viet-Trung Luu864b4f82015-11-11 14:40:05 -0800470 r'\s*#include (\<.*/.*|"build/build_config.h")')
James Robinson646469d2014-10-03 15:33:28 -0700471 custom_include_pattern = input_api.re.compile(r'\s*#include "(?P<FILE>.*)"')
472 # Match the final or penultimate token if it is xxxtest so we can ignore it
473 # when considering the special first include.
474 test_file_tag_pattern = input_api.re.compile(
475 r'_[a-z]+test(?=(_[a-zA-Z0-9]+)?\.)')
476 if_pattern = input_api.re.compile(
477 r'\s*#\s*(if|elif|else|endif|define|undef).*')
478 # Some files need specialized order of includes; exclude such files from this
479 # check.
480 uncheckable_includes_pattern = input_api.re.compile(
481 r'\s*#include '
482 '("ipc/.*macros\.h"|<windows\.h>|".*gl.*autogen.h")\s*')
483
484 contents = f.NewContents()
485 warnings = []
486 line_num = 0
487
488 # Handle the special first include. If the first include file is
489 # some/path/file.h, the corresponding including file can be some/path/file.cc,
490 # some/other/path/file.cc, some/path/file_platform.cc, some/path/file-suffix.h
491 # etc. It's also possible that no special first include exists.
492 # If the included file is some/path/file_platform.h the including file could
493 # also be some/path/file_xxxtest_platform.h.
494 including_file_base_name = test_file_tag_pattern.sub(
495 '', input_api.os_path.basename(f.LocalPath()))
496
497 for line in contents:
498 line_num += 1
499 if system_include_pattern.match(line):
500 # No special first include -> process the line again along with normal
501 # includes.
502 line_num -= 1
503 break
504 match = custom_include_pattern.match(line)
505 if match:
506 match_dict = match.groupdict()
507 header_basename = test_file_tag_pattern.sub(
508 '', input_api.os_path.basename(match_dict['FILE'])).replace('.h', '')
509
510 if header_basename not in including_file_base_name:
511 # No special first include -> process the line again along with normal
512 # includes.
513 line_num -= 1
514 break
515
516 # Split into scopes: Each region between #if and #endif is its own scope.
517 scopes = []
518 current_scope = []
519 for line in contents[line_num:]:
520 line_num += 1
521 if uncheckable_includes_pattern.match(line):
522 continue
523 if if_pattern.match(line):
524 scopes.append(current_scope)
525 current_scope = []
526 elif ((system_include_pattern.match(line) or
527 custom_include_pattern.match(line)) and
528 not excluded_include_pattern.match(line)):
529 current_scope.append((line_num, line))
530 scopes.append(current_scope)
531
532 for scope in scopes:
533 warnings.extend(_CheckIncludeOrderForScope(scope, input_api, f.LocalPath(),
534 changed_linenums))
535 return warnings
536
537
538def _CheckIncludeOrder(input_api, output_api):
539 """Checks that the #include order is correct.
540
541 1. The corresponding header for source files.
542 2. C system files in alphabetical order
543 3. C++ system files in alphabetical order
544 4. Project's .h files in alphabetical order
545
546 Each region separated by #if, #elif, #else, #endif, #define and #undef follows
547 these rules separately.
548 """
549 def FileFilterIncludeOrder(affected_file):
550 black_list = (_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST)
551 return input_api.FilterSourceFile(affected_file, black_list=black_list)
552
553 warnings = []
554 for f in input_api.AffectedFiles(file_filter=FileFilterIncludeOrder):
555 if f.LocalPath().endswith(('.cc', '.h')):
556 changed_linenums = set(line_num for line_num, _ in f.ChangedContents())
557 warnings.extend(_CheckIncludeOrderInFile(input_api, f, changed_linenums))
558
559 results = []
560 if warnings:
561 results.append(output_api.PresubmitPromptOrNotify(_INCLUDE_ORDER_WARNING,
562 warnings))
563 return results
564
565
566def _CheckForVersionControlConflictsInFile(input_api, f):
567 pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$')
568 errors = []
569 for line_num, line in f.ChangedContents():
570 if pattern.match(line):
571 errors.append(' %s:%d %s' % (f.LocalPath(), line_num, line))
572 return errors
573
574
575def _CheckForVersionControlConflicts(input_api, output_api):
576 """Usually this is not intentional and will cause a compile failure."""
577 errors = []
578 for f in input_api.AffectedFiles():
579 errors.extend(_CheckForVersionControlConflictsInFile(input_api, f))
580
581 results = []
582 if errors:
583 results.append(output_api.PresubmitError(
584 'Version control conflict markers found, please resolve.', errors))
585 return results
586
587
588def _CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api):
589 def FilterFile(affected_file):
590 """Filter function for use with input_api.AffectedSourceFiles,
591 below. This filters out everything except non-test files from
592 top-level directories that generally speaking should not hard-code
593 service URLs (e.g. src/android_webview/, src/content/ and others).
594 """
595 return input_api.FilterSourceFile(
596 affected_file,
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700597 white_list=(r'^base/.*', ),
James Robinson646469d2014-10-03 15:33:28 -0700598 black_list=(_EXCLUDED_PATHS +
599 _TEST_CODE_EXCLUDED_PATHS +
600 input_api.DEFAULT_BLACK_LIST))
601
602 base_pattern = '"[^"]*google\.com[^"]*"'
603 comment_pattern = input_api.re.compile('//.*%s' % base_pattern)
604 pattern = input_api.re.compile(base_pattern)
605 problems = [] # items are (filename, line_number, line)
606 for f in input_api.AffectedSourceFiles(FilterFile):
607 for line_num, line in f.ChangedContents():
608 if not comment_pattern.search(line) and pattern.search(line):
609 problems.append((f.LocalPath(), line_num, line))
610
611 if problems:
612 return [output_api.PresubmitPromptOrNotify(
613 'Most layers below src/chrome/ should not hardcode service URLs.\n'
614 'Are you sure this is correct?',
615 [' %s:%d: %s' % (
616 problem[0], problem[1], problem[2]) for problem in problems])]
617 else:
618 return []
619
620
621def _CheckNoAbbreviationInPngFileName(input_api, output_api):
622 """Makes sure there are no abbreviations in the name of PNG files.
623 """
624 pattern = input_api.re.compile(r'.*_[a-z]_.*\.png$|.*_[a-z]\.png$')
625 errors = []
626 for f in input_api.AffectedFiles(include_deletes=False):
627 if pattern.match(f.LocalPath()):
628 errors.append(' %s' % f.LocalPath())
629
630 results = []
631 if errors:
632 results.append(output_api.PresubmitError(
633 'The name of PNG files should not have abbreviations. \n'
634 'Use _hover.png, _center.png, instead of _h.png, _c.png.\n'
635 'Contact oshima@chromium.org if you have questions.', errors))
636 return results
637
638
James Robinson646469d2014-10-03 15:33:28 -0700639def _CheckSpamLogging(input_api, output_api):
640 file_inclusion_pattern = r'.+%s' % _IMPLEMENTATION_EXTENSIONS
641 black_list = (_EXCLUDED_PATHS +
642 _TEST_CODE_EXCLUDED_PATHS +
643 input_api.DEFAULT_BLACK_LIST +
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700644 (r"^base/logging\.h$",
645 r"^base/logging\.cc$",
Jeff Brown2df6b302015-10-27 18:48:31 -0700646 r"^examples/.*$",
Viet-Trung Luud42e48a2015-11-03 14:54:55 -0800647 r"^mojo/edk/util/logging_internal\.cc$",
Sean Klein298d9942015-10-12 12:18:53 -0700648 r"^mojo/nacl/sfi/nacl_bindings/mojo_syscall\.cc$",
Viet-Trung Luua237e8b2016-04-27 13:25:41 -0700649 r"^services/log/main\.cc$",
James Robinsonf0f18602015-04-10 11:29:47 -0700650 r"^shell/application_manager/network_fetcher\.cc$",
651 r"^shell/tracer\.cc$",
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700652 r"^sandbox/linux/.*",
James Robinsonf0f18602015-04-10 11:29:47 -0700653 r"^tools/.*"))
James Robinson646469d2014-10-03 15:33:28 -0700654 source_file_filter = lambda x: input_api.FilterSourceFile(
655 x, white_list=(file_inclusion_pattern,), black_list=black_list)
656
Ojan Vafaid77dcf82014-12-09 13:18:42 -0800657 log_macro = input_api.re.compile(r"\bD?LOG\s*\(\s*INFO\s*\)")
658 log_if_macro = input_api.re.compile(r"\bD?LOG_IF\s*\(\s*INFO\s*,")
659 printf_macro = input_api.re.compile(r"\bprintf\(")
660 fprintf_macro = input_api.re.compile(r"\bfprintf\((stdout|stderr)")
661
James Robinson646469d2014-10-03 15:33:28 -0700662 log_info = []
663 printf = []
664
665 for f in input_api.AffectedSourceFiles(source_file_filter):
Ojan Vafaid77dcf82014-12-09 13:18:42 -0800666 for linenum, line in f.ChangedContents():
667 if log_macro.search(line) or log_if_macro.search(line):
668 log_info.append(f.LocalPath())
669 if printf_macro.search(line) or fprintf_macro.search(line):
670 printf.append(f.LocalPath())
James Robinson646469d2014-10-03 15:33:28 -0700671
672 if log_info:
673 return [output_api.PresubmitError(
674 'These files spam the console log with LOG(INFO):',
675 items=log_info)]
676 if printf:
677 return [output_api.PresubmitError(
678 'These files spam the console log with printf/fprintf:',
679 items=printf)]
680 return []
681
682
683def _CheckForAnonymousVariables(input_api, output_api):
684 """These types are all expected to hold locks while in scope and
685 so should never be anonymous (which causes them to be immediately
686 destroyed)."""
687 they_who_must_be_named = [
688 'base::AutoLock',
689 'base::AutoReset',
690 'base::AutoUnlock',
691 'SkAutoAlphaRestore',
692 'SkAutoBitmapShaderInstall',
693 'SkAutoBlitterChoose',
694 'SkAutoBounderCommit',
695 'SkAutoCallProc',
696 'SkAutoCanvasRestore',
697 'SkAutoCommentBlock',
698 'SkAutoDescriptor',
699 'SkAutoDisableDirectionCheck',
700 'SkAutoDisableOvalCheck',
701 'SkAutoFree',
702 'SkAutoGlyphCache',
703 'SkAutoHDC',
704 'SkAutoLockColors',
705 'SkAutoLockPixels',
706 'SkAutoMalloc',
707 'SkAutoMaskFreeImage',
708 'SkAutoMutexAcquire',
709 'SkAutoPathBoundsUpdate',
710 'SkAutoPDFRelease',
711 'SkAutoRasterClipValidate',
712 'SkAutoRef',
713 'SkAutoTime',
714 'SkAutoTrace',
715 'SkAutoUnref',
716 ]
717 anonymous = r'(%s)\s*[({]' % '|'.join(they_who_must_be_named)
718 # bad: base::AutoLock(lock.get());
719 # not bad: base::AutoLock lock(lock.get());
720 bad_pattern = input_api.re.compile(anonymous)
721 # good: new base::AutoLock(lock.get())
722 good_pattern = input_api.re.compile(r'\bnew\s*' + anonymous)
723 errors = []
724
725 for f in input_api.AffectedFiles():
726 if not f.LocalPath().endswith(('.cc', '.h', '.inl', '.m', '.mm')):
727 continue
728 for linenum, line in f.ChangedContents():
729 if bad_pattern.search(line) and not good_pattern.search(line):
730 errors.append('%s:%d' % (f.LocalPath(), linenum))
731
732 if errors:
733 return [output_api.PresubmitError(
734 'These lines create anonymous variables that need to be named:',
735 items=errors)]
736 return []
737
738
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700739def _GetJSONParseError(input_api, filename):
James Robinson646469d2014-10-03 15:33:28 -0700740 try:
741 contents = input_api.ReadFile(filename)
James Robinson646469d2014-10-03 15:33:28 -0700742 input_api.json.loads(contents)
743 except ValueError as e:
744 return e
745 return None
746
747
James Robinson646469d2014-10-03 15:33:28 -0700748def _CheckParseErrors(input_api, output_api):
yzshen15b9d4a2014-10-26 22:46:24 -0700749 """Check that JSON files do not contain syntax errors."""
James Robinson646469d2014-10-03 15:33:28 -0700750 actions = {
James Robinson646469d2014-10-03 15:33:28 -0700751 '.json': _GetJSONParseError,
752 }
753 # These paths contain test data and other known invalid JSON files.
754 excluded_patterns = [
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700755 r'test/data/',
James Robinson646469d2014-10-03 15:33:28 -0700756 ]
757 # Most JSON files are preprocessed and support comments, but these do not.
758 json_no_comments_patterns = [
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700759 r'^testing/',
James Robinson646469d2014-10-03 15:33:28 -0700760 ]
James Robinson646469d2014-10-03 15:33:28 -0700761
762 def get_action(affected_file):
763 filename = affected_file.LocalPath()
764 return actions.get(input_api.os_path.splitext(filename)[1])
765
766 def MatchesFile(patterns, path):
767 for pattern in patterns:
768 if input_api.re.search(pattern, path):
769 return True
770 return False
771
772 def FilterFile(affected_file):
773 action = get_action(affected_file)
774 if not action:
775 return False
776 path = affected_file.LocalPath()
777
778 if MatchesFile(excluded_patterns, path):
779 return False
James Robinson646469d2014-10-03 15:33:28 -0700780 return True
781
782 results = []
783 for affected_file in input_api.AffectedFiles(
784 file_filter=FilterFile, include_deletes=False):
785 action = get_action(affected_file)
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700786 parse_error = action(input_api, affected_file.AbsoluteLocalPath())
James Robinson646469d2014-10-03 15:33:28 -0700787 if parse_error:
788 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
789 (affected_file.LocalPath(), parse_error)))
790 return results
791
792
793def _CheckJavaStyle(input_api, output_api):
794 """Runs checkstyle on changed java files and returns errors if any exist."""
James Robinson80d418c2014-10-16 16:00:02 -0700795 import sys
James Robinson646469d2014-10-03 15:33:28 -0700796 original_sys_path = sys.path
797 try:
798 sys.path = sys.path + [input_api.os_path.join(
799 input_api.PresubmitLocalPath(), 'tools', 'android', 'checkstyle')]
800 import checkstyle
801 finally:
802 # Restore sys.path to what it was before.
803 sys.path = original_sys_path
804
805 return checkstyle.RunCheckstyle(
806 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml')
807
808
809_DEPRECATED_CSS = [
810 # Values
811 ( "-webkit-box", "flex" ),
812 ( "-webkit-inline-box", "inline-flex" ),
813 ( "-webkit-flex", "flex" ),
814 ( "-webkit-inline-flex", "inline-flex" ),
815 ( "-webkit-min-content", "min-content" ),
816 ( "-webkit-max-content", "max-content" ),
817
818 # Properties
819 ( "-webkit-background-clip", "background-clip" ),
820 ( "-webkit-background-origin", "background-origin" ),
821 ( "-webkit-background-size", "background-size" ),
822 ( "-webkit-box-shadow", "box-shadow" ),
823
824 # Functions
825 ( "-webkit-gradient", "gradient" ),
826 ( "-webkit-repeating-gradient", "repeating-gradient" ),
827 ( "-webkit-linear-gradient", "linear-gradient" ),
828 ( "-webkit-repeating-linear-gradient", "repeating-linear-gradient" ),
829 ( "-webkit-radial-gradient", "radial-gradient" ),
830 ( "-webkit-repeating-radial-gradient", "repeating-radial-gradient" ),
831]
832
833def _CheckNoDeprecatedCSS(input_api, output_api):
834 """ Make sure that we don't use deprecated CSS
835 properties, functions or values. Our external
836 documentation is ignored by the hooks as it
837 needs to be consumed by WebKit. """
838 results = []
839 file_inclusion_pattern = (r".+\.css$")
840 black_list = (_EXCLUDED_PATHS +
841 _TEST_CODE_EXCLUDED_PATHS +
842 input_api.DEFAULT_BLACK_LIST +
843 (r"^chrome/common/extensions/docs",
844 r"^chrome/docs",
845 r"^native_client_sdk"))
846 file_filter = lambda f: input_api.FilterSourceFile(
847 f, white_list=file_inclusion_pattern, black_list=black_list)
848 for fpath in input_api.AffectedFiles(file_filter=file_filter):
849 for line_num, line in fpath.ChangedContents():
850 for (deprecated_value, value) in _DEPRECATED_CSS:
851 if input_api.re.search(deprecated_value, line):
852 results.append(output_api.PresubmitError(
853 "%s:%d: Use of deprecated CSS %s, use %s instead" %
854 (fpath.LocalPath(), line_num, deprecated_value, value)))
855 return results
856
James Robinson80d418c2014-10-16 16:00:02 -0700857
858def _CheckForOverrideAndFinalRules(input_api, output_api):
859 """Checks for final and override used as per C++11"""
860 problems = []
861 for f in input_api.AffectedFiles():
862 if (f.LocalPath().endswith(('.cc', '.cpp', '.h', '.mm'))):
863 for line_num, line in f.ChangedContents():
864 if (input_api.re.search(r'\b(FINAL|OVERRIDE)\b', line)):
865 problems.append(' %s:%d' % (f.LocalPath(), line_num))
866
867 if not problems:
868 return []
869 return [output_api.PresubmitError('Use C++11\'s |final| and |override| '
870 'rather than FINAL and OVERRIDE.',
871 problems)]
872
873
James Robinson646469d2014-10-03 15:33:28 -0700874def _CommonChecks(input_api, output_api):
875 """Checks common to both upload and commit."""
876 results = []
877 results.extend(input_api.canned_checks.PanProjectChecks(
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -0700878 input_api, output_api, excluded_paths=_EXCLUDED_PATHS + _SKY_PATHS))
James Robinson646469d2014-10-03 15:33:28 -0700879 results.extend(_CheckAuthorizedAuthor(input_api, output_api))
880 results.extend(
881 _CheckNoProductionCodeUsingTestOnlyFunctions(input_api, output_api))
882 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
883 results.extend(_CheckNoUNIT_TESTInSourceFiles(input_api, output_api))
884 results.extend(_CheckNoNewWStrings(input_api, output_api))
885 results.extend(_CheckNoDEPSGIT(input_api, output_api))
886 results.extend(_CheckNoBannedFunctions(input_api, output_api))
887 results.extend(_CheckNoPragmaOnce(input_api, output_api))
888 results.extend(_CheckNoTrinaryTrueFalse(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -0700889 results.extend(_CheckFilePermissions(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -0700890 results.extend(_CheckIncludeOrder(input_api, output_api))
891 results.extend(_CheckForVersionControlConflicts(input_api, output_api))
892 results.extend(_CheckPatchFiles(input_api, output_api))
893 results.extend(_CheckHardcodedGoogleHostsInLowerLayers(input_api, output_api))
894 results.extend(_CheckNoAbbreviationInPngFileName(input_api, output_api))
895 results.extend(_CheckForInvalidOSMacros(input_api, output_api))
896 results.extend(_CheckForInvalidIfDefinedMacros(input_api, output_api))
James Robinsona9763132014-10-06 11:18:13 -0700897 # TODO(danakj): Remove this when base/move.h is removed.
898 results.extend(_CheckForUsingSideEffectsOfPass(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -0700899 results.extend(
900 input_api.canned_checks.CheckChangeHasNoTabs(
901 input_api,
902 output_api,
903 source_file_filter=lambda x: x.LocalPath().endswith('.grd')))
904 results.extend(_CheckSpamLogging(input_api, output_api))
905 results.extend(_CheckForAnonymousVariables(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -0700906 results.extend(_CheckNoDeprecatedCSS(input_api, output_api))
907 results.extend(_CheckParseErrors(input_api, output_api))
James Robinson80d418c2014-10-16 16:00:02 -0700908 results.extend(_CheckForOverrideAndFinalRules(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -0700909
910 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()):
911 results.extend(input_api.canned_checks.RunUnitTestsInDirectory(
912 input_api, output_api,
913 input_api.PresubmitLocalPath(),
914 whitelist=[r'^PRESUBMIT_test\.py$']))
915 return results
916
917
918def _CheckAuthorizedAuthor(input_api, output_api):
919 """For non-googler/chromites committers, verify the author's email address is
920 in AUTHORS.
921 """
922 # TODO(maruel): Add it to input_api?
923 import fnmatch
924
925 author = input_api.change.author_email
926 if not author:
927 input_api.logging.info('No author, skipping AUTHOR check')
928 return []
929 authors_path = input_api.os_path.join(
930 input_api.PresubmitLocalPath(), 'AUTHORS')
931 valid_authors = (
932 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line)
933 for line in open(authors_path))
934 valid_authors = [item.group(1).lower() for item in valid_authors if item]
935 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors):
936 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors))
937 return [output_api.PresubmitPromptWarning(
938 ('%s is not in AUTHORS file. If you are a new contributor, please visit'
939 '\n'
940 'http://www.chromium.org/developers/contributing-code and read the '
941 '"Legal" section\n'
942 'If you are a chromite, verify the contributor signed the CLA.') %
943 author)]
944 return []
945
946
947def _CheckPatchFiles(input_api, output_api):
948 problems = [f.LocalPath() for f in input_api.AffectedFiles()
949 if f.LocalPath().endswith(('.orig', '.rej'))]
950 if problems:
951 return [output_api.PresubmitError(
952 "Don't commit .rej and .orig files.", problems)]
953 else:
954 return []
955
956
957def _DidYouMeanOSMacro(bad_macro):
958 try:
959 return {'A': 'OS_ANDROID',
960 'B': 'OS_BSD',
961 'C': 'OS_CHROMEOS',
962 'F': 'OS_FREEBSD',
963 'L': 'OS_LINUX',
964 'M': 'OS_MACOSX',
965 'N': 'OS_NACL',
966 'O': 'OS_OPENBSD',
967 'P': 'OS_POSIX',
968 'S': 'OS_SOLARIS',
969 'W': 'OS_WIN'}[bad_macro[3].upper()]
970 except KeyError:
971 return ''
972
973
974def _CheckForInvalidOSMacrosInFile(input_api, f):
975 """Check for sensible looking, totally invalid OS macros."""
976 preprocessor_statement = input_api.re.compile(r'^\s*#')
977 os_macro = input_api.re.compile(r'defined\((OS_[^)]+)\)')
978 results = []
979 for lnum, line in f.ChangedContents():
980 if preprocessor_statement.search(line):
981 for match in os_macro.finditer(line):
982 if not match.group(1) in _VALID_OS_MACROS:
983 good = _DidYouMeanOSMacro(match.group(1))
984 did_you_mean = ' (did you mean %s?)' % good if good else ''
985 results.append(' %s:%d %s%s' % (f.LocalPath(),
986 lnum,
987 match.group(1),
988 did_you_mean))
989 return results
990
991
992def _CheckForInvalidOSMacros(input_api, output_api):
993 """Check all affected files for invalid OS macros."""
994 bad_macros = []
995 for f in input_api.AffectedFiles():
996 if not f.LocalPath().endswith(('.py', '.js', '.html', '.css')):
997 bad_macros.extend(_CheckForInvalidOSMacrosInFile(input_api, f))
998
999 if not bad_macros:
1000 return []
1001
1002 return [output_api.PresubmitError(
1003 'Possibly invalid OS macro[s] found. Please fix your code\n'
1004 'or add your macro to src/PRESUBMIT.py.', bad_macros)]
1005
1006
1007def _CheckForInvalidIfDefinedMacrosInFile(input_api, f):
1008 """Check all affected files for invalid "if defined" macros."""
1009 ALWAYS_DEFINED_MACROS = (
1010 "TARGET_CPU_PPC",
1011 "TARGET_CPU_PPC64",
1012 "TARGET_CPU_68K",
1013 "TARGET_CPU_X86",
1014 "TARGET_CPU_ARM",
1015 "TARGET_CPU_MIPS",
1016 "TARGET_CPU_SPARC",
1017 "TARGET_CPU_ALPHA",
1018 "TARGET_IPHONE_SIMULATOR",
1019 "TARGET_OS_EMBEDDED",
1020 "TARGET_OS_IPHONE",
1021 "TARGET_OS_MAC",
1022 "TARGET_OS_UNIX",
1023 "TARGET_OS_WIN32",
1024 )
1025 ifdef_macro = input_api.re.compile(r'^\s*#.*(?:ifdef\s|defined\()([^\s\)]+)')
1026 results = []
1027 for lnum, line in f.ChangedContents():
1028 for match in ifdef_macro.finditer(line):
1029 if match.group(1) in ALWAYS_DEFINED_MACROS:
1030 always_defined = ' %s is always defined. ' % match.group(1)
1031 did_you_mean = 'Did you mean \'#if %s\'?' % match.group(1)
1032 results.append(' %s:%d %s\n\t%s' % (f.LocalPath(),
1033 lnum,
1034 always_defined,
1035 did_you_mean))
1036 return results
1037
1038
1039def _CheckForInvalidIfDefinedMacros(input_api, output_api):
1040 """Check all affected files for invalid "if defined" macros."""
1041 bad_macros = []
1042 for f in input_api.AffectedFiles():
1043 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1044 bad_macros.extend(_CheckForInvalidIfDefinedMacrosInFile(input_api, f))
1045
1046 if not bad_macros:
1047 return []
1048
1049 return [output_api.PresubmitError(
1050 'Found ifdef check on always-defined macro[s]. Please fix your code\n'
1051 'or check the list of ALWAYS_DEFINED_MACROS in src/PRESUBMIT.py.',
1052 bad_macros)]
1053
1054
James Robinsona9763132014-10-06 11:18:13 -07001055def _CheckForUsingSideEffectsOfPass(input_api, output_api):
1056 """Check all affected files for using side effects of Pass."""
1057 errors = []
1058 for f in input_api.AffectedFiles():
1059 if f.LocalPath().endswith(('.h', '.c', '.cc', '.m', '.mm')):
1060 for lnum, line in f.ChangedContents():
1061 # Disallow Foo(*my_scoped_thing.Pass()); See crbug.com/418297.
James Robinson80d418c2014-10-16 16:00:02 -07001062 if input_api.re.search(r'\*[a-zA-Z0-9_]+\.Pass\(\)', line):
James Robinsona9763132014-10-06 11:18:13 -07001063 errors.append(output_api.PresubmitError(
1064 ('%s:%d uses *foo.Pass() to delete the contents of scoped_ptr. ' +
1065 'See crbug.com/418297.') % (f.LocalPath(), lnum)))
1066 return errors
1067
1068
John McCutchanad0bc6d2015-11-17 13:55:35 -08001069def _CheckDartBindings(input_api, output_api):
1070 """Check that generated .mojom.dart files are current"""
1071 args = [input_api.python_executable,
1072 'mojo/dart/tools/presubmit/check_mojom_dart.py',
1073 '--affected-files']
1074 files = []
1075 for f in input_api.AffectedFiles():
1076 files.append(f.LocalPath())
1077 args.extend(files)
1078 try:
1079 input_api.subprocess.check_output(args)
1080 return []
1081 except input_api.subprocess.CalledProcessError, error:
1082 return [output_api.PresubmitError(
1083 'Dart bindings need to be updated.',
1084 long_text=error.output)]
1085
1086
James Robinson646469d2014-10-03 15:33:28 -07001087def CheckChangeOnUpload(input_api, output_api):
1088 results = []
1089 results.extend(_CommonChecks(input_api, output_api))
1090 results.extend(_CheckValidHostsInDEPS(input_api, output_api))
1091 results.extend(_CheckJavaStyle(input_api, output_api))
John McCutchanad0bc6d2015-11-17 13:55:35 -08001092 results.extend(_CheckDartBindings(input_api, output_api))
James Robinsond2015d92014-12-08 13:45:40 -08001093 results.extend(
1094 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -07001095 return results
1096
1097
James Robinson646469d2014-10-03 15:33:28 -07001098def GetDefaultTryConfigs(bots=None):
1099 """Returns a list of ('bot', set(['tests']), optionally filtered by [bots].
1100
James Robinson646469d2014-10-03 15:33:28 -07001101 If 'bots' is specified, will only return configurations for bots in that list.
1102 """
1103
James Robinson646469d2014-10-03 15:33:28 -07001104 builders_and_tests = {
James Robinson160c7e52014-12-02 13:28:44 -08001105 'Mojo Android Builder (dbg) Try': ['defaulttests'],
James Robinson682ff0c2015-01-23 10:43:21 -08001106 'Mojo Android Builder Try': ['defaulttests'],
Mitch Rudominer82392642015-04-15 12:36:28 -07001107 'Mojo Android Builder Tests (dbg) Try': ['defaulttests'],
James Robinson682ff0c2015-01-23 10:43:21 -08001108 'Mojo Linux (dbg) Try': ['defaulttests'],
1109 'Mojo Linux ASan Try': ['defaulttests'],
James Robinson682ff0c2015-01-23 10:43:21 -08001110 'Mojo Linux Try': ['defaulttests'],
James Robinson646469d2014-10-03 15:33:28 -07001111 }
1112
1113 if bots:
1114 filtered_builders_and_tests = dict((bot, set(builders_and_tests[bot]))
1115 for bot in bots)
1116 else:
1117 filtered_builders_and_tests = dict(
1118 (bot, set(tests))
1119 for bot, tests in builders_and_tests.iteritems())
1120
1121 # Build up the mapping from tryserver master to bot/test.
1122 out = dict()
1123 for bot, tests in filtered_builders_and_tests.iteritems():
James Robinsoncf552fb2014-11-21 10:56:51 -08001124 out.setdefault("tryserver.client.mojo", {})[bot] = tests
James Robinson646469d2014-10-03 15:33:28 -07001125 return out
1126
1127
1128def CheckChangeOnCommit(input_api, output_api):
1129 results = []
1130 results.extend(_CommonChecks(input_api, output_api))
James Robinson646469d2014-10-03 15:33:28 -07001131 results.extend(input_api.canned_checks.CheckChangeHasBugField(
1132 input_api, output_api))
1133 results.extend(input_api.canned_checks.CheckChangeHasDescription(
1134 input_api, output_api))
1135 return results
1136
1137
1138def GetPreferredTryMasters(project, change):
James Robinson80d418c2014-10-16 16:00:02 -07001139 import re
James Robinson646469d2014-10-03 15:33:28 -07001140 files = change.LocalPaths()
1141
Viet-Trung Luu0d4fef62015-04-09 15:45:05 -07001142 if not files:
James Robinson646469d2014-10-03 15:33:28 -07001143 return {}
1144
James Robinson646469d2014-10-03 15:33:28 -07001145 builders = [
James Robinson160c7e52014-12-02 13:28:44 -08001146 'Mojo Android Builder (dbg) Try',
James Robinson22771532015-01-26 15:38:35 -08001147 'Mojo Android Builder Try',
Mitch Rudominer82392642015-04-15 12:36:28 -07001148 'Mojo Android Builder Tests (dbg) Try',
James Robinson22771532015-01-26 15:38:35 -08001149 'Mojo Linux (dbg) Try',
1150 'Mojo Linux ASan Try',
James Robinson22771532015-01-26 15:38:35 -08001151 'Mojo Linux Try',
James Robinson646469d2014-10-03 15:33:28 -07001152 ]
1153
James Robinson646469d2014-10-03 15:33:28 -07001154 return GetDefaultTryConfigs(builders)
James Robinson53f2b762015-05-12 15:27:46 -07001155
1156def PostUploadHook(cl, change, output_api):
1157 import subprocess
1158 subprocess.check_call(["git", "cl", "try"])
1159 return []