chromium/third_party/blink/tools/blinkpy/presubmit/common_checks.py

# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import tempfile
from typing import Optional


def lint_wpt_root(input_api, output_api, repo_root: Optional[str] = None):
    """Run `wpt lint` against the specified directory."""
    repo_root = repo_root or input_api.PresubmitLocalPath()
    wpt_root = input_api.os_path.join(input_api.change.RepositoryRoot(),
                                      'third_party', 'wpt_tools', 'wpt')
    wpt_executable = input_api.os_path.join(wpt_root, 'wpt')

    # TODO(crbug.com/1406669): Changing a test file should also lint its
    # corresponding reference/*-expected.txt file, if any, because the
    # test-side change may invalidate the other files' contents. For example,
    # removing a test variant will orphan its expectations.
    paths = []
    for abs_path in input_api.AbsoluteLocalPaths():
        if abs_path.endswith(input_api.os_path.relpath(abs_path, repo_root)):
            paths.append(abs_path)

    # Without an explicit file list, `wpt lint` will lint all files in the
    # root, which is slow.
    if not paths:
        return []

    # We have to set delete=False and then let the object go out of scope so
    # that the file can be opened by name on Windows.
    with tempfile.NamedTemporaryFile('w+', newline='', delete=False) as f:
        for path in paths:
            f.write(f'{path}\n')
        paths_name = f.name
    args = [
        input_api.python3_executable,
        wpt_executable,
        # Third-party packages are vended through vpython instead of plain
        # virtualenv.
        f'--venv={wpt_root}',
        '--skip-venv-setup',
        'lint',
        f'--repo-root={repo_root}',
        # To avoid false positives, do not lint files not upstreamed from
        # Chromium.
        '--ignore-glob=*-expected.txt',
        '--ignore-glob=*.ini',
        '--ignore-glob=*DIR_METADATA',
        '--ignore-glob=*OWNERS',
        '--ignore-glob=config.json',
        f'--paths-file={paths_name}',
    ]

    proc = input_api.subprocess.Popen(args,
                                      stdout=input_api.subprocess.PIPE,
                                      stderr=input_api.subprocess.PIPE)
    stdout, stderr = proc.communicate()
    os.remove(paths_name)

    if proc.returncode != 0:
        return [
            output_api.PresubmitError('`wpt lint` failed:',
                                      long_text=(stdout + stderr).decode())
        ]
    return []