diff --git a/PRESUBMIT.py b/PRESUBMIT.py index e533507ac0..96cdbf1d13 100755 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py @@ -410,6 +410,10 @@ def _ReportErrorFileAndLineNumber(filename, line_num): def CheckNoStreamUsageIsAdded(input_api, output_api, error_formatter=_ReportErrorFileAndLineNumber): """Make sure that no more dependencies on stringstream are added.""" + with _AddToPath(input_api.os_path.join( + input_api.PresubmitLocalPath(), 'tools_webrtc', 'presubmit_checks_lib')): + from gn_refs import DefaultGnProject, BelongsToTestTarget + error_msg = ('Usage of , and in WebRTC is ' 'deprecated.\n' 'This includes the following types:\n' @@ -433,13 +437,15 @@ def CheckNoStreamUsageIsAdded(input_api, output_api, usage_re = input_api.re.compile(r'std::(w|i|o|io|wi|wo|wio)(string)*stream') no_presubmit_re = input_api.re.compile( r' // no-presubmit-check TODO\(webrtc:8982\)') - for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile): - if f.LocalPath() == 'PRESUBMIT.py': - continue - for line_num, line in f.ChangedContents(): - if ((include_re.search(line) or usage_re.search(line)) - and not no_presubmit_re.search(line)): - errors.append(error_formatter(f.LocalPath(), line_num)) + is_cpp_file = lambda f: f.LocalPath().endswith(('.cc', '.h')) + with DefaultGnProject() as out_dir: + for f in input_api.AffectedFiles(file_filter=is_cpp_file): + if BelongsToTestTarget(f.LocalPath(), out_dir): + continue + for line_num, line in f.ChangedContents(): + if ((include_re.search(line) or usage_re.search(line)) + and not no_presubmit_re.search(line)): + errors.append(error_formatter(f.LocalPath(), line_num)) if errors: return [output_api.PresubmitError(error_msg, errors)] return [] diff --git a/tools_webrtc/presubmit_checks_lib/gn_refs.py b/tools_webrtc/presubmit_checks_lib/gn_refs.py new file mode 100644 index 0000000000..3f062eb57f --- /dev/null +++ b/tools_webrtc/presubmit_checks_lib/gn_refs.py @@ -0,0 +1,70 @@ +# Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. +# +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file in the root of the source +# tree. An additional intellectual property rights grant can be found +# in the file PATENTS. All contributing project authors may +# be found in the AUTHORS file in the root of the source tree. + +import os +import shutil +import subprocess +import sys +import tempfile +from contextlib import contextmanager + + +# The module find_depot_tools lives into the ./build directory. +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir)) +sys.path.append(os.path.join(SRC_DIR, 'build')) +import find_depot_tools + + +@contextmanager +def DefaultGnProject(): + """Generates a GN projects with defaul args and returns the path to it.""" + out_dir = tempfile.mkdtemp('gn') + gen_command = [ + sys.executable, + os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py'), + 'gen', + out_dir, + ] + subprocess.check_output(gen_command) + try: + yield out_dir + finally: + shutil.rmtree(out_dir, ignore_errors=True) + + +def BelongsToTestTarget(file_path, out_dir): + """Returns True if file_path is part of a testonly build target. + + This function relies on 'gn refs'. It actually runs: + $ gn refs file_path --testonly=true` + + Which returns a list of build targets containing file_path (well, only + one build target should own a file, but that is not a strict rule). + + If the list is empty, it means the file is owned by a non-testonly build + target and the function will return False. Otherwise it will return True. + + Args: + file_path: string with the local path of the file to analyze. + out_dir: the path to the GN out directory to analyze. + + Returns: + boolean: True if the file belongs to a testonly build target. + """ + refs_command = [ + sys.executable, + os.path.join(find_depot_tools.DEPOT_TOOLS_PATH, 'gn.py'), + 'refs', + out_dir, + file_path, + '--testonly=true' + ] + output = subprocess.check_output(refs_command) + # If file_path belongs to a test target, output will contain a list of them. + return output != ''