Files
plezy/scripts/fetch_linux_libmpv.py
edde746 b27cab4510 build: read Windows libmpv pins from the lock and share the Linux fetch and version parsing
windows/CMakeLists.txt repeated the mpv-build key, asset base, and both
SHA-256 values that mpv-build.lock.json already owns, and the pin mover
never touched it, so a lock bump left Windows silently stale. CMake now
reads artifacts.windows with string(JSON) (floor raised to 3.19) and the
Windows native cache key hashes the lock; a workflow guard rejects
hand-pinned checksums.

The byte-identical Linux libmpv fetch heredoc in build.yml and ci.yml
moves to scripts/fetch_linux_libmpv.py, which verifies the checksum
before extracting and is what the packaging script now points local
builds at. The package-windows and release jobs and
linux/packaging/build-packages.py read the version through
scripts/pubspec_version.py instead of three looser regexes.
2026-09-03 11:36:29 +02:00

89 lines
2.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""Fetch the pinned Linux libmpv prefix named by mpv-build.lock.json.
Reads artifacts.linux for this machine's architecture, downloads the asset,
verifies its SHA-256 against the lock before a single byte is extracted, then
untars the self-relocating prefix tree into --dest. Shared by build.yml,
ci.yml, and local packaging builds so the contract lives in one place.
"""
import argparse
import hashlib
import json
import platform
import shutil
import subprocess
import sys
import tempfile
import urllib.request
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
DEFAULT_LOCK = ROOT / "mpv-build.lock.json"
def main() -> int:
parser = argparse.ArgumentParser(
description="Download and verify the locked Linux libmpv prefix."
)
parser.add_argument(
"--lock",
type=Path,
default=DEFAULT_LOCK,
help="path to mpv-build.lock.json (default: the repository lock)",
)
parser.add_argument(
"--dest",
type=Path,
default=Path("libmpv-prefix"),
help="directory to extract the prefix tree into (default: libmpv-prefix)",
)
args = parser.parse_args()
if shutil.which("zstd") is None:
print(
"Error: zstd is required to extract the libmpv archive "
"(install it, e.g. apt-get install zstd)",
file=sys.stderr,
)
return 1
lock = json.loads(args.lock.read_text(encoding="utf-8"))
group = lock["artifacts"]["linux"]
machine = platform.machine()
entry = group["assets"].get(machine)
if entry is None:
print(
f"Error: {args.lock}: no linux asset for {machine!r} "
f"(locked: {', '.join(sorted(group['assets']))})",
file=sys.stderr,
)
return 1
url = f"{group['assetBase']}/{entry['asset']}"
print(f"fetching {url}", flush=True)
with urllib.request.urlopen(url) as response:
data = response.read()
digest = hashlib.sha256(data).hexdigest()
if digest != entry["checksum"]:
print(
f"Error: {entry['asset']}: SHA-256 {digest} does not match "
f"locked {entry['checksum']}",
file=sys.stderr,
)
return 1
args.dest.mkdir(parents=True, exist_ok=True)
with tempfile.NamedTemporaryFile(suffix=".tar.zst") as archive:
archive.write(data)
archive.flush()
subprocess.run(
["tar", "--zstd", "-xf", archive.name, "-C", str(args.dest)],
check=True,
)
return 0
if __name__ == "__main__":
sys.exit(main())