# flake8: noqa from __future__ import annotations import json import subprocess from typing import Any from dataclasses import dataclass from collections.abc import Callable @dataclass class ProcessResult[T]: stdout: T returncode: int def success(self) -> bool: return self.returncode == 0 def map[U](self, f: Callable[[T], U]) -> ProcessResult[U]: new_stdout: U = f(self.stdout) return ProcessResult(stdout=new_stdout, returncode=self.returncode) def run(*cmd: str) -> ProcessResult[str]: print(f"running {cmd!r}") proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=None, stdin=subprocess.DEVNULL, text=True ) (stdout_data, _) = proc.communicate() print(f"finished, exit code {proc.returncode}") return ProcessResult(stdout=stdout_data, returncode=proc.returncode) def must_succeed(*cmd: str) -> str: res = run(*cmd) assert res.success() return res.stdout def parse_maybe_json(maybe_json: str) -> Any: if maybe_json.strip() == "": return None else: return json.loads(maybe_json) def run_json(*cmd: str) -> ProcessResult[Any]: res = run(*cmd) return res.map(parse_maybe_json) def do_build(installable: str, impure: bool) -> bool: eval_command = ["nix", "derivation", "show", installable] if impure: eval_command.append("--impure") res = run_json(*eval_command) if not res.success(): return False drv_paths = list(res.stdout.keys()) for drv_path in drv_paths: print(f"{installable=} {drv_path=}") res = run_json( "nix", "build", "-j1", "--keep-going", "--no-link", "--json", drv_path + "^*", ) if not res.success(): return False builds = res.stdout for build in builds: for out_path in build["outputs"].values(): print(f"{installable=} {out_path=}") res = run("into-nix-cache", out_path) if not res.success(): return False return True res = run_json("nix", "eval", ".#.", "--json", "--apply", "f: f.archival.archiveList") assert res.success() build_list = res.stdout for info in build_list: name = info["name"] if info["broken"]: print(f"Skipping {name}, marked broken") continue res = do_build(f".#archival.drvs.{name}", impure=info["impure"]) if not res: continue do_build(f".#archival.buildDepsDrvs.{name}", impure=info["impure"])