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