blob: 0ad3ad6e128ca92430223284675f514aa1b61fa8 [file] [log] [blame] [edit]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2025 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument(
"--bazel",
type=Path,
required=True,
help="Path to Bazel executable",
)
parser.add_argument(
"--workspace",
type=Path,
required=True,
help="Path to Bazel workspace",
)
parser.add_argument(
"--bazel-vendor-dir",
type=Path,
required=True,
help="Bazel vendor directory to write to",
)
parser.add_argument(
"--repo",
action="append",
required=True,
help="Bazel repositories to vendor",
)
parser.add_argument(
"--stub-repo",
action="append",
required=True,
help=(
"Bazel repositories that are manually stubbed out, their existing"
" content should be preserved after the update"
),
)
args = parser.parse_args()
# Always do a clean vendor in a temporary directory to drop unwanted repos.
with tempfile.TemporaryDirectory() as tmp:
temp_dir = Path(tmp)
cmd = [
args.bazel,
"vendor",
f"--vendor_dir={temp_dir}",
# Overwrite local-only settings from bazelrc. Allow network access and
# enable Bazel Central repository when updating vendor repositories.
"--downloader_config=/dev/null",
"--registry=https://bcr.bazel.build/",
]
cmd += [f"--repo={repo}" for repo in args.repo]
print(" ".join(str(s) for s in cmd))
# Remove the existing local Bazel registry to force `bazel vendor` to update
# and create a new one.
shutil.rmtree(args.bazel_vendor_dir / "_registries", ignore_errors=True)
subprocess.check_call(
cmd,
cwd=args.workspace,
)
# Pin all the vendored and stub directories, to make sure Bazel doesn't try
# to update any of them when building.
with open(temp_dir / "VENDOR.bazel", "w") as f:
f.write(
"""################################################################################
# @generated
# DO NOT MODIFY: This file is auto-generated by the following command, instead
# of changing this file directly, rerun this command:
#
# fx update-bazel-vendor-dir
################################################################################
"""
)
for repo in sorted(args.repo + args.stub_repo):
f.write(f'pin("{repo}")\n')
# Vendor again after all repositories are pinned to drop the `.marker` files.
# This also verifies the VENDOR.bazel file re-written above is valid.
subprocess.check_call(
cmd,
cwd=args.workspace,
# Suppress stdout and stderr to avoid user confusion.
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
# Persist manually stubbed repos from the existing vendor dir.
for repo in args.stub_repo:
repo_name = repo.lstrip("@")
shutil.copytree(
args.bazel_vendor_dir / repo_name, temp_dir / repo_name
)
shutil.move(args.bazel_vendor_dir / "README.md", temp_dir / "README.md")
shutil.move(args.bazel_vendor_dir / "OWNERS", temp_dir / "OWNERS")
shutil.rmtree(args.bazel_vendor_dir)
shutil.move(temp_dir, args.bazel_vendor_dir)
if __name__ == "__main__":
sys.exit(main())