1*d9f75844SAndroid Build Coastguard Worker#!/usr/bin/env vpython3 2*d9f75844SAndroid Build Coastguard Worker 3*d9f75844SAndroid Build Coastguard Worker# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 4*d9f75844SAndroid Build Coastguard Worker# 5*d9f75844SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license 6*d9f75844SAndroid Build Coastguard Worker# that can be found in the LICENSE file in the root of the source 7*d9f75844SAndroid Build Coastguard Worker# tree. An additional intellectual property rights grant can be found 8*d9f75844SAndroid Build Coastguard Worker# in the file PATENTS. All contributing project authors may 9*d9f75844SAndroid Build Coastguard Worker# be found in the AUTHORS file in the root of the source tree. 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Workerimport json 12*d9f75844SAndroid Build Coastguard Workerimport os 13*d9f75844SAndroid Build Coastguard Workerimport re 14*d9f75844SAndroid Build Coastguard Workerimport sys 15*d9f75844SAndroid Build Coastguard Workerfrom collections import defaultdict 16*d9f75844SAndroid Build Coastguard Workerfrom contextlib import contextmanager 17*d9f75844SAndroid Build Coastguard Worker 18*d9f75844SAndroid Build Coastguard Worker# Runs PRESUBMIT.py in py3 mode by git cl presubmit. 19*d9f75844SAndroid Build Coastguard WorkerUSE_PYTHON3 = True 20*d9f75844SAndroid Build Coastguard Worker 21*d9f75844SAndroid Build Coastguard Worker# Files and directories that are *skipped* by cpplint in the presubmit script. 22*d9f75844SAndroid Build Coastguard WorkerCPPLINT_EXCEPTIONS = [ 23*d9f75844SAndroid Build Coastguard Worker 'api/video_codecs/video_decoder.h', 24*d9f75844SAndroid Build Coastguard Worker 'common_types.cc', 25*d9f75844SAndroid Build Coastguard Worker 'common_types.h', 26*d9f75844SAndroid Build Coastguard Worker 'examples/objc', 27*d9f75844SAndroid Build Coastguard Worker 'media/base/stream_params.h', 28*d9f75844SAndroid Build Coastguard Worker 'media/base/video_common.h', 29*d9f75844SAndroid Build Coastguard Worker 'modules/audio_coding', 30*d9f75844SAndroid Build Coastguard Worker 'modules/audio_device', 31*d9f75844SAndroid Build Coastguard Worker 'modules/audio_processing', 32*d9f75844SAndroid Build Coastguard Worker 'modules/desktop_capture', 33*d9f75844SAndroid Build Coastguard Worker 'modules/include/module_common_types.h', 34*d9f75844SAndroid Build Coastguard Worker 'modules/utility', 35*d9f75844SAndroid Build Coastguard Worker 'modules/video_capture', 36*d9f75844SAndroid Build Coastguard Worker 'p2p/base/pseudo_tcp.cc', 37*d9f75844SAndroid Build Coastguard Worker 'p2p/base/pseudo_tcp.h', 38*d9f75844SAndroid Build Coastguard Worker 'PRESUBMIT.py', 39*d9f75844SAndroid Build Coastguard Worker 'presubmit_test_mocks.py', 40*d9f75844SAndroid Build Coastguard Worker 'presubmit_test.py', 41*d9f75844SAndroid Build Coastguard Worker 'rtc_base', 42*d9f75844SAndroid Build Coastguard Worker 'sdk/android/src/jni', 43*d9f75844SAndroid Build Coastguard Worker 'sdk/objc', 44*d9f75844SAndroid Build Coastguard Worker 'system_wrappers', 45*d9f75844SAndroid Build Coastguard Worker 'test', 46*d9f75844SAndroid Build Coastguard Worker 'tools_webrtc', 47*d9f75844SAndroid Build Coastguard Worker 'voice_engine', 48*d9f75844SAndroid Build Coastguard Worker] 49*d9f75844SAndroid Build Coastguard Worker 50*d9f75844SAndroid Build Coastguard Worker# These filters will always be removed, even if the caller specifies a filter 51*d9f75844SAndroid Build Coastguard Worker# set, as they are problematic or broken in some way. 52*d9f75844SAndroid Build Coastguard Worker# 53*d9f75844SAndroid Build Coastguard Worker# Justifications for each filter: 54*d9f75844SAndroid Build Coastguard Worker# - build/c++11 : Rvalue ref checks are unreliable (false positives), 55*d9f75844SAndroid Build Coastguard Worker# include file and feature blocklists are 56*d9f75844SAndroid Build Coastguard Worker# google3-specific. 57*d9f75844SAndroid Build Coastguard Worker# - runtime/references : Mutable references are not banned by the Google 58*d9f75844SAndroid Build Coastguard Worker# C++ style guide anymore (starting from May 2020). 59*d9f75844SAndroid Build Coastguard Worker# - whitespace/operators: Same as above (doesn't seem sufficient to eliminate 60*d9f75844SAndroid Build Coastguard Worker# all move-related errors). 61*d9f75844SAndroid Build Coastguard WorkerDISABLED_LINT_FILTERS = [ 62*d9f75844SAndroid Build Coastguard Worker '-build/c++11', 63*d9f75844SAndroid Build Coastguard Worker '-runtime/references', 64*d9f75844SAndroid Build Coastguard Worker '-whitespace/operators', 65*d9f75844SAndroid Build Coastguard Worker] 66*d9f75844SAndroid Build Coastguard Worker 67*d9f75844SAndroid Build Coastguard Worker# List of directories of "supported" native APIs. That means changes to headers 68*d9f75844SAndroid Build Coastguard Worker# will be done in a compatible way following this scheme: 69*d9f75844SAndroid Build Coastguard Worker# 1. Non-breaking changes are made. 70*d9f75844SAndroid Build Coastguard Worker# 2. The old APIs as marked as deprecated (with comments). 71*d9f75844SAndroid Build Coastguard Worker# 3. Deprecation is announced to [email protected] and 72*d9f75844SAndroid Build Coastguard Worker# [email protected] (internal list). 73*d9f75844SAndroid Build Coastguard Worker# 4. (later) The deprecated APIs are removed. 74*d9f75844SAndroid Build Coastguard WorkerNATIVE_API_DIRS = ( 75*d9f75844SAndroid Build Coastguard Worker 'api', # All subdirectories of api/ are included as well. 76*d9f75844SAndroid Build Coastguard Worker 'media/base', 77*d9f75844SAndroid Build Coastguard Worker 'media/engine', 78*d9f75844SAndroid Build Coastguard Worker 'modules/audio_device/include', 79*d9f75844SAndroid Build Coastguard Worker 'pc', 80*d9f75844SAndroid Build Coastguard Worker) 81*d9f75844SAndroid Build Coastguard Worker 82*d9f75844SAndroid Build Coastguard Worker# These directories should not be used but are maintained only to avoid breaking 83*d9f75844SAndroid Build Coastguard Worker# some legacy downstream code. 84*d9f75844SAndroid Build Coastguard WorkerLEGACY_API_DIRS = ( 85*d9f75844SAndroid Build Coastguard Worker 'common_audio/include', 86*d9f75844SAndroid Build Coastguard Worker 'modules/audio_coding/include', 87*d9f75844SAndroid Build Coastguard Worker 'modules/audio_processing/include', 88*d9f75844SAndroid Build Coastguard Worker 'modules/congestion_controller/include', 89*d9f75844SAndroid Build Coastguard Worker 'modules/include', 90*d9f75844SAndroid Build Coastguard Worker 'modules/remote_bitrate_estimator/include', 91*d9f75844SAndroid Build Coastguard Worker 'modules/rtp_rtcp/include', 92*d9f75844SAndroid Build Coastguard Worker 'modules/rtp_rtcp/source', 93*d9f75844SAndroid Build Coastguard Worker 'modules/utility/include', 94*d9f75844SAndroid Build Coastguard Worker 'modules/video_coding/codecs/h264/include', 95*d9f75844SAndroid Build Coastguard Worker 'modules/video_coding/codecs/vp8/include', 96*d9f75844SAndroid Build Coastguard Worker 'modules/video_coding/codecs/vp9/include', 97*d9f75844SAndroid Build Coastguard Worker 'modules/video_coding/include', 98*d9f75844SAndroid Build Coastguard Worker 'rtc_base', 99*d9f75844SAndroid Build Coastguard Worker 'system_wrappers/include', 100*d9f75844SAndroid Build Coastguard Worker) 101*d9f75844SAndroid Build Coastguard Worker 102*d9f75844SAndroid Build Coastguard Worker# NOTE: The set of directories in API_DIRS should be the same as those 103*d9f75844SAndroid Build Coastguard Worker# listed in the table in native-api.md. 104*d9f75844SAndroid Build Coastguard WorkerAPI_DIRS = NATIVE_API_DIRS[:] + LEGACY_API_DIRS[:] 105*d9f75844SAndroid Build Coastguard Worker 106*d9f75844SAndroid Build Coastguard Worker# TARGET_RE matches a GN target, and extracts the target name and the contents. 107*d9f75844SAndroid Build Coastguard WorkerTARGET_RE = re.compile( 108*d9f75844SAndroid Build Coastguard Worker r'(?P<indent>\s*)(?P<target_type>\w+)\("(?P<target_name>\w+)"\) {' 109*d9f75844SAndroid Build Coastguard Worker r'(?P<target_contents>.*?)' 110*d9f75844SAndroid Build Coastguard Worker r'(?P=indent)}', re.MULTILINE | re.DOTALL) 111*d9f75844SAndroid Build Coastguard Worker 112*d9f75844SAndroid Build Coastguard Worker# SOURCES_RE matches a block of sources inside a GN target. 113*d9f75844SAndroid Build Coastguard WorkerSOURCES_RE = re.compile(r'sources \+?= \[(?P<sources>.*?)\]', 114*d9f75844SAndroid Build Coastguard Worker re.MULTILINE | re.DOTALL) 115*d9f75844SAndroid Build Coastguard Worker 116*d9f75844SAndroid Build Coastguard Worker# DEPS_RE matches a block of sources inside a GN target. 117*d9f75844SAndroid Build Coastguard WorkerDEPS_RE = re.compile(r'\bdeps \+?= \[(?P<deps>.*?)\]', 118*d9f75844SAndroid Build Coastguard Worker re.MULTILINE | re.DOTALL) 119*d9f75844SAndroid Build Coastguard Worker 120*d9f75844SAndroid Build Coastguard Worker# FILE_PATH_RE matches a file path. 121*d9f75844SAndroid Build Coastguard WorkerFILE_PATH_RE = re.compile(r'"(?P<file_path>(\w|\/)+)(?P<extension>\.\w+)"') 122*d9f75844SAndroid Build Coastguard Worker 123*d9f75844SAndroid Build Coastguard Worker 124*d9f75844SAndroid Build Coastguard Workerdef FindSrcDirPath(starting_dir): 125*d9f75844SAndroid Build Coastguard Worker """Returns the abs path to the src/ dir of the project.""" 126*d9f75844SAndroid Build Coastguard Worker src_dir = starting_dir 127*d9f75844SAndroid Build Coastguard Worker while os.path.basename(src_dir) != 'src': 128*d9f75844SAndroid Build Coastguard Worker src_dir = os.path.normpath(os.path.join(src_dir, os.pardir)) 129*d9f75844SAndroid Build Coastguard Worker return src_dir 130*d9f75844SAndroid Build Coastguard Worker 131*d9f75844SAndroid Build Coastguard Worker 132*d9f75844SAndroid Build Coastguard Worker@contextmanager 133*d9f75844SAndroid Build Coastguard Workerdef _AddToPath(*paths): 134*d9f75844SAndroid Build Coastguard Worker original_sys_path = sys.path 135*d9f75844SAndroid Build Coastguard Worker sys.path.extend(paths) 136*d9f75844SAndroid Build Coastguard Worker try: 137*d9f75844SAndroid Build Coastguard Worker yield 138*d9f75844SAndroid Build Coastguard Worker finally: 139*d9f75844SAndroid Build Coastguard Worker # Restore sys.path to what it was before. 140*d9f75844SAndroid Build Coastguard Worker sys.path = original_sys_path 141*d9f75844SAndroid Build Coastguard Worker 142*d9f75844SAndroid Build Coastguard Worker 143*d9f75844SAndroid Build Coastguard Workerdef VerifyNativeApiHeadersListIsValid(input_api, output_api): 144*d9f75844SAndroid Build Coastguard Worker """Ensures the list of native API header directories is up to date.""" 145*d9f75844SAndroid Build Coastguard Worker non_existing_paths = [] 146*d9f75844SAndroid Build Coastguard Worker native_api_full_paths = [ 147*d9f75844SAndroid Build Coastguard Worker input_api.os_path.join(input_api.PresubmitLocalPath(), *path.split('/')) 148*d9f75844SAndroid Build Coastguard Worker for path in API_DIRS 149*d9f75844SAndroid Build Coastguard Worker ] 150*d9f75844SAndroid Build Coastguard Worker for path in native_api_full_paths: 151*d9f75844SAndroid Build Coastguard Worker if not os.path.isdir(path): 152*d9f75844SAndroid Build Coastguard Worker non_existing_paths.append(path) 153*d9f75844SAndroid Build Coastguard Worker if non_existing_paths: 154*d9f75844SAndroid Build Coastguard Worker return [ 155*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 156*d9f75844SAndroid Build Coastguard Worker 'Directories to native API headers have changed which has made ' 157*d9f75844SAndroid Build Coastguard Worker 'the list in PRESUBMIT.py outdated.\nPlease update it to the ' 158*d9f75844SAndroid Build Coastguard Worker 'current location of our native APIs.', non_existing_paths) 159*d9f75844SAndroid Build Coastguard Worker ] 160*d9f75844SAndroid Build Coastguard Worker return [] 161*d9f75844SAndroid Build Coastguard Worker 162*d9f75844SAndroid Build Coastguard Worker 163*d9f75844SAndroid Build Coastguard WorkerAPI_CHANGE_MSG = """ 164*d9f75844SAndroid Build Coastguard WorkerYou seem to be changing native API header files. Please make sure that you: 165*d9f75844SAndroid Build Coastguard Worker 1. Make compatible changes that don't break existing clients. Usually 166*d9f75844SAndroid Build Coastguard Worker this is done by keeping the existing method signatures unchanged. 167*d9f75844SAndroid Build Coastguard Worker 2. Mark the old stuff as deprecated (use the ABSL_DEPRECATED macro). 168*d9f75844SAndroid Build Coastguard Worker 3. Create a timeline and plan for when the deprecated stuff will be 169*d9f75844SAndroid Build Coastguard Worker removed. (The amount of time we give users to change their code 170*d9f75844SAndroid Build Coastguard Worker should be informed by how much work it is for them. If they just 171*d9f75844SAndroid Build Coastguard Worker need to replace one name with another or something equally 172*d9f75844SAndroid Build Coastguard Worker simple, 1-2 weeks might be good; if they need to do serious work, 173*d9f75844SAndroid Build Coastguard Worker up to 3 months may be called for.) 174*d9f75844SAndroid Build Coastguard Worker 4. Update/inform existing downstream code owners to stop using the 175*d9f75844SAndroid Build Coastguard Worker deprecated stuff. (Send announcements to 176*d9f75844SAndroid Build Coastguard Worker [email protected] and [email protected].) 177*d9f75844SAndroid Build Coastguard Worker 5. Remove the deprecated stuff, once the agreed-upon amount of time 178*d9f75844SAndroid Build Coastguard Worker has passed. 179*d9f75844SAndroid Build Coastguard WorkerRelated files: 180*d9f75844SAndroid Build Coastguard Worker""" 181*d9f75844SAndroid Build Coastguard Worker 182*d9f75844SAndroid Build Coastguard Worker 183*d9f75844SAndroid Build Coastguard Workerdef CheckNativeApiHeaderChanges(input_api, output_api): 184*d9f75844SAndroid Build Coastguard Worker """Checks to remind proper changing of native APIs.""" 185*d9f75844SAndroid Build Coastguard Worker files = [] 186*d9f75844SAndroid Build Coastguard Worker source_file_filter = lambda x: input_api.FilterSourceFile( 187*d9f75844SAndroid Build Coastguard Worker x, files_to_check=[r'.+\.(gn|gni|h)$']) 188*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(source_file_filter): 189*d9f75844SAndroid Build Coastguard Worker for path in API_DIRS: 190*d9f75844SAndroid Build Coastguard Worker dn = os.path.dirname(f.LocalPath()) 191*d9f75844SAndroid Build Coastguard Worker if path == 'api': 192*d9f75844SAndroid Build Coastguard Worker # Special case: Subdirectories included. 193*d9f75844SAndroid Build Coastguard Worker if dn == 'api' or dn.startswith('api/'): 194*d9f75844SAndroid Build Coastguard Worker files.append(f.LocalPath()) 195*d9f75844SAndroid Build Coastguard Worker else: 196*d9f75844SAndroid Build Coastguard Worker # Normal case: Subdirectories not included. 197*d9f75844SAndroid Build Coastguard Worker if dn == path: 198*d9f75844SAndroid Build Coastguard Worker files.append(f.LocalPath()) 199*d9f75844SAndroid Build Coastguard Worker 200*d9f75844SAndroid Build Coastguard Worker if files: 201*d9f75844SAndroid Build Coastguard Worker return [output_api.PresubmitNotifyResult(API_CHANGE_MSG, files)] 202*d9f75844SAndroid Build Coastguard Worker return [] 203*d9f75844SAndroid Build Coastguard Worker 204*d9f75844SAndroid Build Coastguard Worker 205*d9f75844SAndroid Build Coastguard Workerdef CheckNoIOStreamInHeaders(input_api, output_api, source_file_filter): 206*d9f75844SAndroid Build Coastguard Worker """Checks to make sure no .h files include <iostream>.""" 207*d9f75844SAndroid Build Coastguard Worker files = [] 208*d9f75844SAndroid Build Coastguard Worker pattern = input_api.re.compile(r'^#include\s*<iostream>', 209*d9f75844SAndroid Build Coastguard Worker input_api.re.MULTILINE) 210*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: (input_api.FilterSourceFile(x) and source_file_filter( 211*d9f75844SAndroid Build Coastguard Worker x)) 212*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 213*d9f75844SAndroid Build Coastguard Worker if not f.LocalPath().endswith('.h'): 214*d9f75844SAndroid Build Coastguard Worker continue 215*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(f) 216*d9f75844SAndroid Build Coastguard Worker if pattern.search(contents): 217*d9f75844SAndroid Build Coastguard Worker files.append(f) 218*d9f75844SAndroid Build Coastguard Worker 219*d9f75844SAndroid Build Coastguard Worker if len(files) > 0: 220*d9f75844SAndroid Build Coastguard Worker return [ 221*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 222*d9f75844SAndroid Build Coastguard Worker 'Do not #include <iostream> in header files, since it inserts ' 223*d9f75844SAndroid Build Coastguard Worker 'static initialization into every file including the header. ' 224*d9f75844SAndroid Build Coastguard Worker 'Instead, #include <ostream>. See http://crbug.com/94794', files) 225*d9f75844SAndroid Build Coastguard Worker ] 226*d9f75844SAndroid Build Coastguard Worker return [] 227*d9f75844SAndroid Build Coastguard Worker 228*d9f75844SAndroid Build Coastguard Worker 229*d9f75844SAndroid Build Coastguard Workerdef CheckNoPragmaOnce(input_api, output_api, source_file_filter): 230*d9f75844SAndroid Build Coastguard Worker """Make sure that banned functions are not used.""" 231*d9f75844SAndroid Build Coastguard Worker files = [] 232*d9f75844SAndroid Build Coastguard Worker pattern = input_api.re.compile(r'^#pragma\s+once', input_api.re.MULTILINE) 233*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: (input_api.FilterSourceFile(x) and source_file_filter( 234*d9f75844SAndroid Build Coastguard Worker x)) 235*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 236*d9f75844SAndroid Build Coastguard Worker if not f.LocalPath().endswith('.h'): 237*d9f75844SAndroid Build Coastguard Worker continue 238*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(f) 239*d9f75844SAndroid Build Coastguard Worker if pattern.search(contents): 240*d9f75844SAndroid Build Coastguard Worker files.append(f) 241*d9f75844SAndroid Build Coastguard Worker 242*d9f75844SAndroid Build Coastguard Worker if files: 243*d9f75844SAndroid Build Coastguard Worker return [ 244*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 245*d9f75844SAndroid Build Coastguard Worker 'Do not use #pragma once in header files.\n' 246*d9f75844SAndroid Build Coastguard Worker 'See http://www.chromium.org/developers/coding-style' 247*d9f75844SAndroid Build Coastguard Worker '#TOC-File-headers', files) 248*d9f75844SAndroid Build Coastguard Worker ] 249*d9f75844SAndroid Build Coastguard Worker return [] 250*d9f75844SAndroid Build Coastguard Worker 251*d9f75844SAndroid Build Coastguard Worker 252*d9f75844SAndroid Build Coastguard Workerdef CheckNoFRIEND_TEST(# pylint: disable=invalid-name 253*d9f75844SAndroid Build Coastguard Worker input_api, 254*d9f75844SAndroid Build Coastguard Worker output_api, 255*d9f75844SAndroid Build Coastguard Worker source_file_filter): 256*d9f75844SAndroid Build Coastguard Worker """Make sure that gtest's FRIEND_TEST() macro is not used, the 257*d9f75844SAndroid Build Coastguard Worker FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be 258*d9f75844SAndroid Build Coastguard Worker used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes.""" 259*d9f75844SAndroid Build Coastguard Worker problems = [] 260*d9f75844SAndroid Build Coastguard Worker 261*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.h')) and 262*d9f75844SAndroid Build Coastguard Worker source_file_filter(f)) 263*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(file_filter=file_filter): 264*d9f75844SAndroid Build Coastguard Worker for line_num, line in f.ChangedContents(): 265*d9f75844SAndroid Build Coastguard Worker if 'FRIEND_TEST(' in line: 266*d9f75844SAndroid Build Coastguard Worker problems.append(' %s:%d' % (f.LocalPath(), line_num)) 267*d9f75844SAndroid Build Coastguard Worker 268*d9f75844SAndroid Build Coastguard Worker if not problems: 269*d9f75844SAndroid Build Coastguard Worker return [] 270*d9f75844SAndroid Build Coastguard Worker return [ 271*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitPromptWarning( 272*d9f75844SAndroid Build Coastguard Worker 'WebRTC\'s code should not use gtest\'s FRIEND_TEST() macro. ' 273*d9f75844SAndroid Build Coastguard Worker 'Include testsupport/gtest_prod_util.h and use ' 274*d9f75844SAndroid Build Coastguard Worker 'FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems)) 275*d9f75844SAndroid Build Coastguard Worker ] 276*d9f75844SAndroid Build Coastguard Worker 277*d9f75844SAndroid Build Coastguard Worker 278*d9f75844SAndroid Build Coastguard Workerdef IsLintDisabled(disabled_paths, file_path): 279*d9f75844SAndroid Build Coastguard Worker """ Checks if a file is disabled for lint check.""" 280*d9f75844SAndroid Build Coastguard Worker for path in disabled_paths: 281*d9f75844SAndroid Build Coastguard Worker if file_path == path or os.path.dirname(file_path).startswith(path): 282*d9f75844SAndroid Build Coastguard Worker return True 283*d9f75844SAndroid Build Coastguard Worker return False 284*d9f75844SAndroid Build Coastguard Worker 285*d9f75844SAndroid Build Coastguard Worker 286*d9f75844SAndroid Build Coastguard Workerdef CheckApprovedFilesLintClean(input_api, output_api, 287*d9f75844SAndroid Build Coastguard Worker source_file_filter=None): 288*d9f75844SAndroid Build Coastguard Worker """Checks that all new or non-exempt .cc and .h files pass cpplint.py. 289*d9f75844SAndroid Build Coastguard Worker This check is based on CheckChangeLintsClean in 290*d9f75844SAndroid Build Coastguard Worker depot_tools/presubmit_canned_checks.py but has less filters and only checks 291*d9f75844SAndroid Build Coastguard Worker added files.""" 292*d9f75844SAndroid Build Coastguard Worker result = [] 293*d9f75844SAndroid Build Coastguard Worker 294*d9f75844SAndroid Build Coastguard Worker # Initialize cpplint. 295*d9f75844SAndroid Build Coastguard Worker import cpplint 296*d9f75844SAndroid Build Coastguard Worker # Access to a protected member _XX of a client class 297*d9f75844SAndroid Build Coastguard Worker # pylint: disable=W0212 298*d9f75844SAndroid Build Coastguard Worker cpplint._cpplint_state.ResetErrorCounts() 299*d9f75844SAndroid Build Coastguard Worker 300*d9f75844SAndroid Build Coastguard Worker lint_filters = cpplint._Filters() 301*d9f75844SAndroid Build Coastguard Worker lint_filters.extend(DISABLED_LINT_FILTERS) 302*d9f75844SAndroid Build Coastguard Worker cpplint._SetFilters(','.join(lint_filters)) 303*d9f75844SAndroid Build Coastguard Worker 304*d9f75844SAndroid Build Coastguard Worker # Create a platform independent exempt list for cpplint. 305*d9f75844SAndroid Build Coastguard Worker disabled_paths = [ 306*d9f75844SAndroid Build Coastguard Worker input_api.os_path.join(*path.split('/')) for path in CPPLINT_EXCEPTIONS 307*d9f75844SAndroid Build Coastguard Worker ] 308*d9f75844SAndroid Build Coastguard Worker 309*d9f75844SAndroid Build Coastguard Worker # Use the strictest verbosity level for cpplint.py (level 1) which is the 310*d9f75844SAndroid Build Coastguard Worker # default when running cpplint.py from command line. To make it possible to 311*d9f75844SAndroid Build Coastguard Worker # work with not-yet-converted code, we're only applying it to new (or 312*d9f75844SAndroid Build Coastguard Worker # moved/renamed) files and files not listed in CPPLINT_EXCEPTIONS. 313*d9f75844SAndroid Build Coastguard Worker verbosity_level = 1 314*d9f75844SAndroid Build Coastguard Worker files = [] 315*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(source_file_filter): 316*d9f75844SAndroid Build Coastguard Worker # Note that moved/renamed files also count as added. 317*d9f75844SAndroid Build Coastguard Worker if f.Action() == 'A' or not IsLintDisabled(disabled_paths, f.LocalPath()): 318*d9f75844SAndroid Build Coastguard Worker files.append(f.AbsoluteLocalPath()) 319*d9f75844SAndroid Build Coastguard Worker 320*d9f75844SAndroid Build Coastguard Worker for file_name in files: 321*d9f75844SAndroid Build Coastguard Worker cpplint.ProcessFile(file_name, verbosity_level) 322*d9f75844SAndroid Build Coastguard Worker 323*d9f75844SAndroid Build Coastguard Worker if cpplint._cpplint_state.error_count > 0: 324*d9f75844SAndroid Build Coastguard Worker if input_api.is_committing: 325*d9f75844SAndroid Build Coastguard Worker res_type = output_api.PresubmitError 326*d9f75844SAndroid Build Coastguard Worker else: 327*d9f75844SAndroid Build Coastguard Worker res_type = output_api.PresubmitPromptWarning 328*d9f75844SAndroid Build Coastguard Worker result = [res_type('Changelist failed cpplint.py check.')] 329*d9f75844SAndroid Build Coastguard Worker 330*d9f75844SAndroid Build Coastguard Worker return result 331*d9f75844SAndroid Build Coastguard Worker 332*d9f75844SAndroid Build Coastguard Worker 333*d9f75844SAndroid Build Coastguard Workerdef CheckNoSourcesAbove(input_api, gn_files, output_api): 334*d9f75844SAndroid Build Coastguard Worker # Disallow referencing source files with paths above the GN file location. 335*d9f75844SAndroid Build Coastguard Worker source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]', 336*d9f75844SAndroid Build Coastguard Worker re.MULTILINE | re.DOTALL) 337*d9f75844SAndroid Build Coastguard Worker file_pattern = input_api.re.compile(r'"((\.\./.*?)|(//.*?))"') 338*d9f75844SAndroid Build Coastguard Worker violating_gn_files = set() 339*d9f75844SAndroid Build Coastguard Worker violating_source_entries = [] 340*d9f75844SAndroid Build Coastguard Worker for gn_file in gn_files: 341*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(gn_file) 342*d9f75844SAndroid Build Coastguard Worker for source_block_match in source_pattern.finditer(contents): 343*d9f75844SAndroid Build Coastguard Worker # Find all source list entries starting with ../ in the source block 344*d9f75844SAndroid Build Coastguard Worker # (exclude overrides entries). 345*d9f75844SAndroid Build Coastguard Worker for file_list_match in file_pattern.finditer(source_block_match.group(1)): 346*d9f75844SAndroid Build Coastguard Worker source_file = file_list_match.group(1) 347*d9f75844SAndroid Build Coastguard Worker if 'overrides/' not in source_file: 348*d9f75844SAndroid Build Coastguard Worker violating_source_entries.append(source_file) 349*d9f75844SAndroid Build Coastguard Worker violating_gn_files.add(gn_file) 350*d9f75844SAndroid Build Coastguard Worker if violating_gn_files: 351*d9f75844SAndroid Build Coastguard Worker return [ 352*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 353*d9f75844SAndroid Build Coastguard Worker 'Referencing source files above the directory of the GN file ' 354*d9f75844SAndroid Build Coastguard Worker 'is not allowed. Please introduce new GN targets in the proper ' 355*d9f75844SAndroid Build Coastguard Worker 'location instead.\n' 356*d9f75844SAndroid Build Coastguard Worker 'Invalid source entries:\n' 357*d9f75844SAndroid Build Coastguard Worker '%s\n' 358*d9f75844SAndroid Build Coastguard Worker 'Violating GN files:' % '\n'.join(violating_source_entries), 359*d9f75844SAndroid Build Coastguard Worker items=violating_gn_files) 360*d9f75844SAndroid Build Coastguard Worker ] 361*d9f75844SAndroid Build Coastguard Worker return [] 362*d9f75844SAndroid Build Coastguard Worker 363*d9f75844SAndroid Build Coastguard Worker 364*d9f75844SAndroid Build Coastguard Workerdef CheckAbseilDependencies(input_api, gn_files, output_api): 365*d9f75844SAndroid Build Coastguard Worker """Checks that Abseil dependencies are declared in `absl_deps`.""" 366*d9f75844SAndroid Build Coastguard Worker absl_re = re.compile(r'third_party/abseil-cpp', re.MULTILINE | re.DOTALL) 367*d9f75844SAndroid Build Coastguard Worker target_types_to_check = [ 368*d9f75844SAndroid Build Coastguard Worker 'rtc_library', 369*d9f75844SAndroid Build Coastguard Worker 'rtc_source_set', 370*d9f75844SAndroid Build Coastguard Worker 'rtc_static_library', 371*d9f75844SAndroid Build Coastguard Worker 'webrtc_fuzzer_test', 372*d9f75844SAndroid Build Coastguard Worker ] 373*d9f75844SAndroid Build Coastguard Worker error_msg = ('Abseil dependencies in target "%s" (file: %s) ' 374*d9f75844SAndroid Build Coastguard Worker 'should be moved to the "absl_deps" parameter.') 375*d9f75844SAndroid Build Coastguard Worker errors = [] 376*d9f75844SAndroid Build Coastguard Worker 377*d9f75844SAndroid Build Coastguard Worker # pylint: disable=too-many-nested-blocks 378*d9f75844SAndroid Build Coastguard Worker for gn_file in gn_files: 379*d9f75844SAndroid Build Coastguard Worker gn_file_content = input_api.ReadFile(gn_file) 380*d9f75844SAndroid Build Coastguard Worker for target_match in TARGET_RE.finditer(gn_file_content): 381*d9f75844SAndroid Build Coastguard Worker target_type = target_match.group('target_type') 382*d9f75844SAndroid Build Coastguard Worker target_name = target_match.group('target_name') 383*d9f75844SAndroid Build Coastguard Worker target_contents = target_match.group('target_contents') 384*d9f75844SAndroid Build Coastguard Worker if target_type in target_types_to_check: 385*d9f75844SAndroid Build Coastguard Worker for deps_match in DEPS_RE.finditer(target_contents): 386*d9f75844SAndroid Build Coastguard Worker deps = deps_match.group('deps').splitlines() 387*d9f75844SAndroid Build Coastguard Worker for dep in deps: 388*d9f75844SAndroid Build Coastguard Worker if re.search(absl_re, dep): 389*d9f75844SAndroid Build Coastguard Worker errors.append( 390*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError(error_msg % 391*d9f75844SAndroid Build Coastguard Worker (target_name, gn_file.LocalPath()))) 392*d9f75844SAndroid Build Coastguard Worker break # no need to warn more than once per target 393*d9f75844SAndroid Build Coastguard Worker return errors 394*d9f75844SAndroid Build Coastguard Worker 395*d9f75844SAndroid Build Coastguard Worker 396*d9f75844SAndroid Build Coastguard Workerdef CheckNoMixingSources(input_api, gn_files, output_api): 397*d9f75844SAndroid Build Coastguard Worker """Disallow mixing C, C++ and Obj-C/Obj-C++ in the same target. 398*d9f75844SAndroid Build Coastguard Worker 399*d9f75844SAndroid Build Coastguard Worker See bugs.webrtc.org/7743 for more context. 400*d9f75844SAndroid Build Coastguard Worker """ 401*d9f75844SAndroid Build Coastguard Worker 402*d9f75844SAndroid Build Coastguard Worker def _MoreThanOneSourceUsed(*sources_lists): 403*d9f75844SAndroid Build Coastguard Worker sources_used = 0 404*d9f75844SAndroid Build Coastguard Worker for source_list in sources_lists: 405*d9f75844SAndroid Build Coastguard Worker if len(source_list) > 0: 406*d9f75844SAndroid Build Coastguard Worker sources_used += 1 407*d9f75844SAndroid Build Coastguard Worker return sources_used > 1 408*d9f75844SAndroid Build Coastguard Worker 409*d9f75844SAndroid Build Coastguard Worker errors = defaultdict(lambda: []) 410*d9f75844SAndroid Build Coastguard Worker for gn_file in gn_files: 411*d9f75844SAndroid Build Coastguard Worker gn_file_content = input_api.ReadFile(gn_file) 412*d9f75844SAndroid Build Coastguard Worker for target_match in TARGET_RE.finditer(gn_file_content): 413*d9f75844SAndroid Build Coastguard Worker # list_of_sources is a list of tuples of the form 414*d9f75844SAndroid Build Coastguard Worker # (c_files, cc_files, objc_files) that keeps track of all the 415*d9f75844SAndroid Build Coastguard Worker # sources defined in a target. A GN target can have more that 416*d9f75844SAndroid Build Coastguard Worker # on definition of sources (since it supports if/else statements). 417*d9f75844SAndroid Build Coastguard Worker # E.g.: 418*d9f75844SAndroid Build Coastguard Worker # rtc_static_library("foo") { 419*d9f75844SAndroid Build Coastguard Worker # if (is_win) { 420*d9f75844SAndroid Build Coastguard Worker # sources = [ "foo.cc" ] 421*d9f75844SAndroid Build Coastguard Worker # } else { 422*d9f75844SAndroid Build Coastguard Worker # sources = [ "foo.mm" ] 423*d9f75844SAndroid Build Coastguard Worker # } 424*d9f75844SAndroid Build Coastguard Worker # } 425*d9f75844SAndroid Build Coastguard Worker # This is allowed and the presubmit check should support this case. 426*d9f75844SAndroid Build Coastguard Worker list_of_sources = [] 427*d9f75844SAndroid Build Coastguard Worker c_files = [] 428*d9f75844SAndroid Build Coastguard Worker cc_files = [] 429*d9f75844SAndroid Build Coastguard Worker objc_files = [] 430*d9f75844SAndroid Build Coastguard Worker target_name = target_match.group('target_name') 431*d9f75844SAndroid Build Coastguard Worker target_contents = target_match.group('target_contents') 432*d9f75844SAndroid Build Coastguard Worker for sources_match in SOURCES_RE.finditer(target_contents): 433*d9f75844SAndroid Build Coastguard Worker if '+=' not in sources_match.group(0): 434*d9f75844SAndroid Build Coastguard Worker if c_files or cc_files or objc_files: 435*d9f75844SAndroid Build Coastguard Worker list_of_sources.append((c_files, cc_files, objc_files)) 436*d9f75844SAndroid Build Coastguard Worker c_files = [] 437*d9f75844SAndroid Build Coastguard Worker cc_files = [] 438*d9f75844SAndroid Build Coastguard Worker objc_files = [] 439*d9f75844SAndroid Build Coastguard Worker for file_match in FILE_PATH_RE.finditer(sources_match.group(1)): 440*d9f75844SAndroid Build Coastguard Worker file_path = file_match.group('file_path') 441*d9f75844SAndroid Build Coastguard Worker extension = file_match.group('extension') 442*d9f75844SAndroid Build Coastguard Worker if extension == '.c': 443*d9f75844SAndroid Build Coastguard Worker c_files.append(file_path + extension) 444*d9f75844SAndroid Build Coastguard Worker if extension == '.cc': 445*d9f75844SAndroid Build Coastguard Worker cc_files.append(file_path + extension) 446*d9f75844SAndroid Build Coastguard Worker if extension in ['.m', '.mm']: 447*d9f75844SAndroid Build Coastguard Worker objc_files.append(file_path + extension) 448*d9f75844SAndroid Build Coastguard Worker list_of_sources.append((c_files, cc_files, objc_files)) 449*d9f75844SAndroid Build Coastguard Worker for c_files_list, cc_files_list, objc_files_list in list_of_sources: 450*d9f75844SAndroid Build Coastguard Worker if _MoreThanOneSourceUsed(c_files_list, cc_files_list, objc_files_list): 451*d9f75844SAndroid Build Coastguard Worker all_sources = sorted(c_files_list + cc_files_list + objc_files_list) 452*d9f75844SAndroid Build Coastguard Worker errors[gn_file.LocalPath()].append((target_name, all_sources)) 453*d9f75844SAndroid Build Coastguard Worker if errors: 454*d9f75844SAndroid Build Coastguard Worker return [ 455*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 456*d9f75844SAndroid Build Coastguard Worker 'GN targets cannot mix .c, .cc and .m (or .mm) source files.\n' 457*d9f75844SAndroid Build Coastguard Worker 'Please create a separate target for each collection of ' 458*d9f75844SAndroid Build Coastguard Worker 'sources.\n' 459*d9f75844SAndroid Build Coastguard Worker 'Mixed sources: \n' 460*d9f75844SAndroid Build Coastguard Worker '%s\n' 461*d9f75844SAndroid Build Coastguard Worker 'Violating GN files:\n%s\n' % 462*d9f75844SAndroid Build Coastguard Worker (json.dumps(errors, indent=2), '\n'.join(list(errors.keys())))) 463*d9f75844SAndroid Build Coastguard Worker ] 464*d9f75844SAndroid Build Coastguard Worker return [] 465*d9f75844SAndroid Build Coastguard Worker 466*d9f75844SAndroid Build Coastguard Worker 467*d9f75844SAndroid Build Coastguard Workerdef CheckNoPackageBoundaryViolations(input_api, gn_files, output_api): 468*d9f75844SAndroid Build Coastguard Worker cwd = input_api.PresubmitLocalPath() 469*d9f75844SAndroid Build Coastguard Worker with _AddToPath( 470*d9f75844SAndroid Build Coastguard Worker input_api.os_path.join(cwd, 'tools_webrtc', 'presubmit_checks_lib')): 471*d9f75844SAndroid Build Coastguard Worker from check_package_boundaries import CheckPackageBoundaries 472*d9f75844SAndroid Build Coastguard Worker build_files = [os.path.join(cwd, gn_file.LocalPath()) for gn_file in gn_files] 473*d9f75844SAndroid Build Coastguard Worker errors = CheckPackageBoundaries(cwd, build_files)[:5] 474*d9f75844SAndroid Build Coastguard Worker if errors: 475*d9f75844SAndroid Build Coastguard Worker return [ 476*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 477*d9f75844SAndroid Build Coastguard Worker 'There are package boundary violations in the following GN ' 478*d9f75844SAndroid Build Coastguard Worker 'files:', 479*d9f75844SAndroid Build Coastguard Worker long_text='\n\n'.join(str(err) for err in errors)) 480*d9f75844SAndroid Build Coastguard Worker ] 481*d9f75844SAndroid Build Coastguard Worker return [] 482*d9f75844SAndroid Build Coastguard Worker 483*d9f75844SAndroid Build Coastguard Worker 484*d9f75844SAndroid Build Coastguard Workerdef _ReportFileAndLine(filename, line_num): 485*d9f75844SAndroid Build Coastguard Worker """Default error formatter for _FindNewViolationsOfRule.""" 486*d9f75844SAndroid Build Coastguard Worker return '%s (line %s)' % (filename, line_num) 487*d9f75844SAndroid Build Coastguard Worker 488*d9f75844SAndroid Build Coastguard Worker 489*d9f75844SAndroid Build Coastguard Workerdef CheckNoWarningSuppressionFlagsAreAdded(gn_files, 490*d9f75844SAndroid Build Coastguard Worker input_api, 491*d9f75844SAndroid Build Coastguard Worker output_api, 492*d9f75844SAndroid Build Coastguard Worker error_formatter=_ReportFileAndLine): 493*d9f75844SAndroid Build Coastguard Worker """Ensure warning suppression flags are not added without a reason.""" 494*d9f75844SAndroid Build Coastguard Worker msg = ('Usage of //build/config/clang:extra_warnings is discouraged ' 495*d9f75844SAndroid Build Coastguard Worker 'in WebRTC.\n' 496*d9f75844SAndroid Build Coastguard Worker 'If you are not adding this code (e.g. you are just moving ' 497*d9f75844SAndroid Build Coastguard Worker 'existing code) or you want to add an exception,\n' 498*d9f75844SAndroid Build Coastguard Worker 'you can add a comment on the line that causes the problem:\n\n' 499*d9f75844SAndroid Build Coastguard Worker '"-Wno-odr" # no-presubmit-check TODO(bugs.webrtc.org/BUG_ID)\n' 500*d9f75844SAndroid Build Coastguard Worker '\n' 501*d9f75844SAndroid Build Coastguard Worker 'Affected files:\n') 502*d9f75844SAndroid Build Coastguard Worker errors = [] # 2-element tuples with (file, line number) 503*d9f75844SAndroid Build Coastguard Worker clang_warn_re = input_api.re.compile(r'//build/config/clang:extra_warnings') 504*d9f75844SAndroid Build Coastguard Worker # pylint: disable-next=fixme 505*d9f75844SAndroid Build Coastguard Worker no_presubmit_re = input_api.re.compile( 506*d9f75844SAndroid Build Coastguard Worker r'# no-presubmit-check TODO\(bugs\.webrtc\.org/\d+\)') 507*d9f75844SAndroid Build Coastguard Worker for f in gn_files: 508*d9f75844SAndroid Build Coastguard Worker for line_num, line in f.ChangedContents(): 509*d9f75844SAndroid Build Coastguard Worker if clang_warn_re.search(line) and not no_presubmit_re.search(line): 510*d9f75844SAndroid Build Coastguard Worker errors.append(error_formatter(f.LocalPath(), line_num)) 511*d9f75844SAndroid Build Coastguard Worker if errors: 512*d9f75844SAndroid Build Coastguard Worker return [output_api.PresubmitError(msg, errors)] 513*d9f75844SAndroid Build Coastguard Worker return [] 514*d9f75844SAndroid Build Coastguard Worker 515*d9f75844SAndroid Build Coastguard Worker 516*d9f75844SAndroid Build Coastguard Workerdef CheckNoTestCaseUsageIsAdded(input_api, 517*d9f75844SAndroid Build Coastguard Worker output_api, 518*d9f75844SAndroid Build Coastguard Worker source_file_filter, 519*d9f75844SAndroid Build Coastguard Worker error_formatter=_ReportFileAndLine): 520*d9f75844SAndroid Build Coastguard Worker error_msg = ('Usage of legacy GoogleTest API detected!\nPlease use the ' 521*d9f75844SAndroid Build Coastguard Worker 'new API: https://github.com/google/googletest/blob/master/' 522*d9f75844SAndroid Build Coastguard Worker 'googletest/docs/primer.md#beware-of-the-nomenclature.\n' 523*d9f75844SAndroid Build Coastguard Worker 'Affected files:\n') 524*d9f75844SAndroid Build Coastguard Worker errors = [] # 2-element tuples with (file, line number) 525*d9f75844SAndroid Build Coastguard Worker test_case_re = input_api.re.compile(r'TEST_CASE') 526*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: (source_file_filter(f) and f.LocalPath().endswith( 527*d9f75844SAndroid Build Coastguard Worker '.cc')) 528*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 529*d9f75844SAndroid Build Coastguard Worker for line_num, line in f.ChangedContents(): 530*d9f75844SAndroid Build Coastguard Worker if test_case_re.search(line): 531*d9f75844SAndroid Build Coastguard Worker errors.append(error_formatter(f.LocalPath(), line_num)) 532*d9f75844SAndroid Build Coastguard Worker if errors: 533*d9f75844SAndroid Build Coastguard Worker return [output_api.PresubmitError(error_msg, errors)] 534*d9f75844SAndroid Build Coastguard Worker return [] 535*d9f75844SAndroid Build Coastguard Worker 536*d9f75844SAndroid Build Coastguard Worker 537*d9f75844SAndroid Build Coastguard Workerdef CheckNoStreamUsageIsAdded(input_api, 538*d9f75844SAndroid Build Coastguard Worker output_api, 539*d9f75844SAndroid Build Coastguard Worker source_file_filter, 540*d9f75844SAndroid Build Coastguard Worker error_formatter=_ReportFileAndLine): 541*d9f75844SAndroid Build Coastguard Worker """Make sure that no more dependencies on stringstream are added.""" 542*d9f75844SAndroid Build Coastguard Worker error_msg = ('Usage of <sstream>, <istream> and <ostream> in WebRTC is ' 543*d9f75844SAndroid Build Coastguard Worker 'deprecated.\n' 544*d9f75844SAndroid Build Coastguard Worker 'This includes the following types:\n' 545*d9f75844SAndroid Build Coastguard Worker 'std::istringstream, std::ostringstream, std::wistringstream, ' 546*d9f75844SAndroid Build Coastguard Worker 'std::wostringstream,\n' 547*d9f75844SAndroid Build Coastguard Worker 'std::wstringstream, std::ostream, std::wostream, std::istream,' 548*d9f75844SAndroid Build Coastguard Worker 'std::wistream,\n' 549*d9f75844SAndroid Build Coastguard Worker 'std::iostream, std::wiostream.\n' 550*d9f75844SAndroid Build Coastguard Worker 'If you are not adding this code (e.g. you are just moving ' 551*d9f75844SAndroid Build Coastguard Worker 'existing code),\n' 552*d9f75844SAndroid Build Coastguard Worker 'you can add a comment on the line that causes the problem:\n\n' 553*d9f75844SAndroid Build Coastguard Worker '#include <sstream> // no-presubmit-check TODO(webrtc:8982)\n' 554*d9f75844SAndroid Build Coastguard Worker 'std::ostream& F() { // no-presubmit-check TODO(webrtc:8982)\n' 555*d9f75844SAndroid Build Coastguard Worker '\n' 556*d9f75844SAndroid Build Coastguard Worker 'If you are adding new code, consider using ' 557*d9f75844SAndroid Build Coastguard Worker 'rtc::SimpleStringBuilder\n' 558*d9f75844SAndroid Build Coastguard Worker '(in rtc_base/strings/string_builder.h).\n' 559*d9f75844SAndroid Build Coastguard Worker 'Affected files:\n') 560*d9f75844SAndroid Build Coastguard Worker errors = [] # 2-element tuples with (file, line number) 561*d9f75844SAndroid Build Coastguard Worker include_re = input_api.re.compile(r'#include <(i|o|s)stream>') 562*d9f75844SAndroid Build Coastguard Worker usage_re = input_api.re.compile(r'std::(w|i|o|io|wi|wo|wio)(string)*stream') 563*d9f75844SAndroid Build Coastguard Worker no_presubmit_re = input_api.re.compile( 564*d9f75844SAndroid Build Coastguard Worker r'// no-presubmit-check TODO\(webrtc:8982\)') 565*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: (input_api.FilterSourceFile(x) and source_file_filter( 566*d9f75844SAndroid Build Coastguard Worker x)) 567*d9f75844SAndroid Build Coastguard Worker 568*d9f75844SAndroid Build Coastguard Worker def _IsException(file_path): 569*d9f75844SAndroid Build Coastguard Worker is_test = any( 570*d9f75844SAndroid Build Coastguard Worker file_path.endswith(x) 571*d9f75844SAndroid Build Coastguard Worker for x in ['_test.cc', '_tests.cc', '_unittest.cc', '_unittests.cc']) 572*d9f75844SAndroid Build Coastguard Worker return (file_path.startswith('examples') or file_path.startswith('test') 573*d9f75844SAndroid Build Coastguard Worker or is_test) 574*d9f75844SAndroid Build Coastguard Worker 575*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 576*d9f75844SAndroid Build Coastguard Worker # Usage of stringstream is allowed under examples/ and in tests. 577*d9f75844SAndroid Build Coastguard Worker if f.LocalPath() == 'PRESUBMIT.py' or _IsException(f.LocalPath()): 578*d9f75844SAndroid Build Coastguard Worker continue 579*d9f75844SAndroid Build Coastguard Worker for line_num, line in f.ChangedContents(): 580*d9f75844SAndroid Build Coastguard Worker if ((include_re.search(line) or usage_re.search(line)) 581*d9f75844SAndroid Build Coastguard Worker and not no_presubmit_re.search(line)): 582*d9f75844SAndroid Build Coastguard Worker errors.append(error_formatter(f.LocalPath(), line_num)) 583*d9f75844SAndroid Build Coastguard Worker if errors: 584*d9f75844SAndroid Build Coastguard Worker return [output_api.PresubmitError(error_msg, errors)] 585*d9f75844SAndroid Build Coastguard Worker return [] 586*d9f75844SAndroid Build Coastguard Worker 587*d9f75844SAndroid Build Coastguard Worker 588*d9f75844SAndroid Build Coastguard Workerdef CheckPublicDepsIsNotUsed(gn_files, input_api, output_api): 589*d9f75844SAndroid Build Coastguard Worker """Checks that public_deps is not used without a good reason.""" 590*d9f75844SAndroid Build Coastguard Worker result = [] 591*d9f75844SAndroid Build Coastguard Worker no_presubmit_check_re = input_api.re.compile( 592*d9f75844SAndroid Build Coastguard Worker r'# no-presubmit-check TODO\(webrtc:\d+\)') 593*d9f75844SAndroid Build Coastguard Worker error_msg = ('public_deps is not recommended in WebRTC BUILD.gn files ' 594*d9f75844SAndroid Build Coastguard Worker 'because it doesn\'t map well to downstream build systems.\n' 595*d9f75844SAndroid Build Coastguard Worker 'Used in: %s (line %d).\n' 596*d9f75844SAndroid Build Coastguard Worker 'If you are not adding this code (e.g. you are just moving ' 597*d9f75844SAndroid Build Coastguard Worker 'existing code) or you have a good reason, you can add this ' 598*d9f75844SAndroid Build Coastguard Worker 'comment (verbatim) on the line that causes the problem:\n\n' 599*d9f75844SAndroid Build Coastguard Worker 'public_deps = [ # no-presubmit-check TODO(webrtc:8603)\n') 600*d9f75844SAndroid Build Coastguard Worker for affected_file in gn_files: 601*d9f75844SAndroid Build Coastguard Worker for (line_number, affected_line) in affected_file.ChangedContents(): 602*d9f75844SAndroid Build Coastguard Worker if 'public_deps' in affected_line: 603*d9f75844SAndroid Build Coastguard Worker surpressed = no_presubmit_check_re.search(affected_line) 604*d9f75844SAndroid Build Coastguard Worker if not surpressed: 605*d9f75844SAndroid Build Coastguard Worker result.append( 606*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 607*d9f75844SAndroid Build Coastguard Worker error_msg % (affected_file.LocalPath(), line_number))) 608*d9f75844SAndroid Build Coastguard Worker return result 609*d9f75844SAndroid Build Coastguard Worker 610*d9f75844SAndroid Build Coastguard Worker 611*d9f75844SAndroid Build Coastguard Workerdef CheckCheckIncludesIsNotUsed(gn_files, input_api, output_api): 612*d9f75844SAndroid Build Coastguard Worker result = [] 613*d9f75844SAndroid Build Coastguard Worker error_msg = ('check_includes overrides are not allowed since it can cause ' 614*d9f75844SAndroid Build Coastguard Worker 'incorrect dependencies to form. It effectively means that your ' 615*d9f75844SAndroid Build Coastguard Worker 'module can include any .h file without depending on its ' 616*d9f75844SAndroid Build Coastguard Worker 'corresponding target. There are some exceptional cases when ' 617*d9f75844SAndroid Build Coastguard Worker 'this is allowed: if so, get approval from a .gn owner in the ' 618*d9f75844SAndroid Build Coastguard Worker 'root OWNERS file.\n' 619*d9f75844SAndroid Build Coastguard Worker 'Used in: %s (line %d).') 620*d9f75844SAndroid Build Coastguard Worker # pylint: disable-next=fixme 621*d9f75844SAndroid Build Coastguard Worker no_presubmit_re = input_api.re.compile( 622*d9f75844SAndroid Build Coastguard Worker r'# no-presubmit-check TODO\(bugs\.webrtc\.org/\d+\)') 623*d9f75844SAndroid Build Coastguard Worker for affected_file in gn_files: 624*d9f75844SAndroid Build Coastguard Worker for (line_number, affected_line) in affected_file.ChangedContents(): 625*d9f75844SAndroid Build Coastguard Worker if ('check_includes' in affected_line 626*d9f75844SAndroid Build Coastguard Worker and not no_presubmit_re.search(affected_line)): 627*d9f75844SAndroid Build Coastguard Worker result.append( 628*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError(error_msg % 629*d9f75844SAndroid Build Coastguard Worker (affected_file.LocalPath(), line_number))) 630*d9f75844SAndroid Build Coastguard Worker return result 631*d9f75844SAndroid Build Coastguard Worker 632*d9f75844SAndroid Build Coastguard Worker 633*d9f75844SAndroid Build Coastguard Workerdef CheckGnChanges(input_api, output_api): 634*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: (input_api.FilterSourceFile( 635*d9f75844SAndroid Build Coastguard Worker x, 636*d9f75844SAndroid Build Coastguard Worker files_to_check=(r'.+\.(gn|gni)$', ), 637*d9f75844SAndroid Build Coastguard Worker files_to_skip=(r'.*/presubmit_checks_lib/testdata/.*', ))) 638*d9f75844SAndroid Build Coastguard Worker 639*d9f75844SAndroid Build Coastguard Worker gn_files = [] 640*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 641*d9f75844SAndroid Build Coastguard Worker gn_files.append(f) 642*d9f75844SAndroid Build Coastguard Worker 643*d9f75844SAndroid Build Coastguard Worker result = [] 644*d9f75844SAndroid Build Coastguard Worker if gn_files: 645*d9f75844SAndroid Build Coastguard Worker result.extend(CheckNoSourcesAbove(input_api, gn_files, output_api)) 646*d9f75844SAndroid Build Coastguard Worker result.extend(CheckNoMixingSources(input_api, gn_files, output_api)) 647*d9f75844SAndroid Build Coastguard Worker result.extend(CheckAbseilDependencies(input_api, gn_files, output_api)) 648*d9f75844SAndroid Build Coastguard Worker result.extend( 649*d9f75844SAndroid Build Coastguard Worker CheckNoPackageBoundaryViolations(input_api, gn_files, output_api)) 650*d9f75844SAndroid Build Coastguard Worker result.extend(CheckPublicDepsIsNotUsed(gn_files, input_api, output_api)) 651*d9f75844SAndroid Build Coastguard Worker result.extend(CheckCheckIncludesIsNotUsed(gn_files, input_api, output_api)) 652*d9f75844SAndroid Build Coastguard Worker result.extend( 653*d9f75844SAndroid Build Coastguard Worker CheckNoWarningSuppressionFlagsAreAdded(gn_files, input_api, output_api)) 654*d9f75844SAndroid Build Coastguard Worker return result 655*d9f75844SAndroid Build Coastguard Worker 656*d9f75844SAndroid Build Coastguard Worker 657*d9f75844SAndroid Build Coastguard Workerdef CheckGnGen(input_api, output_api): 658*d9f75844SAndroid Build Coastguard Worker """Runs `gn gen --check` with default args to detect mismatches between 659*d9f75844SAndroid Build Coastguard Worker #includes and dependencies in the BUILD.gn files, as well as general build 660*d9f75844SAndroid Build Coastguard Worker errors. 661*d9f75844SAndroid Build Coastguard Worker """ 662*d9f75844SAndroid Build Coastguard Worker with _AddToPath( 663*d9f75844SAndroid Build Coastguard Worker input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools_webrtc', 664*d9f75844SAndroid Build Coastguard Worker 'presubmit_checks_lib')): 665*d9f75844SAndroid Build Coastguard Worker from build_helpers import RunGnCheck 666*d9f75844SAndroid Build Coastguard Worker errors = RunGnCheck(FindSrcDirPath(input_api.PresubmitLocalPath()))[:5] 667*d9f75844SAndroid Build Coastguard Worker if errors: 668*d9f75844SAndroid Build Coastguard Worker return [ 669*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitPromptWarning( 670*d9f75844SAndroid Build Coastguard Worker 'Some #includes do not match the build dependency graph. ' 671*d9f75844SAndroid Build Coastguard Worker 'Please run:\n' 672*d9f75844SAndroid Build Coastguard Worker ' gn gen --check <out_dir>', 673*d9f75844SAndroid Build Coastguard Worker long_text='\n\n'.join(errors)) 674*d9f75844SAndroid Build Coastguard Worker ] 675*d9f75844SAndroid Build Coastguard Worker return [] 676*d9f75844SAndroid Build Coastguard Worker 677*d9f75844SAndroid Build Coastguard Worker 678*d9f75844SAndroid Build Coastguard Workerdef CheckUnwantedDependencies(input_api, output_api, source_file_filter): 679*d9f75844SAndroid Build Coastguard Worker """Runs checkdeps on #include statements added in this 680*d9f75844SAndroid Build Coastguard Worker change. Breaking - rules is an error, breaking ! rules is a 681*d9f75844SAndroid Build Coastguard Worker warning. 682*d9f75844SAndroid Build Coastguard Worker """ 683*d9f75844SAndroid Build Coastguard Worker # Copied from Chromium's src/PRESUBMIT.py. 684*d9f75844SAndroid Build Coastguard Worker 685*d9f75844SAndroid Build Coastguard Worker # We need to wait until we have an input_api object and use this 686*d9f75844SAndroid Build Coastguard Worker # roundabout construct to import checkdeps because this file is 687*d9f75844SAndroid Build Coastguard Worker # eval-ed and thus doesn't have __file__. 688*d9f75844SAndroid Build Coastguard Worker src_path = FindSrcDirPath(input_api.PresubmitLocalPath()) 689*d9f75844SAndroid Build Coastguard Worker checkdeps_path = input_api.os_path.join(src_path, 'buildtools', 'checkdeps') 690*d9f75844SAndroid Build Coastguard Worker if not os.path.exists(checkdeps_path): 691*d9f75844SAndroid Build Coastguard Worker return [ 692*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 693*d9f75844SAndroid Build Coastguard Worker 'Cannot find checkdeps at %s\nHave you run "gclient sync" to ' 694*d9f75844SAndroid Build Coastguard Worker 'download all the DEPS entries?' % checkdeps_path) 695*d9f75844SAndroid Build Coastguard Worker ] 696*d9f75844SAndroid Build Coastguard Worker with _AddToPath(checkdeps_path): 697*d9f75844SAndroid Build Coastguard Worker import checkdeps 698*d9f75844SAndroid Build Coastguard Worker from cpp_checker import CppChecker 699*d9f75844SAndroid Build Coastguard Worker from rules import Rule 700*d9f75844SAndroid Build Coastguard Worker 701*d9f75844SAndroid Build Coastguard Worker added_includes = [] 702*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(file_filter=source_file_filter): 703*d9f75844SAndroid Build Coastguard Worker if not CppChecker.IsCppFile(f.LocalPath()): 704*d9f75844SAndroid Build Coastguard Worker continue 705*d9f75844SAndroid Build Coastguard Worker 706*d9f75844SAndroid Build Coastguard Worker changed_lines = [line for _, line in f.ChangedContents()] 707*d9f75844SAndroid Build Coastguard Worker added_includes.append([f.LocalPath(), changed_lines]) 708*d9f75844SAndroid Build Coastguard Worker 709*d9f75844SAndroid Build Coastguard Worker deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath()) 710*d9f75844SAndroid Build Coastguard Worker 711*d9f75844SAndroid Build Coastguard Worker error_descriptions = [] 712*d9f75844SAndroid Build Coastguard Worker warning_descriptions = [] 713*d9f75844SAndroid Build Coastguard Worker for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes( 714*d9f75844SAndroid Build Coastguard Worker added_includes): 715*d9f75844SAndroid Build Coastguard Worker description_with_path = '%s\n %s' % (path, rule_description) 716*d9f75844SAndroid Build Coastguard Worker if rule_type == Rule.DISALLOW: 717*d9f75844SAndroid Build Coastguard Worker error_descriptions.append(description_with_path) 718*d9f75844SAndroid Build Coastguard Worker else: 719*d9f75844SAndroid Build Coastguard Worker warning_descriptions.append(description_with_path) 720*d9f75844SAndroid Build Coastguard Worker 721*d9f75844SAndroid Build Coastguard Worker results = [] 722*d9f75844SAndroid Build Coastguard Worker if error_descriptions: 723*d9f75844SAndroid Build Coastguard Worker results.append( 724*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 725*d9f75844SAndroid Build Coastguard Worker 'You added one or more #includes that violate checkdeps rules.' 726*d9f75844SAndroid Build Coastguard Worker '\nCheck that the DEPS files in these locations contain valid ' 727*d9f75844SAndroid Build Coastguard Worker 'rules.\nSee ' 728*d9f75844SAndroid Build Coastguard Worker 'https://cs.chromium.org/chromium/src/buildtools/checkdeps/ ' 729*d9f75844SAndroid Build Coastguard Worker 'for more details about checkdeps.', error_descriptions)) 730*d9f75844SAndroid Build Coastguard Worker if warning_descriptions: 731*d9f75844SAndroid Build Coastguard Worker results.append( 732*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitPromptOrNotify( 733*d9f75844SAndroid Build Coastguard Worker 'You added one or more #includes of files that are temporarily' 734*d9f75844SAndroid Build Coastguard Worker '\nallowed but being removed. Can you avoid introducing the\n' 735*d9f75844SAndroid Build Coastguard Worker '#include? See relevant DEPS file(s) for details and contacts.' 736*d9f75844SAndroid Build Coastguard Worker '\nSee ' 737*d9f75844SAndroid Build Coastguard Worker 'https://cs.chromium.org/chromium/src/buildtools/checkdeps/ ' 738*d9f75844SAndroid Build Coastguard Worker 'for more details about checkdeps.', warning_descriptions)) 739*d9f75844SAndroid Build Coastguard Worker return results 740*d9f75844SAndroid Build Coastguard Worker 741*d9f75844SAndroid Build Coastguard Worker 742*d9f75844SAndroid Build Coastguard Workerdef CheckCommitMessageBugEntry(input_api, output_api): 743*d9f75844SAndroid Build Coastguard Worker """Check that bug entries are well-formed in commit message.""" 744*d9f75844SAndroid Build Coastguard Worker bogus_bug_msg = ( 745*d9f75844SAndroid Build Coastguard Worker 'Bogus Bug entry: %s. Please specify the issue tracker prefix and the ' 746*d9f75844SAndroid Build Coastguard Worker 'issue number, separated by a colon, e.g. webrtc:123 or chromium:12345.') 747*d9f75844SAndroid Build Coastguard Worker results = [] 748*d9f75844SAndroid Build Coastguard Worker for bug in input_api.change.BugsFromDescription(): 749*d9f75844SAndroid Build Coastguard Worker bug = bug.strip() 750*d9f75844SAndroid Build Coastguard Worker if bug.lower() == 'none': 751*d9f75844SAndroid Build Coastguard Worker continue 752*d9f75844SAndroid Build Coastguard Worker if 'b/' not in bug and ':' not in bug: 753*d9f75844SAndroid Build Coastguard Worker try: 754*d9f75844SAndroid Build Coastguard Worker if int(bug) > 100000: 755*d9f75844SAndroid Build Coastguard Worker # Rough indicator for current chromium bugs. 756*d9f75844SAndroid Build Coastguard Worker prefix_guess = 'chromium' 757*d9f75844SAndroid Build Coastguard Worker else: 758*d9f75844SAndroid Build Coastguard Worker prefix_guess = 'webrtc' 759*d9f75844SAndroid Build Coastguard Worker results.append('Bug entry requires issue tracker prefix, e.g. %s:%s' % 760*d9f75844SAndroid Build Coastguard Worker (prefix_guess, bug)) 761*d9f75844SAndroid Build Coastguard Worker except ValueError: 762*d9f75844SAndroid Build Coastguard Worker results.append(bogus_bug_msg % bug) 763*d9f75844SAndroid Build Coastguard Worker elif not (re.match(r'\w+:\d+', bug) or re.match(r'b/\d+', bug)): 764*d9f75844SAndroid Build Coastguard Worker results.append(bogus_bug_msg % bug) 765*d9f75844SAndroid Build Coastguard Worker return [output_api.PresubmitError(r) for r in results] 766*d9f75844SAndroid Build Coastguard Worker 767*d9f75844SAndroid Build Coastguard Worker 768*d9f75844SAndroid Build Coastguard Workerdef CheckChangeHasBugField(input_api, output_api): 769*d9f75844SAndroid Build Coastguard Worker """Requires that the changelist is associated with a bug. 770*d9f75844SAndroid Build Coastguard Worker 771*d9f75844SAndroid Build Coastguard Worker This check is stricter than the one in depot_tools/presubmit_canned_checks.py 772*d9f75844SAndroid Build Coastguard Worker since it fails the presubmit if the bug field is missing or doesn't contain 773*d9f75844SAndroid Build Coastguard Worker a bug reference. 774*d9f75844SAndroid Build Coastguard Worker 775*d9f75844SAndroid Build Coastguard Worker This supports both 'BUG=' and 'Bug:' since we are in the process of migrating 776*d9f75844SAndroid Build Coastguard Worker to Gerrit and it encourages the usage of 'Bug:'. 777*d9f75844SAndroid Build Coastguard Worker """ 778*d9f75844SAndroid Build Coastguard Worker if input_api.change.BugsFromDescription(): 779*d9f75844SAndroid Build Coastguard Worker return [] 780*d9f75844SAndroid Build Coastguard Worker return [ 781*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 782*d9f75844SAndroid Build Coastguard Worker 'The "Bug: [bug number]" footer is mandatory. Please create a ' 783*d9f75844SAndroid Build Coastguard Worker 'bug and reference it using either of:\n' 784*d9f75844SAndroid Build Coastguard Worker ' * https://bugs.webrtc.org - reference it using Bug: ' 785*d9f75844SAndroid Build Coastguard Worker 'webrtc:XXXX\n' 786*d9f75844SAndroid Build Coastguard Worker ' * https://crbug.com - reference it using Bug: chromium:XXXXXX') 787*d9f75844SAndroid Build Coastguard Worker ] 788*d9f75844SAndroid Build Coastguard Worker 789*d9f75844SAndroid Build Coastguard Worker 790*d9f75844SAndroid Build Coastguard Workerdef CheckJSONParseErrors(input_api, output_api, source_file_filter): 791*d9f75844SAndroid Build Coastguard Worker """Check that JSON files do not contain syntax errors.""" 792*d9f75844SAndroid Build Coastguard Worker 793*d9f75844SAndroid Build Coastguard Worker def FilterFile(affected_file): 794*d9f75844SAndroid Build Coastguard Worker return (input_api.os_path.splitext(affected_file.LocalPath())[1] == '.json' 795*d9f75844SAndroid Build Coastguard Worker and source_file_filter(affected_file)) 796*d9f75844SAndroid Build Coastguard Worker 797*d9f75844SAndroid Build Coastguard Worker def GetJSONParseError(input_api, filename): 798*d9f75844SAndroid Build Coastguard Worker try: 799*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(filename) 800*d9f75844SAndroid Build Coastguard Worker input_api.json.loads(contents) 801*d9f75844SAndroid Build Coastguard Worker except ValueError as e: 802*d9f75844SAndroid Build Coastguard Worker return e 803*d9f75844SAndroid Build Coastguard Worker return None 804*d9f75844SAndroid Build Coastguard Worker 805*d9f75844SAndroid Build Coastguard Worker results = [] 806*d9f75844SAndroid Build Coastguard Worker for affected_file in input_api.AffectedFiles(file_filter=FilterFile, 807*d9f75844SAndroid Build Coastguard Worker include_deletes=False): 808*d9f75844SAndroid Build Coastguard Worker parse_error = GetJSONParseError(input_api, 809*d9f75844SAndroid Build Coastguard Worker affected_file.AbsoluteLocalPath()) 810*d9f75844SAndroid Build Coastguard Worker if parse_error: 811*d9f75844SAndroid Build Coastguard Worker results.append( 812*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError('%s could not be parsed: %s' % 813*d9f75844SAndroid Build Coastguard Worker (affected_file.LocalPath(), parse_error))) 814*d9f75844SAndroid Build Coastguard Worker return results 815*d9f75844SAndroid Build Coastguard Worker 816*d9f75844SAndroid Build Coastguard Worker 817*d9f75844SAndroid Build Coastguard Workerdef RunPythonTests(input_api, output_api): 818*d9f75844SAndroid Build Coastguard Worker def Join(*args): 819*d9f75844SAndroid Build Coastguard Worker return input_api.os_path.join(input_api.PresubmitLocalPath(), *args) 820*d9f75844SAndroid Build Coastguard Worker 821*d9f75844SAndroid Build Coastguard Worker excluded_files = [ 822*d9f75844SAndroid Build Coastguard Worker # These tests should be run manually after webrtc_dashboard_upload target 823*d9f75844SAndroid Build Coastguard Worker # has been built. 824*d9f75844SAndroid Build Coastguard Worker 'catapult_uploader_test.py', 825*d9f75844SAndroid Build Coastguard Worker 'process_perf_results_test.py', 826*d9f75844SAndroid Build Coastguard Worker ] 827*d9f75844SAndroid Build Coastguard Worker 828*d9f75844SAndroid Build Coastguard Worker test_directories = [ 829*d9f75844SAndroid Build Coastguard Worker input_api.PresubmitLocalPath(), 830*d9f75844SAndroid Build Coastguard Worker Join('rtc_tools', 'py_event_log_analyzer'), 831*d9f75844SAndroid Build Coastguard Worker Join('audio', 'test', 'unittests'), 832*d9f75844SAndroid Build Coastguard Worker ] + [ 833*d9f75844SAndroid Build Coastguard Worker root for root, _, files in os.walk(Join('tools_webrtc')) if any( 834*d9f75844SAndroid Build Coastguard Worker f.endswith('_test.py') and f not in excluded_files for f in files) 835*d9f75844SAndroid Build Coastguard Worker ] 836*d9f75844SAndroid Build Coastguard Worker 837*d9f75844SAndroid Build Coastguard Worker tests = [] 838*d9f75844SAndroid Build Coastguard Worker 839*d9f75844SAndroid Build Coastguard Worker for directory in test_directories: 840*d9f75844SAndroid Build Coastguard Worker tests.extend( 841*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.GetUnitTestsInDirectory( 842*d9f75844SAndroid Build Coastguard Worker input_api, 843*d9f75844SAndroid Build Coastguard Worker output_api, 844*d9f75844SAndroid Build Coastguard Worker directory, 845*d9f75844SAndroid Build Coastguard Worker files_to_check=[r'.+_test\.py$'], 846*d9f75844SAndroid Build Coastguard Worker run_on_python2=False)) 847*d9f75844SAndroid Build Coastguard Worker return input_api.RunTests(tests, parallel=True) 848*d9f75844SAndroid Build Coastguard Worker 849*d9f75844SAndroid Build Coastguard Worker 850*d9f75844SAndroid Build Coastguard Workerdef CheckUsageOfGoogleProtobufNamespace(input_api, output_api, 851*d9f75844SAndroid Build Coastguard Worker source_file_filter): 852*d9f75844SAndroid Build Coastguard Worker """Checks that the namespace google::protobuf has not been used.""" 853*d9f75844SAndroid Build Coastguard Worker files = [] 854*d9f75844SAndroid Build Coastguard Worker pattern = input_api.re.compile(r'google::protobuf') 855*d9f75844SAndroid Build Coastguard Worker proto_utils_path = os.path.join('rtc_base', 'protobuf_utils.h') 856*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: (input_api.FilterSourceFile(x) and source_file_filter( 857*d9f75844SAndroid Build Coastguard Worker x)) 858*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 859*d9f75844SAndroid Build Coastguard Worker if f.LocalPath() in [proto_utils_path, 'PRESUBMIT.py']: 860*d9f75844SAndroid Build Coastguard Worker continue 861*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(f) 862*d9f75844SAndroid Build Coastguard Worker if pattern.search(contents): 863*d9f75844SAndroid Build Coastguard Worker files.append(f) 864*d9f75844SAndroid Build Coastguard Worker 865*d9f75844SAndroid Build Coastguard Worker if files: 866*d9f75844SAndroid Build Coastguard Worker return [ 867*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 868*d9f75844SAndroid Build Coastguard Worker 'Please avoid to use namespace `google::protobuf` directly.\n' 869*d9f75844SAndroid Build Coastguard Worker 'Add a using directive in `%s` and include that header instead.' % 870*d9f75844SAndroid Build Coastguard Worker proto_utils_path, files) 871*d9f75844SAndroid Build Coastguard Worker ] 872*d9f75844SAndroid Build Coastguard Worker return [] 873*d9f75844SAndroid Build Coastguard Worker 874*d9f75844SAndroid Build Coastguard Worker 875*d9f75844SAndroid Build Coastguard Workerdef _LicenseHeader(input_api): 876*d9f75844SAndroid Build Coastguard Worker """Returns the license header regexp.""" 877*d9f75844SAndroid Build Coastguard Worker # Accept any year number from 2003 to the current year 878*d9f75844SAndroid Build Coastguard Worker current_year = int(input_api.time.strftime('%Y')) 879*d9f75844SAndroid Build Coastguard Worker allowed_years = (str(s) for s in reversed(range(2003, current_year + 1))) 880*d9f75844SAndroid Build Coastguard Worker years_re = '(' + '|'.join(allowed_years) + ')' 881*d9f75844SAndroid Build Coastguard Worker license_header = ( 882*d9f75844SAndroid Build Coastguard Worker r'.*? Copyright( \(c\))? %(year)s The WebRTC [Pp]roject [Aa]uthors\. ' 883*d9f75844SAndroid Build Coastguard Worker r'All [Rr]ights [Rr]eserved\.\n' 884*d9f75844SAndroid Build Coastguard Worker r'.*?\n' 885*d9f75844SAndroid Build Coastguard Worker r'.*? Use of this source code is governed by a BSD-style license\n' 886*d9f75844SAndroid Build Coastguard Worker r'.*? that can be found in the LICENSE file in the root of the source\n' 887*d9f75844SAndroid Build Coastguard Worker r'.*? tree\. An additional intellectual property rights grant can be ' 888*d9f75844SAndroid Build Coastguard Worker r'found\n' 889*d9f75844SAndroid Build Coastguard Worker r'.*? in the file PATENTS\. All contributing project authors may\n' 890*d9f75844SAndroid Build Coastguard Worker r'.*? be found in the AUTHORS file in the root of the source tree\.\n' 891*d9f75844SAndroid Build Coastguard Worker ) % { 892*d9f75844SAndroid Build Coastguard Worker 'year': years_re, 893*d9f75844SAndroid Build Coastguard Worker } 894*d9f75844SAndroid Build Coastguard Worker return license_header 895*d9f75844SAndroid Build Coastguard Worker 896*d9f75844SAndroid Build Coastguard Worker 897*d9f75844SAndroid Build Coastguard Workerdef CommonChecks(input_api, output_api): 898*d9f75844SAndroid Build Coastguard Worker """Checks common to both upload and commit.""" 899*d9f75844SAndroid Build Coastguard Worker results = [] 900*d9f75844SAndroid Build Coastguard Worker # Filter out files that are in objc or ios dirs from being cpplint-ed since 901*d9f75844SAndroid Build Coastguard Worker # they do not follow C++ lint rules. 902*d9f75844SAndroid Build Coastguard Worker exception_list = input_api.DEFAULT_FILES_TO_SKIP + ( 903*d9f75844SAndroid Build Coastguard Worker r".*\bobjc[\\\/].*", 904*d9f75844SAndroid Build Coastguard Worker r".*objc\.[hcm]+$", 905*d9f75844SAndroid Build Coastguard Worker ) 906*d9f75844SAndroid Build Coastguard Worker source_file_filter = lambda x: input_api.FilterSourceFile( 907*d9f75844SAndroid Build Coastguard Worker x, None, exception_list) 908*d9f75844SAndroid Build Coastguard Worker results.extend( 909*d9f75844SAndroid Build Coastguard Worker CheckApprovedFilesLintClean(input_api, output_api, source_file_filter)) 910*d9f75844SAndroid Build Coastguard Worker results.extend( 911*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckLicense(input_api, output_api, 912*d9f75844SAndroid Build Coastguard Worker _LicenseHeader(input_api))) 913*d9f75844SAndroid Build Coastguard Worker 914*d9f75844SAndroid Build Coastguard Worker # TODO(bugs.webrtc.org/12114): Delete this filter and run pylint on 915*d9f75844SAndroid Build Coastguard Worker # all python files. This is a temporary solution. 916*d9f75844SAndroid Build Coastguard Worker python_file_filter = lambda f: (f.LocalPath().endswith('.py') and 917*d9f75844SAndroid Build Coastguard Worker source_file_filter(f)) 918*d9f75844SAndroid Build Coastguard Worker python_changed_files = [ 919*d9f75844SAndroid Build Coastguard Worker f.LocalPath() 920*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(include_deletes=False, 921*d9f75844SAndroid Build Coastguard Worker file_filter=python_file_filter) 922*d9f75844SAndroid Build Coastguard Worker ] 923*d9f75844SAndroid Build Coastguard Worker 924*d9f75844SAndroid Build Coastguard Worker results.extend( 925*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.RunPylint( 926*d9f75844SAndroid Build Coastguard Worker input_api, 927*d9f75844SAndroid Build Coastguard Worker output_api, 928*d9f75844SAndroid Build Coastguard Worker files_to_check=python_changed_files, 929*d9f75844SAndroid Build Coastguard Worker files_to_skip=( 930*d9f75844SAndroid Build Coastguard Worker r'^base[\\\/].*\.py$', 931*d9f75844SAndroid Build Coastguard Worker r'^build[\\\/].*\.py$', 932*d9f75844SAndroid Build Coastguard Worker r'^buildtools[\\\/].*\.py$', 933*d9f75844SAndroid Build Coastguard Worker r'^infra[\\\/].*\.py$', 934*d9f75844SAndroid Build Coastguard Worker r'^ios[\\\/].*\.py$', 935*d9f75844SAndroid Build Coastguard Worker r'^out.*[\\\/].*\.py$', 936*d9f75844SAndroid Build Coastguard Worker r'^testing[\\\/].*\.py$', 937*d9f75844SAndroid Build Coastguard Worker r'^third_party[\\\/].*\.py$', 938*d9f75844SAndroid Build Coastguard Worker r'^tools[\\\/].*\.py$', 939*d9f75844SAndroid Build Coastguard Worker r'^xcodebuild.*[\\\/].*\.py$', 940*d9f75844SAndroid Build Coastguard Worker ), 941*d9f75844SAndroid Build Coastguard Worker pylintrc='pylintrc', 942*d9f75844SAndroid Build Coastguard Worker version='2.7')) 943*d9f75844SAndroid Build Coastguard Worker 944*d9f75844SAndroid Build Coastguard Worker # TODO(bugs.webrtc.org/13606): talk/ is no more, so make below checks simpler? 945*d9f75844SAndroid Build Coastguard Worker # WebRTC can't use the presubmit_canned_checks.PanProjectChecks function 946*d9f75844SAndroid Build Coastguard Worker # since we need to have different license checks 947*d9f75844SAndroid Build Coastguard Worker # in talk/ and webrtc/directories. 948*d9f75844SAndroid Build Coastguard Worker # Instead, hand-picked checks are included below. 949*d9f75844SAndroid Build Coastguard Worker 950*d9f75844SAndroid Build Coastguard Worker # .m and .mm files are ObjC files. For simplicity we will consider 951*d9f75844SAndroid Build Coastguard Worker # .h files in ObjC subdirectories ObjC headers. 952*d9f75844SAndroid Build Coastguard Worker objc_filter_list = (r'.+\.m$', r'.+\.mm$', r'.+objc\/.+\.h$') 953*d9f75844SAndroid Build Coastguard Worker # Skip long-lines check for DEPS and GN files. 954*d9f75844SAndroid Build Coastguard Worker build_file_filter_list = (r'.+\.gn$', r'.+\.gni$', 'DEPS') 955*d9f75844SAndroid Build Coastguard Worker # Also we will skip most checks for third_party directory. 956*d9f75844SAndroid Build Coastguard Worker third_party_filter_list = (r'(^|.*[\\\/])third_party[\\\/].+', ) 957*d9f75844SAndroid Build Coastguard Worker eighty_char_sources = lambda x: input_api.FilterSourceFile( 958*d9f75844SAndroid Build Coastguard Worker x, 959*d9f75844SAndroid Build Coastguard Worker files_to_skip=build_file_filter_list + objc_filter_list + 960*d9f75844SAndroid Build Coastguard Worker third_party_filter_list) 961*d9f75844SAndroid Build Coastguard Worker hundred_char_sources = lambda x: input_api.FilterSourceFile( 962*d9f75844SAndroid Build Coastguard Worker x, files_to_check=objc_filter_list) 963*d9f75844SAndroid Build Coastguard Worker non_third_party_sources = lambda x: input_api.FilterSourceFile( 964*d9f75844SAndroid Build Coastguard Worker x, files_to_skip=third_party_filter_list) 965*d9f75844SAndroid Build Coastguard Worker 966*d9f75844SAndroid Build Coastguard Worker results.extend( 967*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckLongLines( 968*d9f75844SAndroid Build Coastguard Worker input_api, 969*d9f75844SAndroid Build Coastguard Worker output_api, 970*d9f75844SAndroid Build Coastguard Worker maxlen=80, 971*d9f75844SAndroid Build Coastguard Worker source_file_filter=eighty_char_sources)) 972*d9f75844SAndroid Build Coastguard Worker results.extend( 973*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckLongLines( 974*d9f75844SAndroid Build Coastguard Worker input_api, 975*d9f75844SAndroid Build Coastguard Worker output_api, 976*d9f75844SAndroid Build Coastguard Worker maxlen=100, 977*d9f75844SAndroid Build Coastguard Worker source_file_filter=hundred_char_sources)) 978*d9f75844SAndroid Build Coastguard Worker results.extend( 979*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckChangeHasNoTabs( 980*d9f75844SAndroid Build Coastguard Worker input_api, output_api, source_file_filter=non_third_party_sources)) 981*d9f75844SAndroid Build Coastguard Worker results.extend( 982*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckChangeHasNoStrayWhitespace( 983*d9f75844SAndroid Build Coastguard Worker input_api, output_api, source_file_filter=non_third_party_sources)) 984*d9f75844SAndroid Build Coastguard Worker results.extend( 985*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckAuthorizedAuthor( 986*d9f75844SAndroid Build Coastguard Worker input_api, 987*d9f75844SAndroid Build Coastguard Worker output_api, 988*d9f75844SAndroid Build Coastguard Worker bot_allowlist=[ 989*d9f75844SAndroid Build Coastguard Worker '[email protected]', 990*d9f75844SAndroid Build Coastguard Worker '[email protected]', 991*d9f75844SAndroid Build Coastguard Worker ])) 992*d9f75844SAndroid Build Coastguard Worker results.extend( 993*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckChangeTodoHasOwner( 994*d9f75844SAndroid Build Coastguard Worker input_api, output_api, source_file_filter=non_third_party_sources)) 995*d9f75844SAndroid Build Coastguard Worker results.extend( 996*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckPatchFormatted(input_api, output_api)) 997*d9f75844SAndroid Build Coastguard Worker results.extend(CheckNativeApiHeaderChanges(input_api, output_api)) 998*d9f75844SAndroid Build Coastguard Worker results.extend( 999*d9f75844SAndroid Build Coastguard Worker CheckNoIOStreamInHeaders(input_api, 1000*d9f75844SAndroid Build Coastguard Worker output_api, 1001*d9f75844SAndroid Build Coastguard Worker source_file_filter=non_third_party_sources)) 1002*d9f75844SAndroid Build Coastguard Worker results.extend( 1003*d9f75844SAndroid Build Coastguard Worker CheckNoPragmaOnce(input_api, 1004*d9f75844SAndroid Build Coastguard Worker output_api, 1005*d9f75844SAndroid Build Coastguard Worker source_file_filter=non_third_party_sources)) 1006*d9f75844SAndroid Build Coastguard Worker results.extend( 1007*d9f75844SAndroid Build Coastguard Worker CheckNoFRIEND_TEST(input_api, 1008*d9f75844SAndroid Build Coastguard Worker output_api, 1009*d9f75844SAndroid Build Coastguard Worker source_file_filter=non_third_party_sources)) 1010*d9f75844SAndroid Build Coastguard Worker results.extend(CheckGnChanges(input_api, output_api)) 1011*d9f75844SAndroid Build Coastguard Worker results.extend( 1012*d9f75844SAndroid Build Coastguard Worker CheckUnwantedDependencies(input_api, 1013*d9f75844SAndroid Build Coastguard Worker output_api, 1014*d9f75844SAndroid Build Coastguard Worker source_file_filter=non_third_party_sources)) 1015*d9f75844SAndroid Build Coastguard Worker results.extend( 1016*d9f75844SAndroid Build Coastguard Worker CheckJSONParseErrors(input_api, 1017*d9f75844SAndroid Build Coastguard Worker output_api, 1018*d9f75844SAndroid Build Coastguard Worker source_file_filter=non_third_party_sources)) 1019*d9f75844SAndroid Build Coastguard Worker results.extend(RunPythonTests(input_api, output_api)) 1020*d9f75844SAndroid Build Coastguard Worker results.extend( 1021*d9f75844SAndroid Build Coastguard Worker CheckUsageOfGoogleProtobufNamespace( 1022*d9f75844SAndroid Build Coastguard Worker input_api, output_api, source_file_filter=non_third_party_sources)) 1023*d9f75844SAndroid Build Coastguard Worker results.extend( 1024*d9f75844SAndroid Build Coastguard Worker CheckOrphanHeaders(input_api, 1025*d9f75844SAndroid Build Coastguard Worker output_api, 1026*d9f75844SAndroid Build Coastguard Worker source_file_filter=non_third_party_sources)) 1027*d9f75844SAndroid Build Coastguard Worker results.extend( 1028*d9f75844SAndroid Build Coastguard Worker CheckNewlineAtTheEndOfProtoFiles( 1029*d9f75844SAndroid Build Coastguard Worker input_api, output_api, source_file_filter=non_third_party_sources)) 1030*d9f75844SAndroid Build Coastguard Worker results.extend( 1031*d9f75844SAndroid Build Coastguard Worker CheckNoStreamUsageIsAdded(input_api, output_api, non_third_party_sources)) 1032*d9f75844SAndroid Build Coastguard Worker results.extend( 1033*d9f75844SAndroid Build Coastguard Worker CheckNoTestCaseUsageIsAdded(input_api, output_api, 1034*d9f75844SAndroid Build Coastguard Worker non_third_party_sources)) 1035*d9f75844SAndroid Build Coastguard Worker results.extend(CheckAddedDepsHaveTargetApprovals(input_api, output_api)) 1036*d9f75844SAndroid Build Coastguard Worker results.extend(CheckApiDepsFileIsUpToDate(input_api, output_api)) 1037*d9f75844SAndroid Build Coastguard Worker results.extend( 1038*d9f75844SAndroid Build Coastguard Worker CheckAbslMemoryInclude(input_api, output_api, non_third_party_sources)) 1039*d9f75844SAndroid Build Coastguard Worker results.extend( 1040*d9f75844SAndroid Build Coastguard Worker CheckAssertUsage(input_api, output_api, non_third_party_sources)) 1041*d9f75844SAndroid Build Coastguard Worker results.extend( 1042*d9f75844SAndroid Build Coastguard Worker CheckBannedAbslMakeUnique(input_api, output_api, non_third_party_sources)) 1043*d9f75844SAndroid Build Coastguard Worker results.extend( 1044*d9f75844SAndroid Build Coastguard Worker CheckObjcApiSymbols(input_api, output_api, non_third_party_sources)) 1045*d9f75844SAndroid Build Coastguard Worker return results 1046*d9f75844SAndroid Build Coastguard Worker 1047*d9f75844SAndroid Build Coastguard Worker 1048*d9f75844SAndroid Build Coastguard Workerdef CheckApiDepsFileIsUpToDate(input_api, output_api): 1049*d9f75844SAndroid Build Coastguard Worker """Check that 'include_rules' in api/DEPS is up to date. 1050*d9f75844SAndroid Build Coastguard Worker 1051*d9f75844SAndroid Build Coastguard Worker The file api/DEPS must be kept up to date in order to avoid to avoid to 1052*d9f75844SAndroid Build Coastguard Worker include internal header from WebRTC's api/ headers. 1053*d9f75844SAndroid Build Coastguard Worker 1054*d9f75844SAndroid Build Coastguard Worker This check is focused on ensuring that 'include_rules' contains a deny 1055*d9f75844SAndroid Build Coastguard Worker rule for each root level directory. More focused allow rules can be 1056*d9f75844SAndroid Build Coastguard Worker added to 'specific_include_rules'. 1057*d9f75844SAndroid Build Coastguard Worker """ 1058*d9f75844SAndroid Build Coastguard Worker results = [] 1059*d9f75844SAndroid Build Coastguard Worker api_deps = os.path.join(input_api.PresubmitLocalPath(), 'api', 'DEPS') 1060*d9f75844SAndroid Build Coastguard Worker with open(api_deps) as f: 1061*d9f75844SAndroid Build Coastguard Worker deps_content = _ParseDeps(f.read()) 1062*d9f75844SAndroid Build Coastguard Worker 1063*d9f75844SAndroid Build Coastguard Worker include_rules = deps_content.get('include_rules', []) 1064*d9f75844SAndroid Build Coastguard Worker dirs_to_skip = set(['api', 'docs']) 1065*d9f75844SAndroid Build Coastguard Worker 1066*d9f75844SAndroid Build Coastguard Worker # Only check top level directories affected by the current CL. 1067*d9f75844SAndroid Build Coastguard Worker dirs_to_check = set() 1068*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(): 1069*d9f75844SAndroid Build Coastguard Worker path_tokens = [t for t in f.LocalPath().split(os.sep) if t] 1070*d9f75844SAndroid Build Coastguard Worker if len(path_tokens) > 1: 1071*d9f75844SAndroid Build Coastguard Worker if (path_tokens[0] not in dirs_to_skip and os.path.isdir( 1072*d9f75844SAndroid Build Coastguard Worker os.path.join(input_api.PresubmitLocalPath(), path_tokens[0]))): 1073*d9f75844SAndroid Build Coastguard Worker dirs_to_check.add(path_tokens[0]) 1074*d9f75844SAndroid Build Coastguard Worker 1075*d9f75844SAndroid Build Coastguard Worker missing_include_rules = set() 1076*d9f75844SAndroid Build Coastguard Worker for p in dirs_to_check: 1077*d9f75844SAndroid Build Coastguard Worker rule = '-%s' % p 1078*d9f75844SAndroid Build Coastguard Worker if rule not in include_rules: 1079*d9f75844SAndroid Build Coastguard Worker missing_include_rules.add(rule) 1080*d9f75844SAndroid Build Coastguard Worker 1081*d9f75844SAndroid Build Coastguard Worker if missing_include_rules: 1082*d9f75844SAndroid Build Coastguard Worker error_msg = [ 1083*d9f75844SAndroid Build Coastguard Worker 'include_rules = [\n', 1084*d9f75844SAndroid Build Coastguard Worker ' ...\n', 1085*d9f75844SAndroid Build Coastguard Worker ] 1086*d9f75844SAndroid Build Coastguard Worker 1087*d9f75844SAndroid Build Coastguard Worker for r in sorted(missing_include_rules): 1088*d9f75844SAndroid Build Coastguard Worker error_msg.append(' "%s",\n' % str(r)) 1089*d9f75844SAndroid Build Coastguard Worker 1090*d9f75844SAndroid Build Coastguard Worker error_msg.append(' ...\n') 1091*d9f75844SAndroid Build Coastguard Worker error_msg.append(']\n') 1092*d9f75844SAndroid Build Coastguard Worker 1093*d9f75844SAndroid Build Coastguard Worker results.append( 1094*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1095*d9f75844SAndroid Build Coastguard Worker 'New root level directory detected! WebRTC api/ headers should ' 1096*d9f75844SAndroid Build Coastguard Worker 'not #include headers from \n' 1097*d9f75844SAndroid Build Coastguard Worker 'the new directory, so please update "include_rules" in file\n' 1098*d9f75844SAndroid Build Coastguard Worker '"%s". Example:\n%s\n' % (api_deps, ''.join(error_msg)))) 1099*d9f75844SAndroid Build Coastguard Worker 1100*d9f75844SAndroid Build Coastguard Worker return results 1101*d9f75844SAndroid Build Coastguard Worker 1102*d9f75844SAndroid Build Coastguard Worker 1103*d9f75844SAndroid Build Coastguard Workerdef CheckBannedAbslMakeUnique(input_api, output_api, source_file_filter): 1104*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.h')) and 1105*d9f75844SAndroid Build Coastguard Worker source_file_filter(f)) 1106*d9f75844SAndroid Build Coastguard Worker 1107*d9f75844SAndroid Build Coastguard Worker files = [] 1108*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(include_deletes=False, 1109*d9f75844SAndroid Build Coastguard Worker file_filter=file_filter): 1110*d9f75844SAndroid Build Coastguard Worker for _, line in f.ChangedContents(): 1111*d9f75844SAndroid Build Coastguard Worker if 'absl::make_unique' in line: 1112*d9f75844SAndroid Build Coastguard Worker files.append(f) 1113*d9f75844SAndroid Build Coastguard Worker break 1114*d9f75844SAndroid Build Coastguard Worker 1115*d9f75844SAndroid Build Coastguard Worker if files: 1116*d9f75844SAndroid Build Coastguard Worker return [ 1117*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1118*d9f75844SAndroid Build Coastguard Worker 'Please use std::make_unique instead of absl::make_unique.\n' 1119*d9f75844SAndroid Build Coastguard Worker 'Affected files:', files) 1120*d9f75844SAndroid Build Coastguard Worker ] 1121*d9f75844SAndroid Build Coastguard Worker return [] 1122*d9f75844SAndroid Build Coastguard Worker 1123*d9f75844SAndroid Build Coastguard Worker 1124*d9f75844SAndroid Build Coastguard Workerdef CheckObjcApiSymbols(input_api, output_api, source_file_filter): 1125*d9f75844SAndroid Build Coastguard Worker rtc_objc_export = re.compile(r'RTC_OBJC_EXPORT(.|\n){26}', 1126*d9f75844SAndroid Build Coastguard Worker re.MULTILINE | re.DOTALL) 1127*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: (f.LocalPath().endswith(('.h')) and 1128*d9f75844SAndroid Build Coastguard Worker source_file_filter(f)) 1129*d9f75844SAndroid Build Coastguard Worker 1130*d9f75844SAndroid Build Coastguard Worker files = [] 1131*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: (input_api.FilterSourceFile(x) and source_file_filter( 1132*d9f75844SAndroid Build Coastguard Worker x)) 1133*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 1134*d9f75844SAndroid Build Coastguard Worker if not f.LocalPath().endswith('.h') or not 'sdk/objc' in f.LocalPath(): 1135*d9f75844SAndroid Build Coastguard Worker continue 1136*d9f75844SAndroid Build Coastguard Worker if f.LocalPath().endswith('sdk/objc/base/RTCMacros.h'): 1137*d9f75844SAndroid Build Coastguard Worker continue 1138*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(f) 1139*d9f75844SAndroid Build Coastguard Worker for match in rtc_objc_export.finditer(contents): 1140*d9f75844SAndroid Build Coastguard Worker export_block = match.group(0) 1141*d9f75844SAndroid Build Coastguard Worker if 'RTC_OBJC_TYPE' not in export_block: 1142*d9f75844SAndroid Build Coastguard Worker files.append(f.LocalPath()) 1143*d9f75844SAndroid Build Coastguard Worker 1144*d9f75844SAndroid Build Coastguard Worker if len(files) > 0: 1145*d9f75844SAndroid Build Coastguard Worker return [ 1146*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1147*d9f75844SAndroid Build Coastguard Worker 'RTC_OBJC_EXPORT types must be wrapped into an RTC_OBJC_TYPE() ' + 1148*d9f75844SAndroid Build Coastguard Worker 'macro.\n\n' + 'For example:\n' + 1149*d9f75844SAndroid Build Coastguard Worker 'RTC_OBJC_EXPORT @protocol RTC_OBJC_TYPE(RtcFoo)\n\n' + 1150*d9f75844SAndroid Build Coastguard Worker 'RTC_OBJC_EXPORT @interface RTC_OBJC_TYPE(RtcFoo)\n\n' + 1151*d9f75844SAndroid Build Coastguard Worker 'Please fix the following files:', files) 1152*d9f75844SAndroid Build Coastguard Worker ] 1153*d9f75844SAndroid Build Coastguard Worker return [] 1154*d9f75844SAndroid Build Coastguard Worker 1155*d9f75844SAndroid Build Coastguard Worker 1156*d9f75844SAndroid Build Coastguard Workerdef CheckAssertUsage(input_api, output_api, source_file_filter): 1157*d9f75844SAndroid Build Coastguard Worker pattern = input_api.re.compile(r'\bassert\(') 1158*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.h', '.m', '.mm')) 1159*d9f75844SAndroid Build Coastguard Worker and source_file_filter(f)) 1160*d9f75844SAndroid Build Coastguard Worker 1161*d9f75844SAndroid Build Coastguard Worker files = [] 1162*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(include_deletes=False, 1163*d9f75844SAndroid Build Coastguard Worker file_filter=file_filter): 1164*d9f75844SAndroid Build Coastguard Worker for _, line in f.ChangedContents(): 1165*d9f75844SAndroid Build Coastguard Worker if pattern.search(line): 1166*d9f75844SAndroid Build Coastguard Worker files.append(f.LocalPath()) 1167*d9f75844SAndroid Build Coastguard Worker break 1168*d9f75844SAndroid Build Coastguard Worker 1169*d9f75844SAndroid Build Coastguard Worker if len(files) > 0: 1170*d9f75844SAndroid Build Coastguard Worker return [ 1171*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1172*d9f75844SAndroid Build Coastguard Worker 'Usage of assert() has been detected in the following files, ' 1173*d9f75844SAndroid Build Coastguard Worker 'please use RTC_DCHECK() instead.\n Files:', files) 1174*d9f75844SAndroid Build Coastguard Worker ] 1175*d9f75844SAndroid Build Coastguard Worker return [] 1176*d9f75844SAndroid Build Coastguard Worker 1177*d9f75844SAndroid Build Coastguard Worker 1178*d9f75844SAndroid Build Coastguard Workerdef CheckAbslMemoryInclude(input_api, output_api, source_file_filter): 1179*d9f75844SAndroid Build Coastguard Worker pattern = input_api.re.compile(r'^#include\s*"absl/memory/memory.h"', 1180*d9f75844SAndroid Build Coastguard Worker input_api.re.MULTILINE) 1181*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.h')) and 1182*d9f75844SAndroid Build Coastguard Worker source_file_filter(f)) 1183*d9f75844SAndroid Build Coastguard Worker 1184*d9f75844SAndroid Build Coastguard Worker files = [] 1185*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(include_deletes=False, 1186*d9f75844SAndroid Build Coastguard Worker file_filter=file_filter): 1187*d9f75844SAndroid Build Coastguard Worker contents = input_api.ReadFile(f) 1188*d9f75844SAndroid Build Coastguard Worker if pattern.search(contents): 1189*d9f75844SAndroid Build Coastguard Worker continue 1190*d9f75844SAndroid Build Coastguard Worker for _, line in f.ChangedContents(): 1191*d9f75844SAndroid Build Coastguard Worker if 'absl::WrapUnique' in line: 1192*d9f75844SAndroid Build Coastguard Worker files.append(f) 1193*d9f75844SAndroid Build Coastguard Worker break 1194*d9f75844SAndroid Build Coastguard Worker 1195*d9f75844SAndroid Build Coastguard Worker if len(files) > 0: 1196*d9f75844SAndroid Build Coastguard Worker return [ 1197*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1198*d9f75844SAndroid Build Coastguard Worker 'Please include "absl/memory/memory.h" header for ' 1199*d9f75844SAndroid Build Coastguard Worker 'absl::WrapUnique.\nThis header may or may not be included ' 1200*d9f75844SAndroid Build Coastguard Worker 'transitively depending on the C++ standard version.', files) 1201*d9f75844SAndroid Build Coastguard Worker ] 1202*d9f75844SAndroid Build Coastguard Worker return [] 1203*d9f75844SAndroid Build Coastguard Worker 1204*d9f75844SAndroid Build Coastguard Worker 1205*d9f75844SAndroid Build Coastguard Workerdef CheckChangeOnUpload(input_api, output_api): 1206*d9f75844SAndroid Build Coastguard Worker results = [] 1207*d9f75844SAndroid Build Coastguard Worker results.extend(CommonChecks(input_api, output_api)) 1208*d9f75844SAndroid Build Coastguard Worker results.extend(CheckGnGen(input_api, output_api)) 1209*d9f75844SAndroid Build Coastguard Worker results.extend(input_api.canned_checks.CheckGNFormatted( 1210*d9f75844SAndroid Build Coastguard Worker input_api, output_api)) 1211*d9f75844SAndroid Build Coastguard Worker return results 1212*d9f75844SAndroid Build Coastguard Worker 1213*d9f75844SAndroid Build Coastguard Worker 1214*d9f75844SAndroid Build Coastguard Workerdef CheckChangeOnCommit(input_api, output_api): 1215*d9f75844SAndroid Build Coastguard Worker results = [] 1216*d9f75844SAndroid Build Coastguard Worker results.extend(CommonChecks(input_api, output_api)) 1217*d9f75844SAndroid Build Coastguard Worker results.extend(VerifyNativeApiHeadersListIsValid(input_api, output_api)) 1218*d9f75844SAndroid Build Coastguard Worker results.extend(input_api.canned_checks.CheckOwners(input_api, output_api)) 1219*d9f75844SAndroid Build Coastguard Worker results.extend( 1220*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckChangeWasUploaded(input_api, output_api)) 1221*d9f75844SAndroid Build Coastguard Worker results.extend( 1222*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckChangeHasDescription(input_api, output_api)) 1223*d9f75844SAndroid Build Coastguard Worker results.extend(CheckChangeHasBugField(input_api, output_api)) 1224*d9f75844SAndroid Build Coastguard Worker results.extend(CheckCommitMessageBugEntry(input_api, output_api)) 1225*d9f75844SAndroid Build Coastguard Worker results.extend( 1226*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.CheckTreeIsOpen( 1227*d9f75844SAndroid Build Coastguard Worker input_api, 1228*d9f75844SAndroid Build Coastguard Worker output_api, 1229*d9f75844SAndroid Build Coastguard Worker json_url='http://webrtc-status.appspot.com/current?format=json')) 1230*d9f75844SAndroid Build Coastguard Worker return results 1231*d9f75844SAndroid Build Coastguard Worker 1232*d9f75844SAndroid Build Coastguard Worker 1233*d9f75844SAndroid Build Coastguard Workerdef CheckOrphanHeaders(input_api, output_api, source_file_filter): 1234*d9f75844SAndroid Build Coastguard Worker # We need to wait until we have an input_api object and use this 1235*d9f75844SAndroid Build Coastguard Worker # roundabout construct to import prebubmit_checks_lib because this file is 1236*d9f75844SAndroid Build Coastguard Worker # eval-ed and thus doesn't have __file__. 1237*d9f75844SAndroid Build Coastguard Worker error_msg = """{} should be listed in {}.""" 1238*d9f75844SAndroid Build Coastguard Worker results = [] 1239*d9f75844SAndroid Build Coastguard Worker exempt_paths = [re.escape(os.path.join('tools_webrtc', 'ios', 'SDK'))] 1240*d9f75844SAndroid Build Coastguard Worker 1241*d9f75844SAndroid Build Coastguard Worker with _AddToPath( 1242*d9f75844SAndroid Build Coastguard Worker input_api.os_path.join(input_api.PresubmitLocalPath(), 'tools_webrtc', 1243*d9f75844SAndroid Build Coastguard Worker 'presubmit_checks_lib')): 1244*d9f75844SAndroid Build Coastguard Worker from check_orphan_headers import GetBuildGnPathFromFilePath 1245*d9f75844SAndroid Build Coastguard Worker from check_orphan_headers import IsHeaderInBuildGn 1246*d9f75844SAndroid Build Coastguard Worker 1247*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: input_api.FilterSourceFile( 1248*d9f75844SAndroid Build Coastguard Worker x, files_to_skip=exempt_paths) and source_file_filter(x) 1249*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 1250*d9f75844SAndroid Build Coastguard Worker if f.LocalPath().endswith('.h'): 1251*d9f75844SAndroid Build Coastguard Worker file_path = os.path.abspath(f.LocalPath()) 1252*d9f75844SAndroid Build Coastguard Worker root_dir = os.getcwd() 1253*d9f75844SAndroid Build Coastguard Worker gn_file_path = GetBuildGnPathFromFilePath(file_path, os.path.exists, 1254*d9f75844SAndroid Build Coastguard Worker root_dir) 1255*d9f75844SAndroid Build Coastguard Worker in_build_gn = IsHeaderInBuildGn(file_path, gn_file_path) 1256*d9f75844SAndroid Build Coastguard Worker if not in_build_gn: 1257*d9f75844SAndroid Build Coastguard Worker results.append( 1258*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1259*d9f75844SAndroid Build Coastguard Worker error_msg.format(f.LocalPath(), os.path.relpath(gn_file_path)))) 1260*d9f75844SAndroid Build Coastguard Worker return results 1261*d9f75844SAndroid Build Coastguard Worker 1262*d9f75844SAndroid Build Coastguard Worker 1263*d9f75844SAndroid Build Coastguard Workerdef CheckNewlineAtTheEndOfProtoFiles(input_api, output_api, 1264*d9f75844SAndroid Build Coastguard Worker source_file_filter): 1265*d9f75844SAndroid Build Coastguard Worker """Checks that all .proto files are terminated with a newline.""" 1266*d9f75844SAndroid Build Coastguard Worker error_msg = 'File {} must end with exactly one newline.' 1267*d9f75844SAndroid Build Coastguard Worker results = [] 1268*d9f75844SAndroid Build Coastguard Worker file_filter = lambda x: input_api.FilterSourceFile( 1269*d9f75844SAndroid Build Coastguard Worker x, files_to_check=(r'.+\.proto$', )) and source_file_filter(x) 1270*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedSourceFiles(file_filter): 1271*d9f75844SAndroid Build Coastguard Worker file_path = f.LocalPath() 1272*d9f75844SAndroid Build Coastguard Worker with open(file_path) as f: 1273*d9f75844SAndroid Build Coastguard Worker lines = f.readlines() 1274*d9f75844SAndroid Build Coastguard Worker if len(lines) > 0 and not lines[-1].endswith('\n'): 1275*d9f75844SAndroid Build Coastguard Worker results.append(output_api.PresubmitError(error_msg.format(file_path))) 1276*d9f75844SAndroid Build Coastguard Worker return results 1277*d9f75844SAndroid Build Coastguard Worker 1278*d9f75844SAndroid Build Coastguard Worker 1279*d9f75844SAndroid Build Coastguard Workerdef _ExtractAddRulesFromParsedDeps(parsed_deps): 1280*d9f75844SAndroid Build Coastguard Worker """Extract the rules that add dependencies from a parsed DEPS file. 1281*d9f75844SAndroid Build Coastguard Worker 1282*d9f75844SAndroid Build Coastguard Worker Args: 1283*d9f75844SAndroid Build Coastguard Worker parsed_deps: the locals dictionary from evaluating the DEPS file.""" 1284*d9f75844SAndroid Build Coastguard Worker add_rules = set() 1285*d9f75844SAndroid Build Coastguard Worker add_rules.update([ 1286*d9f75844SAndroid Build Coastguard Worker rule[1:] for rule in parsed_deps.get('include_rules', []) 1287*d9f75844SAndroid Build Coastguard Worker if rule.startswith('+') or rule.startswith('!') 1288*d9f75844SAndroid Build Coastguard Worker ]) 1289*d9f75844SAndroid Build Coastguard Worker for _, rules in parsed_deps.get('specific_include_rules', {}).items(): 1290*d9f75844SAndroid Build Coastguard Worker add_rules.update([ 1291*d9f75844SAndroid Build Coastguard Worker rule[1:] for rule in rules 1292*d9f75844SAndroid Build Coastguard Worker if rule.startswith('+') or rule.startswith('!') 1293*d9f75844SAndroid Build Coastguard Worker ]) 1294*d9f75844SAndroid Build Coastguard Worker return add_rules 1295*d9f75844SAndroid Build Coastguard Worker 1296*d9f75844SAndroid Build Coastguard Worker 1297*d9f75844SAndroid Build Coastguard Workerdef _ParseDeps(contents): 1298*d9f75844SAndroid Build Coastguard Worker """Simple helper for parsing DEPS files.""" 1299*d9f75844SAndroid Build Coastguard Worker 1300*d9f75844SAndroid Build Coastguard Worker # Stubs for handling special syntax in the root DEPS file. 1301*d9f75844SAndroid Build Coastguard Worker class VarImpl: 1302*d9f75844SAndroid Build Coastguard Worker def __init__(self, local_scope): 1303*d9f75844SAndroid Build Coastguard Worker self._local_scope = local_scope 1304*d9f75844SAndroid Build Coastguard Worker 1305*d9f75844SAndroid Build Coastguard Worker def Lookup(self, var_name): 1306*d9f75844SAndroid Build Coastguard Worker """Implements the Var syntax.""" 1307*d9f75844SAndroid Build Coastguard Worker try: 1308*d9f75844SAndroid Build Coastguard Worker return self._local_scope['vars'][var_name] 1309*d9f75844SAndroid Build Coastguard Worker except KeyError as var_not_defined: 1310*d9f75844SAndroid Build Coastguard Worker raise Exception('Var is not defined: %s' % 1311*d9f75844SAndroid Build Coastguard Worker var_name) from var_not_defined 1312*d9f75844SAndroid Build Coastguard Worker 1313*d9f75844SAndroid Build Coastguard Worker local_scope = {} 1314*d9f75844SAndroid Build Coastguard Worker global_scope = { 1315*d9f75844SAndroid Build Coastguard Worker 'Var': VarImpl(local_scope).Lookup, 1316*d9f75844SAndroid Build Coastguard Worker } 1317*d9f75844SAndroid Build Coastguard Worker exec(contents, global_scope, local_scope) 1318*d9f75844SAndroid Build Coastguard Worker return local_scope 1319*d9f75844SAndroid Build Coastguard Worker 1320*d9f75844SAndroid Build Coastguard Worker 1321*d9f75844SAndroid Build Coastguard Workerdef _CalculateAddedDeps(os_path, old_contents, new_contents): 1322*d9f75844SAndroid Build Coastguard Worker """Helper method for _CheckAddedDepsHaveTargetApprovals. Returns 1323*d9f75844SAndroid Build Coastguard Worker a set of DEPS entries that we should look up. 1324*d9f75844SAndroid Build Coastguard Worker 1325*d9f75844SAndroid Build Coastguard Worker For a directory (rather than a specific filename) we fake a path to 1326*d9f75844SAndroid Build Coastguard Worker a specific filename by adding /DEPS. This is chosen as a file that 1327*d9f75844SAndroid Build Coastguard Worker will seldom or never be subject to per-file include_rules. 1328*d9f75844SAndroid Build Coastguard Worker """ 1329*d9f75844SAndroid Build Coastguard Worker # We ignore deps entries on auto-generated directories. 1330*d9f75844SAndroid Build Coastguard Worker auto_generated_dirs = ['grit', 'jni'] 1331*d9f75844SAndroid Build Coastguard Worker 1332*d9f75844SAndroid Build Coastguard Worker old_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(old_contents)) 1333*d9f75844SAndroid Build Coastguard Worker new_deps = _ExtractAddRulesFromParsedDeps(_ParseDeps(new_contents)) 1334*d9f75844SAndroid Build Coastguard Worker 1335*d9f75844SAndroid Build Coastguard Worker added_deps = new_deps.difference(old_deps) 1336*d9f75844SAndroid Build Coastguard Worker 1337*d9f75844SAndroid Build Coastguard Worker results = set() 1338*d9f75844SAndroid Build Coastguard Worker for added_dep in added_deps: 1339*d9f75844SAndroid Build Coastguard Worker if added_dep.split('/')[0] in auto_generated_dirs: 1340*d9f75844SAndroid Build Coastguard Worker continue 1341*d9f75844SAndroid Build Coastguard Worker # Assume that a rule that ends in .h is a rule for a specific file. 1342*d9f75844SAndroid Build Coastguard Worker if added_dep.endswith('.h'): 1343*d9f75844SAndroid Build Coastguard Worker results.add(added_dep) 1344*d9f75844SAndroid Build Coastguard Worker else: 1345*d9f75844SAndroid Build Coastguard Worker results.add(os_path.join(added_dep, 'DEPS')) 1346*d9f75844SAndroid Build Coastguard Worker return results 1347*d9f75844SAndroid Build Coastguard Worker 1348*d9f75844SAndroid Build Coastguard Worker 1349*d9f75844SAndroid Build Coastguard Workerdef CheckAddedDepsHaveTargetApprovals(input_api, output_api): 1350*d9f75844SAndroid Build Coastguard Worker """When a dependency prefixed with + is added to a DEPS file, we 1351*d9f75844SAndroid Build Coastguard Worker want to make sure that the change is reviewed by an OWNER of the 1352*d9f75844SAndroid Build Coastguard Worker target file or directory, to avoid layering violations from being 1353*d9f75844SAndroid Build Coastguard Worker introduced. This check verifies that this happens. 1354*d9f75844SAndroid Build Coastguard Worker """ 1355*d9f75844SAndroid Build Coastguard Worker virtual_depended_on_files = set() 1356*d9f75844SAndroid Build Coastguard Worker 1357*d9f75844SAndroid Build Coastguard Worker file_filter = lambda f: not input_api.re.match( 1358*d9f75844SAndroid Build Coastguard Worker r"^third_party[\\\/](WebKit|blink)[\\\/].*", f.LocalPath()) 1359*d9f75844SAndroid Build Coastguard Worker for f in input_api.AffectedFiles(include_deletes=False, 1360*d9f75844SAndroid Build Coastguard Worker file_filter=file_filter): 1361*d9f75844SAndroid Build Coastguard Worker filename = input_api.os_path.basename(f.LocalPath()) 1362*d9f75844SAndroid Build Coastguard Worker if filename == 'DEPS': 1363*d9f75844SAndroid Build Coastguard Worker virtual_depended_on_files.update( 1364*d9f75844SAndroid Build Coastguard Worker _CalculateAddedDeps(input_api.os_path, '\n'.join(f.OldContents()), 1365*d9f75844SAndroid Build Coastguard Worker '\n'.join(f.NewContents()))) 1366*d9f75844SAndroid Build Coastguard Worker 1367*d9f75844SAndroid Build Coastguard Worker if not virtual_depended_on_files: 1368*d9f75844SAndroid Build Coastguard Worker return [] 1369*d9f75844SAndroid Build Coastguard Worker 1370*d9f75844SAndroid Build Coastguard Worker if input_api.is_committing: 1371*d9f75844SAndroid Build Coastguard Worker if input_api.tbr: 1372*d9f75844SAndroid Build Coastguard Worker return [ 1373*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitNotifyResult( 1374*d9f75844SAndroid Build Coastguard Worker '--tbr was specified, skipping OWNERS check for DEPS ' 1375*d9f75844SAndroid Build Coastguard Worker 'additions') 1376*d9f75844SAndroid Build Coastguard Worker ] 1377*d9f75844SAndroid Build Coastguard Worker if input_api.dry_run: 1378*d9f75844SAndroid Build Coastguard Worker return [ 1379*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitNotifyResult( 1380*d9f75844SAndroid Build Coastguard Worker 'This is a dry run, skipping OWNERS check for DEPS ' 1381*d9f75844SAndroid Build Coastguard Worker 'additions') 1382*d9f75844SAndroid Build Coastguard Worker ] 1383*d9f75844SAndroid Build Coastguard Worker if not input_api.change.issue: 1384*d9f75844SAndroid Build Coastguard Worker return [ 1385*d9f75844SAndroid Build Coastguard Worker output_api.PresubmitError( 1386*d9f75844SAndroid Build Coastguard Worker "DEPS approval by OWNERS check failed: this change has " 1387*d9f75844SAndroid Build Coastguard Worker "no change number, so we can't check it for approvals.") 1388*d9f75844SAndroid Build Coastguard Worker ] 1389*d9f75844SAndroid Build Coastguard Worker output = output_api.PresubmitError 1390*d9f75844SAndroid Build Coastguard Worker else: 1391*d9f75844SAndroid Build Coastguard Worker output = output_api.PresubmitNotifyResult 1392*d9f75844SAndroid Build Coastguard Worker 1393*d9f75844SAndroid Build Coastguard Worker owner_email, reviewers = ( 1394*d9f75844SAndroid Build Coastguard Worker input_api.canned_checks.GetCodereviewOwnerAndReviewers( 1395*d9f75844SAndroid Build Coastguard Worker input_api, None, approval_needed=input_api.is_committing)) 1396*d9f75844SAndroid Build Coastguard Worker 1397*d9f75844SAndroid Build Coastguard Worker owner_email = owner_email or input_api.change.author_email 1398*d9f75844SAndroid Build Coastguard Worker 1399*d9f75844SAndroid Build Coastguard Worker approval_status = input_api.owners_client.GetFilesApprovalStatus( 1400*d9f75844SAndroid Build Coastguard Worker virtual_depended_on_files, reviewers.union([owner_email]), []) 1401*d9f75844SAndroid Build Coastguard Worker missing_files = [ 1402*d9f75844SAndroid Build Coastguard Worker f for f in virtual_depended_on_files 1403*d9f75844SAndroid Build Coastguard Worker if approval_status[f] != input_api.owners_client.APPROVED 1404*d9f75844SAndroid Build Coastguard Worker ] 1405*d9f75844SAndroid Build Coastguard Worker 1406*d9f75844SAndroid Build Coastguard Worker # We strip the /DEPS part that was added by 1407*d9f75844SAndroid Build Coastguard Worker # _FilesToCheckForIncomingDeps to fake a path to a file in a 1408*d9f75844SAndroid Build Coastguard Worker # directory. 1409*d9f75844SAndroid Build Coastguard Worker def StripDeps(path): 1410*d9f75844SAndroid Build Coastguard Worker start_deps = path.rfind('/DEPS') 1411*d9f75844SAndroid Build Coastguard Worker if start_deps != -1: 1412*d9f75844SAndroid Build Coastguard Worker return path[:start_deps] 1413*d9f75844SAndroid Build Coastguard Worker return path 1414*d9f75844SAndroid Build Coastguard Worker 1415*d9f75844SAndroid Build Coastguard Worker unapproved_dependencies = [ 1416*d9f75844SAndroid Build Coastguard Worker "'+%s'," % StripDeps(path) for path in missing_files 1417*d9f75844SAndroid Build Coastguard Worker ] 1418*d9f75844SAndroid Build Coastguard Worker 1419*d9f75844SAndroid Build Coastguard Worker if unapproved_dependencies: 1420*d9f75844SAndroid Build Coastguard Worker output_list = [ 1421*d9f75844SAndroid Build Coastguard Worker output('You need LGTM from owners of depends-on paths in DEPS that ' 1422*d9f75844SAndroid Build Coastguard Worker ' were modified in this CL:\n %s' % 1423*d9f75844SAndroid Build Coastguard Worker '\n '.join(sorted(unapproved_dependencies))) 1424*d9f75844SAndroid Build Coastguard Worker ] 1425*d9f75844SAndroid Build Coastguard Worker suggested_owners = input_api.owners_client.SuggestOwners( 1426*d9f75844SAndroid Build Coastguard Worker missing_files, exclude=[owner_email]) 1427*d9f75844SAndroid Build Coastguard Worker output_list.append( 1428*d9f75844SAndroid Build Coastguard Worker output('Suggested missing target path OWNERS:\n %s' % 1429*d9f75844SAndroid Build Coastguard Worker '\n '.join(suggested_owners or []))) 1430*d9f75844SAndroid Build Coastguard Worker return output_list 1431*d9f75844SAndroid Build Coastguard Worker 1432*d9f75844SAndroid Build Coastguard Worker return [] 1433