File size: 2,763 Bytes
95200a7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | """Merge a fragment printed by `record_llama_pin.py` into `llama_runtime.json`.
The recorder deliberately does not write the file: a digest belongs in the
repository only once somebody has looked at it. This does the mechanical half
of that -- read the fragment, put it in the right place, keep the file's
formatting and its explanatory comment intact -- and prints the resulting entry
so the change is still something a person reads before it is committed.
Usage::
python scripts/record_llama_pin.py windows-x64-cuda > cuda-pin.json
python scripts/apply_llama_pin.py cuda-pin.json
Refuses a fragment whose URLs are not GitHub, and refuses one whose digests are
not 64 hex characters, because a pin that fails those checks will be refused at
install time anyway and is better refused here where somebody is watching.
"""
from __future__ import annotations
import json
import re
import sys
from pathlib import Path
PIN_FILE = Path(__file__).resolve().parent.parent / "llama_runtime.json"
_SHA = re.compile(r"^[0-9a-f]{64}$")
_GITHUB = ("https://github.com/", "https://objects.githubusercontent.com/")
def _archives(entry: dict) -> list[dict]:
listed = entry.get("archives")
return list(listed) if isinstance(listed, list) else [entry]
def _check(key: str, entry: dict) -> list[str]:
problems = []
for archive in _archives(entry):
url = str(archive.get("url", ""))
digest = str(archive.get("sha256", "")).casefold()
if not url.startswith(_GITHUB):
problems.append(f"{key}: {url!r} is not a GitHub release URL")
if not _SHA.match(digest):
problems.append(f"{key}: {digest!r} is not a SHA-256 digest")
if not _archives(entry):
problems.append(f"{key}: names no archives")
return problems
def main(argv: list[str]) -> int:
if len(argv) != 1:
print(__doc__, file=sys.stderr)
return 2
fragment = json.loads(Path(argv[0]).read_text(encoding="utf-8"))
if not isinstance(fragment, dict) or not fragment:
print("the fragment is not a JSON object of builds", file=sys.stderr)
return 1
problems = [line for key, entry in fragment.items() for line in _check(key, entry)]
if problems:
print("\n".join(problems), file=sys.stderr)
return 1
pins = json.loads(PIN_FILE.read_text(encoding="utf-8"))
builds = pins.setdefault("builds", {})
for key, entry in fragment.items():
was = builds.get(key)
builds[key] = entry
print(f"{'replaced' if was else 'added'} {key}")
print(json.dumps(entry, indent=2))
PIN_FILE.write_text(json.dumps(pins, indent=2) + "\n", encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main(sys.argv[1:]))
|