Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Top-level presubmit script for Chromium. | 5 """Top-level presubmit script for Chromium. |
| 6 | 6 |
| 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts | 7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
| 8 for more details about the presubmit API built into depot_tools. | 8 for more details about the presubmit API built into depot_tools. |
| 9 """ | 9 """ |
| 10 | 10 |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 def _CheckDCHECK_IS_ONHasBraces(input_api, output_api): | 421 def _CheckDCHECK_IS_ONHasBraces(input_api, output_api): |
| 422 """Checks to make sure DCHECK_IS_ON() does not skip the braces.""" | 422 """Checks to make sure DCHECK_IS_ON() does not skip the braces.""" |
| 423 errors = [] | 423 errors = [] |
| 424 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))', | 424 pattern = input_api.re.compile(r'DCHECK_IS_ON(?!\(\))', |
| 425 input_api.re.MULTILINE) | 425 input_api.re.MULTILINE) |
| 426 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): | 426 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): |
| 427 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))): | 427 if (not f.LocalPath().endswith(('.cc', '.mm', '.h'))): |
| 428 continue | 428 continue |
| 429 for lnum, line in f.ChangedContents(): | 429 for lnum, line in f.ChangedContents(): |
| 430 if input_api.re.search(pattern, line): | 430 if input_api.re.search(pattern, line): |
| 431 errors.append(output_api.PresubmitError( | 431 errors.append(output_api.PresubmitError( |
| 432 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' + | 432 ('%s:%d: Use of DCHECK_IS_ON() must be written as "#if ' + |
| 433 'DCHECK_IS_ON()", not forgetting the braces.') | 433 'DCHECK_IS_ON()", not forgetting the braces.') |
| 434 % (f.LocalPath(), lnum))) | 434 % (f.LocalPath(), lnum))) |
| 435 return errors | 435 return errors |
| 436 | 436 |
| 437 | 437 |
| 438 def _FindHistogramNameInLine(histogram_name, line): | 438 def _FindHistogramNameInLine(histogram_name, line): |
| 439 """Tries to find a histogram name or prefix in a line.""" | 439 """Tries to find a histogram name or prefix in a line.""" |
| 440 if not "affected-histogram" in line: | 440 if not "affected-histogram" in line: |
| 441 return histogram_name in line | 441 return histogram_name in line |
| 442 # A histogram_suffixes tag type has an affected-histogram name as a prefix of | 442 # A histogram_suffixes tag type has an affected-histogram name as a prefix of |
| 443 # the histogram_name. | 443 # the histogram_name. |
| 444 if not '"' in line: | 444 if not '"' in line: |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 583 return True | 583 return True |
| 584 return False | 584 return False |
| 585 | 585 |
| 586 def CheckForMatch(affected_file, line_num, line, func_name, message, error): | 586 def CheckForMatch(affected_file, line_num, line, func_name, message, error): |
| 587 matched = False | 587 matched = False |
| 588 if func_name[0:1] == '/': | 588 if func_name[0:1] == '/': |
| 589 regex = func_name[1:] | 589 regex = func_name[1:] |
| 590 if input_api.re.search(regex, line): | 590 if input_api.re.search(regex, line): |
| 591 matched = True | 591 matched = True |
| 592 elif func_name in line: | 592 elif func_name in line: |
| 593 matched = True | 593 matched = True |
| 594 if matched: | 594 if matched: |
| 595 problems = warnings; | 595 problems = warnings |
| 596 if error: | 596 if error: |
| 597 problems = errors; | 597 problems = errors |
| 598 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num)) | 598 problems.append(' %s:%d:' % (affected_file.LocalPath(), line_num)) |
| 599 for message_line in message: | 599 for message_line in message: |
| 600 problems.append(' %s' % message_line) | 600 problems.append(' %s' % message_line) |
| 601 | 601 |
| 602 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h')) | 602 file_filter = lambda f: f.LocalPath().endswith(('.mm', '.m', '.h')) |
| 603 for f in input_api.AffectedFiles(file_filter=file_filter): | 603 for f in input_api.AffectedFiles(file_filter=file_filter): |
| 604 for line_num, line in f.ChangedContents(): | 604 for line_num, line in f.ChangedContents(): |
| 605 for func_name, message, error in _BANNED_OBJC_FUNCTIONS: | 605 for func_name, message, error in _BANNED_OBJC_FUNCTIONS: |
| 606 CheckForMatch(f, line_num, line, func_name, message, error) | 606 CheckForMatch(f, line_num, line, func_name, message, error) |
| 607 | 607 |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1392 import checkstyle | 1392 import checkstyle |
| 1393 finally: | 1393 finally: |
| 1394 # Restore sys.path to what it was before. | 1394 # Restore sys.path to what it was before. |
| 1395 sys.path = original_sys_path | 1395 sys.path = original_sys_path |
| 1396 | 1396 |
| 1397 return checkstyle.RunCheckstyle( | 1397 return checkstyle.RunCheckstyle( |
| 1398 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml', | 1398 input_api, output_api, 'tools/android/checkstyle/chromium-style-5.0.xml', |
| 1399 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST) | 1399 black_list=_EXCLUDED_PATHS + input_api.DEFAULT_BLACK_LIST) |
| 1400 | 1400 |
| 1401 | 1401 |
| 1402 def _CheckIpcOwners(input_api, output_api): | |
| 1403 """Checks that affected files involving IPC have an IPC OWNERS rule. | |
| 1404 | |
| 1405 Whether or not a file affects IPC is determined by a simple whitelist of | |
| 1406 filename patterns.""" | |
| 1407 file_patterns = [ | |
| 1408 '*_messages.cc', | |
| 1409 '*_messages*.h', | |
| 1410 '*_param_traits*.*', | |
| 1411 '*.mojom', | |
| 1412 '*_struct_traits*.*', | |
| 1413 '*_type_converters*.*', | |
| 1414 ] | |
| 1415 | |
| 1416 # Dictionary mapping an OWNERS file path to Patterns. | |
| 1417 # Patterns is a dictionary mapping glob patterns (suitable for use in per-file | |
| 1418 # rules ) to a PatternEntry. | |
| 1419 # PatternEntry is a dictionary with two keys: | |
| 1420 # - 'files': the files that are matched by this pattern | |
| 1421 # - 'rules': the per-file rules needed for this pattern | |
| 1422 # For example, if we expect OWNERS file to contain rules for *.mojom and | |
| 1423 # *_struct_traits*.*, Patterns might look like this: | |
| 1424 # { | |
| 1425 # '*.mojom': { | |
| 1426 # 'files': ..., | |
| 1427 # 'rules': [ | |
| 1428 # 'per-file *.mojom=set noparent', | |
| 1429 # 'per-file *.mojom=file://ipc/SECURITY_OWNERS', | |
| 1430 # ], | |
| 1431 # }, | |
| 1432 # '*_struct_traits*.*': { | |
| 1433 # 'files': ..., | |
| 1434 # 'rules': [ | |
| 1435 # 'per-file *_struct_traits*.*=set noparent', | |
| 1436 # 'per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS', | |
| 1437 # ], | |
| 1438 # }, | |
| 1439 # } | |
| 1440 to_check = {} | |
| 1441 | |
| 1442 # Iterate through the affected files to see what we actually need to check | |
| 1443 # for. We should only nag patch authors about per-file rules if a file in that | |
| 1444 # directory would match that pattern. If a directory only contains *.mojom | |
| 1445 # files and no *_messages*.h files, we should only nag about rules for | |
| 1446 # *.mojom files. | |
| 1447 for f in input_api.change.AffectedFiles(): | |
| 1448 for pattern in file_patterns: | |
| 1449 if input_api.fnmatch.fnmatch( | |
| 1450 input_api.os_path.basename(f.LocalPath()), pattern): | |
| 1451 owners_file = input_api.os_path.join( | |
| 1452 input_api.os_path.dirname(f.LocalPath()), 'OWNERS') | |
| 1453 if owners_file not in to_check: | |
| 1454 to_check[owners_file] = {} | |
| 1455 if pattern not in to_check[owners_file]: | |
| 1456 to_check[owners_file][pattern] = { | |
| 1457 'files': [], | |
| 1458 'rules': [ | |
| 1459 'per-file %s=set noparent' % pattern, | |
| 1460 'per-file %s=file://ipc/SECURITY_OWNERS' % pattern, | |
| 1461 ] | |
| 1462 } | |
| 1463 to_check[owners_file][pattern]['files'].append(f) | |
| 1464 break | |
| 1465 | |
| 1466 # Now go through the OWNERS files we collected, filtering out rules that are | |
| 1467 # already present in that OWNERS file. | |
| 1468 for owners_file, patterns in to_check.iteritems(): | |
| 1469 try: | |
| 1470 with file(owners_file) as f: | |
| 1471 for line in f.read().splitlines(): | |
| 1472 for entry in patterns.itervalues(): | |
| 1473 entry['rules'] = [rule for rule in entry['rules'] if rule != line] | |
|
Dirk Pranke
2016/06/18 20:49:26
Maybe
lines = f.read().splitlines()
for entry
dcheng
2016/06/19 00:03:28
I tweaked this slightly and put the lines in a set
| |
| 1474 except IOError: | |
| 1475 # No OWNERS file, so all the rules are definitely missing. | |
| 1476 continue | |
| 1477 | |
| 1478 # All the remaining lines weren't found in OWNERS files, so emit an error. | |
| 1479 errors = [] | |
| 1480 for owners_file, patterns in to_check.iteritems(): | |
| 1481 missing_lines = [] | |
| 1482 files = [] | |
| 1483 for pattern, entry in patterns.iteritems(): | |
| 1484 missing_lines.extend(entry['rules']) | |
| 1485 files.extend([' %s' % f.LocalPath() for f in entry['files']]) | |
| 1486 if missing_lines: | |
| 1487 errors.append( | |
| 1488 '%s is missing the following lines:\n\n%s\n\nfor changed files:\n%s' % | |
| 1489 (owners_file, '\n'.join(missing_lines), '\n'.join(files))) | |
| 1490 | |
| 1491 results = [] | |
| 1492 if errors: | |
| 1493 results.append(output_api.PresubmitError( | |
| 1494 'Found changes to IPC files without a security OWNER!', | |
| 1495 long_text='\n\n'.join(errors))) | |
| 1496 | |
| 1497 return results | |
| 1498 | |
| 1499 | |
| 1402 def _CheckAndroidToastUsage(input_api, output_api): | 1500 def _CheckAndroidToastUsage(input_api, output_api): |
| 1403 """Checks that code uses org.chromium.ui.widget.Toast instead of | 1501 """Checks that code uses org.chromium.ui.widget.Toast instead of |
| 1404 android.widget.Toast (Chromium Toast doesn't force hardware | 1502 android.widget.Toast (Chromium Toast doesn't force hardware |
| 1405 acceleration on low-end devices, saving memory). | 1503 acceleration on low-end devices, saving memory). |
| 1406 """ | 1504 """ |
| 1407 toast_import_pattern = input_api.re.compile( | 1505 toast_import_pattern = input_api.re.compile( |
| 1408 r'^import android\.widget\.Toast;$') | 1506 r'^import android\.widget\.Toast;$') |
| 1409 | 1507 |
| 1410 errors = [] | 1508 errors = [] |
| 1411 | 1509 |
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1855 results.extend(_CheckNoDeprecatedCSS(input_api, output_api)) | 1953 results.extend(_CheckNoDeprecatedCSS(input_api, output_api)) |
| 1856 results.extend(_CheckNoDeprecatedJS(input_api, output_api)) | 1954 results.extend(_CheckNoDeprecatedJS(input_api, output_api)) |
| 1857 results.extend(_CheckParseErrors(input_api, output_api)) | 1955 results.extend(_CheckParseErrors(input_api, output_api)) |
| 1858 results.extend(_CheckForIPCRules(input_api, output_api)) | 1956 results.extend(_CheckForIPCRules(input_api, output_api)) |
| 1859 results.extend(_CheckForCopyrightedCode(input_api, output_api)) | 1957 results.extend(_CheckForCopyrightedCode(input_api, output_api)) |
| 1860 results.extend(_CheckForWindowsLineEndings(input_api, output_api)) | 1958 results.extend(_CheckForWindowsLineEndings(input_api, output_api)) |
| 1861 results.extend(_CheckSingletonInHeaders(input_api, output_api)) | 1959 results.extend(_CheckSingletonInHeaders(input_api, output_api)) |
| 1862 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api)) | 1960 results.extend(_CheckNoDeprecatedCompiledResourcesGYP(input_api, output_api)) |
| 1863 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api)) | 1961 results.extend(_CheckPydepsNeedsUpdating(input_api, output_api)) |
| 1864 results.extend(_CheckJavaStyle(input_api, output_api)) | 1962 results.extend(_CheckJavaStyle(input_api, output_api)) |
| 1963 results.extend(_CheckIpcOwners(input_api, output_api)) | |
| 1865 | 1964 |
| 1866 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()): | 1965 if any('PRESUBMIT.py' == f.LocalPath() for f in input_api.AffectedFiles()): |
| 1867 results.extend(input_api.canned_checks.RunUnitTestsInDirectory( | 1966 results.extend(input_api.canned_checks.RunUnitTestsInDirectory( |
| 1868 input_api, output_api, | 1967 input_api, output_api, |
| 1869 input_api.PresubmitLocalPath(), | 1968 input_api.PresubmitLocalPath(), |
| 1870 whitelist=[r'^PRESUBMIT_test\.py$'])) | 1969 whitelist=[r'^PRESUBMIT_test\.py$'])) |
| 1871 return results | 1970 return results |
| 1872 | 1971 |
| 1873 | 1972 |
| 1874 def _CheckAuthorizedAuthor(input_api, output_api): | 1973 def _CheckAuthorizedAuthor(input_api, output_api): |
| 1875 """For non-googler/chromites committers, verify the author's email address is | 1974 """For non-googler/chromites committers, verify the author's email address is |
| 1876 in AUTHORS. | 1975 in AUTHORS. |
| 1877 """ | 1976 """ |
| 1878 # TODO(maruel): Add it to input_api? | |
| 1879 import fnmatch | |
| 1880 | |
| 1881 author = input_api.change.author_email | 1977 author = input_api.change.author_email |
| 1882 if not author: | 1978 if not author: |
| 1883 input_api.logging.info('No author, skipping AUTHOR check') | 1979 input_api.logging.info('No author, skipping AUTHOR check') |
| 1884 return [] | 1980 return [] |
| 1885 authors_path = input_api.os_path.join( | 1981 authors_path = input_api.os_path.join( |
| 1886 input_api.PresubmitLocalPath(), 'AUTHORS') | 1982 input_api.PresubmitLocalPath(), 'AUTHORS') |
| 1887 valid_authors = ( | 1983 valid_authors = ( |
| 1888 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line) | 1984 input_api.re.match(r'[^#]+\s+\<(.+?)\>\s*$', line) |
| 1889 for line in open(authors_path)) | 1985 for line in open(authors_path)) |
| 1890 valid_authors = [item.group(1).lower() for item in valid_authors if item] | 1986 valid_authors = [item.group(1).lower() for item in valid_authors if item] |
| 1891 if not any(fnmatch.fnmatch(author.lower(), valid) for valid in valid_authors): | 1987 if not any(input_api.fnmatch.fnmatch(author.lower(), valid) |
| 1988 for valid in valid_authors): | |
| 1892 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors)) | 1989 input_api.logging.info('Valid authors are %s', ', '.join(valid_authors)) |
| 1893 return [output_api.PresubmitPromptWarning( | 1990 return [output_api.PresubmitPromptWarning( |
| 1894 ('%s is not in AUTHORS file. If you are a new contributor, please visit' | 1991 ('%s is not in AUTHORS file. If you are a new contributor, please visit' |
| 1895 '\n' | 1992 '\n' |
| 1896 'http://www.chromium.org/developers/contributing-code and read the ' | 1993 'http://www.chromium.org/developers/contributing-code and read the ' |
| 1897 '"Legal" section\n' | 1994 '"Legal" section\n' |
| 1898 'If you are a chromite, verify the contributor signed the CLA.') % | 1995 'If you are a chromite, verify the contributor signed the CLA.') % |
| 1899 author)] | 1996 author)] |
| 1900 return [] | 1997 return [] |
| 1901 | 1998 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2122 results.extend(input_api.canned_checks.CheckTreeIsOpen( | 2219 results.extend(input_api.canned_checks.CheckTreeIsOpen( |
| 2123 input_api, | 2220 input_api, |
| 2124 output_api, | 2221 output_api, |
| 2125 json_url='http://chromium-status.appspot.com/current?format=json')) | 2222 json_url='http://chromium-status.appspot.com/current?format=json')) |
| 2126 | 2223 |
| 2127 results.extend(input_api.canned_checks.CheckChangeHasBugField( | 2224 results.extend(input_api.canned_checks.CheckChangeHasBugField( |
| 2128 input_api, output_api)) | 2225 input_api, output_api)) |
| 2129 results.extend(input_api.canned_checks.CheckChangeHasDescription( | 2226 results.extend(input_api.canned_checks.CheckChangeHasDescription( |
| 2130 input_api, output_api)) | 2227 input_api, output_api)) |
| 2131 return results | 2228 return results |
| OLD | NEW |