# Copyright 2015 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Top-level presubmit script for catapult. See https://www.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into depot_tools. """ import re import sys _EXCLUDED_PATHS = ( r'(.*[\\/])?\.git[\\/].*', r'.+\.png$', r'.+\.svg$', r'.+\.skp$', r'.+\.gypi$', r'.+\.gyp$', r'.+\.gn$', r'.*\.gitignore$', r'.*codereview.settings$', r'.*AUTHOR$', r'^CONTRIBUTORS\.md$', r'.*LICENSE$', r'.*OWNERS$', r'.*README\.md$', r'^dashboard[\\/]dashboard[\\/]templates[\\/].*', r'^experimental[\\/]heatmap[\\/].*', r'^perf_insights[\\/]test_data[\\/].*', r'^perf_insights[\\/]third_party[\\/].*', r'^third_party[\\/].*', r'^tracing[\\/]\.allow-devtools-save$', r'^tracing[\\/]bower\.json$', r'^tracing[\\/]\.bowerrc$', r'^tracing[\\/]tracing_examples[\\/]string_convert\.js$', r'^tracing[\\/]test_data[\\/].*', r'^tracing[\\/]third_party[\\/].*', r'^telemetry[\\/]support[\\/]html_output[\\/]results-template.html', ) _CATAPULT_BUG_ID_RE = re.compile(r'#[1-9]\d*') _RIETVELD_BUG_ID_RE = re.compile(r'[1-9]\d*') _RIETVELD_REPOSITORY_NAMES = frozenset({'chromium', 'v8'}) def CheckChangeLogBug(input_api, output_api): # Show a presubmit message if there is no BUG= line. if input_api.change.BUG is None: return [output_api.PresubmitNotifyResult( 'If this change has associated Catapult and/or Rietveld bug(s), add a ' '"BUG=(, )*" line to the patch description where can ' 'be one of the following: catapult:#NNNN, ' + ', '.join('%s:NNNNNN' % n for n in _RIETVELD_REPOSITORY_NAMES) + '.')] # Throw a presubmit error if the BUG= line is provided but empty. if input_api.change.BUG.strip() == '': return [output_api.PresubmitError( 'Empty BUG= line. Either remove it, or, preferably, change it to ' '"BUG=(, )*" where can be one of the following: ' + 'catapult:#NNNN, ' + ', '.join('%s:NNNNNN' % n for n in _RIETVELD_REPOSITORY_NAMES) + '.')] # Check that each bug in the BUG= line has the correct format. error_messages = [] catapult_bug_provided = False append_repository_order_error = False for index, bug in enumerate(input_api.change.BUG.split(',')): if index > 0: bug = bug.lstrip() # Allow spaces after commas. # Check if the bug can be split into a repository name and a bug ID (e.g. # 'catapult:#1234' -> 'catapult' and '#1234'). bug_parts = bug.split(':') if len(bug_parts) != 2: error_messages.append('Invalid bug "%s". Bugs should be provided in the ' '":" format.' % bug) continue repository_name, bug_id = bug_parts if repository_name == 'catapult': if not _CATAPULT_BUG_ID_RE.match(bug_id): error_messages.append('Invalid bug "%s". Bugs in the Catapult ' 'repository should be provided in the ' '"catapult:#NNNN" format.' % bug) catapult_bug_provided = True elif repository_name in _RIETVELD_REPOSITORY_NAMES: if not _RIETVELD_BUG_ID_RE.match(bug_id): error_messages.append('Invalid bug "%s". Bugs in the Rietveld %s ' 'repository should be provided in the ' '"%s:NNNNNN" format.' % (bug, repository_name, repository_name)) if catapult_bug_provided: append_repository_order_error = True else: error_messages.append('Invalid bug "%s". Unknown repository "%s".' % ( bug, repository_name)) if append_repository_order_error: error_messages.append('Please list Rietveld bugs (' + ', '.join('%s:NNNNNN' % n for n in _RIETVELD_REPOSITORY_NAMES) + ') before Catapult bugs (catapult:#NNNN) so ' 'that Rietveld would display them as hyperlinks.') return map(output_api.PresubmitError, error_messages) def CheckChange(input_api, output_api): results = [] try: sys.path += [input_api.PresubmitLocalPath()] from catapult_build import js_checks from catapult_build import html_checks from catapult_build import repo_checks results += input_api.canned_checks.PanProjectChecks( input_api, output_api, excluded_paths=_EXCLUDED_PATHS) results += CheckChangeLogBug(input_api, output_api) results += js_checks.RunChecks( input_api, output_api, excluded_paths=_EXCLUDED_PATHS) results += html_checks.RunChecks( input_api, output_api, excluded_paths=_EXCLUDED_PATHS) results += repo_checks.RunChecks(input_api, output_api) finally: sys.path.remove(input_api.PresubmitLocalPath()) return results def CheckChangeOnUpload(input_api, output_api): return CheckChange(input_api, output_api) def CheckChangeOnCommit(input_api, output_api): return CheckChange(input_api, output_api)