| # Copyright 2011 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Presubmit script for changes affecting chrome/ |
| |
| See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
| for more details about the presubmit API built into depot_tools. |
| """ |
| |
| |
| import re |
| |
| INCLUDE_CPP_FILES_ONLY = ( |
| r'.*\.(cc|h)$', |
| ) |
| |
| INCLUDE_SOURCE_FILES_ONLY = ( |
| r'.*\.(c|cc|cpp|h|m|mm)$', |
| ) |
| |
| EXCLUDE = ( |
| # Objective C confuses everything. |
| r'.*cocoa.*', |
| r'.*_mac\.(cc|h)$', |
| r'.*_mac_.*', |
| # All the messages files do weird multiple include trickery |
| r'.*_messages.*\.h$', |
| # Autogenerated window resources files are off limits |
| r'.*resource.h$', |
| # Header trickery |
| r'.*-inl\.h$', |
| # Has safe printf usage that cpplint complains about |
| r'safe_browsing_util\.cc$', |
| ) |
| |
| def _CheckChangeLintsClean(input_api, output_api): |
| """Makes sure that the chrome/ code is cpplint clean.""" |
| files_to_skip = input_api.DEFAULT_FILES_TO_SKIP + EXCLUDE |
| sources = lambda x: input_api.FilterSourceFile( |
| x, files_to_check=INCLUDE_CPP_FILES_ONLY, files_to_skip=files_to_skip) |
| return input_api.canned_checks.CheckChangeLintsClean( |
| input_api, output_api, sources) |
| |
| |
| def _CheckNoContentUnitTestsInChrome(input_api, output_api): |
| """Makes sure that no unit tests from content/ are included in unit_tests.""" |
| problems = [] |
| for f in input_api.AffectedFiles(): |
| if not f.LocalPath().endswith('BUILD.gn'): |
| continue |
| |
| for line_num, line in f.ChangedContents(): |
| m = re.search(r"'(.*\/content\/.*unittest.*)'", line) |
| if m: |
| problems.append(m.group(1)) |
| |
| if not problems: |
| return [] |
| return [output_api.PresubmitPromptWarning( |
| 'Unit tests located in content/ should be added to the ' + |
| 'content_unittests target.', |
| items=problems)] |
| |
| |
| def _CheckNoIsAppleBuildFlagsInChromeFile(input_api, f): |
| """Check for IS_APPLE in a given file in chrome/.""" |
| preprocessor_statement = input_api.re.compile(r'^\s*#') |
| apple_buildflag = input_api.re.compile(r'BUILDFLAG\(IS_APPLE\)') |
| results = [] |
| for lnum, line in f.ChangedContents(): |
| if preprocessor_statement.search(line) and apple_buildflag.search(line): |
| results.append(' %s:%d' % (f.LocalPath(), lnum)) |
| |
| return results |
| |
| |
| def _CheckNoIsAppleBuildFlagsInChrome(input_api, output_api): |
| """Check for IS_APPLE which isn't used in chrome/.""" |
| apple_buildflags = [] |
| def SourceFilter(affected_file): |
| return input_api.FilterSourceFile(affected_file, INCLUDE_SOURCE_FILES_ONLY, |
| input_api.DEFAULT_FILES_TO_SKIP) |
| for f in input_api.AffectedSourceFiles(SourceFilter): |
| apple_buildflags.extend(_CheckNoIsAppleBuildFlagsInChromeFile(input_api, f)) |
| |
| if not apple_buildflags: |
| return [] |
| |
| return [output_api.PresubmitError( |
| 'IS_APPLE is not used in chrome/ but found in:\n', apple_buildflags)] |
| |
| |
| def _CheckNoIsIOSBuildFlagsInChromeFile(input_api, f): |
| """Check for IS_IOS in a given file in chrome/.""" |
| preprocessor_statement = input_api.re.compile(r'^\s*#') |
| ios_buildflag = input_api.re.compile(r'BUILDFLAG\(IS_IOS\)') |
| results = [] |
| for lnum, line in f.ChangedContents(): |
| if preprocessor_statement.search(line) and ios_buildflag.search(line): |
| results.append(' %s:%d' % (f.LocalPath(), lnum)) |
| |
| return results |
| |
| |
| def _CheckNoIsIOSBuildFlagsInChrome(input_api, output_api): |
| """Check for IS_IOS which isn't used in chrome/.""" |
| ios_buildflags = [] |
| def SourceFilter(affected_file): |
| return input_api.FilterSourceFile(affected_file, INCLUDE_SOURCE_FILES_ONLY, |
| input_api.DEFAULT_FILES_TO_SKIP) |
| for f in input_api.AffectedSourceFiles(SourceFilter): |
| ios_buildflags.extend(_CheckNoIsIOSBuildFlagsInChromeFile(input_api, f)) |
| |
| if not ios_buildflags: |
| return [] |
| |
| return [output_api.PresubmitError( |
| 'IS_IOS is not used in chrome/ but found in:\n', ios_buildflags)] |
| |
| |
| def _CheckBreakingInstallerVersionBumpNeeded(input_api, output_api): |
| files = [] |
| breaking_version_installer_updated = False |
| |
| def _FilterFile(affected_file): |
| return input_api.FilterSourceFile( |
| affected_file, |
| files_to_check=input_api.DEFAULT_FILES_TO_CHECK + (r'.*\.release',)) |
| for f in input_api.AffectedSourceFiles(_FilterFile): |
| # Normalize the local path to Linux-style path separators so that the path |
| # comparisons work on Windows as well. |
| local_path = f.LocalPath().replace('\\', '/') |
| breaking_version_installer_updated |= (local_path == |
| 'chrome/installer/setup/last_breaking_installer_version.cc') |
| if (local_path == 'chrome/installer/mini_installer/chrome.release' or |
| local_path.startswith('chrome/test/mini_installer')): |
| files.append(local_path) |
| |
| if files and not breaking_version_installer_updated: |
| return [output_api.PresubmitPromptWarning(''' |
| Update chrome/installer/setup/last_breaking_installer_version.cc if the changes |
| found in the following files might break make downgrades not possible beyond |
| this browser's version.''', items=files)] |
| |
| if not files and breaking_version_installer_updated: |
| return [output_api.PresubmitPromptWarning(''' |
| No installer breaking changes detected but |
| chrome/installer/setup/last_breaking_installer_version.cc was updated. Please |
| update chrome/installer/PRESUBMIT.py if more files need to be watched for |
| breaking installer changes.''')] |
| |
| return [] |
| |
| |
| def _CommonChecks(input_api, output_api): |
| """Checks common to both upload and commit.""" |
| results = [] |
| results.extend(_CheckNoContentUnitTestsInChrome(input_api, output_api)) |
| results.extend(_CheckNoIsAppleBuildFlagsInChrome(input_api, output_api)) |
| results.extend(_CheckNoIsIOSBuildFlagsInChrome(input_api, output_api)) |
| results.extend(_CheckBreakingInstallerVersionBumpNeeded(input_api, |
| output_api)) |
| return results |
| |
| |
| def CheckChangeOnUpload(input_api, output_api): |
| results = [] |
| results.extend(_CommonChecks(input_api, output_api)) |
| results.extend(_CheckChangeLintsClean(input_api, output_api)) |
| return results |
| |
| |
| def CheckChangeOnCommit(input_api, output_api): |
| results = [] |
| results.extend(_CommonChecks(input_api, output_api)) |
| return results |