| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- """Utilities for scripts."""
- __copyright__ = """
- Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- Exceptions. See /LICENSE for license information.
- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- """
- from enum import Enum
- import hashlib
- import os
- from pathlib import Path
- import platform
- import shutil
- import time
- from typing import Optional
- import urllib.request
- _URL = "https://github.com/bazelbuild/buildtools/releases/download/4.2.5/"
- """Version SHAs.
- Gather shas with:
- for f in buildozer buildifier; do
- echo \"$f\": {
- for v in darwin-amd64 darwin-arm64 linux-amd64 linux-arm64 \
- windows-amd64.exe
- do
- echo "\"$v\": \"$(wget -q -O - https://github.com/bazelbuild/buildtools/releases/download/4.2.5/$f-$v | sha256sum | cut -d ' ' -f1)\", # noqa: E501"
- done
- echo },
- done
- """
- _VERSION_SHAS = {
- "buildozer": {
- "darwin-amd64": "3fe671620e6cb7d2386f9da09c1de8de88b02b9dd9275cdecd8b9e417f74df1b", # noqa: E501
- "darwin-arm64": "ff4d297023fe3e0fd14113c78f04cef55289ca5bfe5e45a916be738b948dc743", # noqa: E501
- "linux-amd64": "e8e39b71c52318a9030dd9fcb9bbfd968d0e03e59268c60b489e6e6fc1595d7b", # noqa: E501
- "linux-arm64": "96227142969540def1d23a9e8225524173390d23f3d7fd56ce9c4436953f02fc", # noqa: E501
- "windows-amd64.exe": "2a9a7176cbd3b2f0ef989502128efbafd3b156ddabae93b9c979cd4017ffa300", # noqa: E501
- },
- "buildifier": {
- "darwin-amd64": "757f246040aceb2c9550d02ef5d1f22d3ef1ff53405fe76ef4c6239ef1ea2cc1", # noqa: E501
- "darwin-arm64": "4cf02e051f6cda18765935cb6e77cc938cf8b405064589a50fe9582f82c7edaf", # noqa: E501
- "linux-amd64": "f94e71b22925aff76ce01a49e1c6c6d31f521bbbccff047b81f2ea01fd01a945", # noqa: E501
- "linux-arm64": "2113d79e45efb51e2b3013c8737cb66cadae3fd89bd7e820438cb06201e50874", # noqa: E501
- "windows-amd64.exe": "4185a40d3154cacbe8b79f570b94e2c6f74fc9e317362b7d028c2e6c94edf9ba", # noqa: E501
- },
- }
- class Release(Enum):
- BUILDOZER = "buildozer"
- BUILDIFIER = "buildifier"
- def chdir_repo_root() -> None:
- """Change the working directory to the repository root.
- This is done so that scripts run from a consistent directory.
- """
- os.chdir(Path(__file__).parent.parent)
- def _get_hash(file: Path) -> str:
- """Returns the sha256 of a file."""
- digest = hashlib.sha256()
- with file.open("rb") as f:
- while True:
- chunk = f.read(1024 * 64)
- if not chunk:
- break
- digest.update(chunk)
- return digest.hexdigest()
- def _download(url: str, local_path: Path) -> Optional[int]:
- """Downloads the URL to the path. Returns an HTTP error code on failure."""
- with urllib.request.urlopen(url) as response:
- if response.code != 200:
- return int(response.code)
- with local_path.open("wb") as f:
- shutil.copyfileobj(response, f)
- # Run fsync because of "Text file busy" in GH Actions.
- os.fsync(f.fileno())
- return None
- def get_release(release: Release) -> str:
- """Install a file to carbon-lang's cache.
- release: The release to cache.
- """
- cache_dir = Path.home().joinpath(".cache", "carbon-lang-scripts")
- cache_dir.mkdir(parents=True, exist_ok=True)
- # Translate platform information into Bazel's release form.
- machine = platform.machine()
- if machine == "x86_64":
- machine = "amd64"
- version = f"{platform.system().lower()}-{machine}"
- # Get ready to add .exe for Windows.
- ext = ""
- if platform.system() == "Windows":
- ext = ".exe"
- # Ensure the platform is supported, and grab its hash.
- if version not in _VERSION_SHAS[release.value]:
- # If this because a platform support issue, we may need to print errors.
- exit(f"No {release.value} release available for platform: {version}")
- want_hash = _VERSION_SHAS[release.value][version]
- # Check if there's a cached file that can be used.
- local_path = cache_dir.joinpath(f"{release.value}{ext}")
- if local_path.is_file() and want_hash == _get_hash(local_path):
- return str(local_path)
- # Download the file.
- url = f"{_URL}/{release.value}-{version}{ext}"
- retries = 5
- while True:
- err = _download(url, local_path)
- if err is None:
- break
- retries -= 1
- if retries == 0:
- exit(f"Failed to download {release.value}-{version}: HTTP {err}.")
- time.sleep(1)
- local_path.chmod(0o755)
- # Verify the downloaded hash.
- found_hash = _get_hash(local_path)
- if want_hash != found_hash:
- exit(
- f"Downloaded {release.value}-{version} but found sha256 "
- f"{found_hash}, wanted {want_hash}"
- )
- return str(local_path)
- def locate_bazel() -> str:
- """Returns the bazel command.
- We use the `BAZEL` environment variable if present. If not, then we try to
- use `bazelisk` and then `bazel`.
- """
- bazel = os.environ.get("BAZEL")
- if bazel:
- return bazel
- if shutil.which("bazelisk"):
- return "bazelisk"
- if shutil.which("bazel"):
- return "bazel"
- exit("Unable to run Bazel")
|