50 lines
1.8 KiB
Python
50 lines
1.8 KiB
Python
import importlib.util
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from src.layout import Layout
|
|
|
|
REQUIRED_KEYS = ("arch", "triple", "container_image")
|
|
|
|
|
|
def _load_module(path: Path, name: str):
|
|
spec = importlib.util.spec_from_file_location(name, path)
|
|
if spec is None or spec.loader is None:
|
|
raise RuntimeError(f"cannot load profile module {path}")
|
|
mod = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(mod)
|
|
return mod
|
|
|
|
|
|
def load_profile(layout: Layout) -> dict[str, Any]:
|
|
link = layout.profile_link
|
|
if not link.exists():
|
|
raise FileNotFoundError(f"{link} missing a profile")
|
|
target = link.resolve()
|
|
if not target.is_file():
|
|
raise FileNotFoundError(f"profile {target.name}: missing config.py")
|
|
mod = _load_module(target, f"orchid_profile_{target.name}")
|
|
if not hasattr(mod, "profile"):
|
|
raise AttributeError(f"profile {target.name}: config.py must define profile()")
|
|
data = mod.profile()
|
|
if not isinstance(data, dict):
|
|
raise TypeError(f"profile {target.name}: profile() must return a dict")
|
|
missing = [k for k in REQUIRED_KEYS if k not in data]
|
|
if missing:
|
|
raise ValueError(f"profile {target.name}: missing keys {missing}")
|
|
data["__name__"] = target.name
|
|
return data
|
|
|
|
|
|
def init_build_dir(build: Path, repo: Path, profile_name: str) -> None:
|
|
profile_src = repo / "profiles" / (profile_name + ".py")
|
|
if not (profile_src).is_file():
|
|
raise FileNotFoundError(f"profile {profile_name!r} not found at {profile_src}")
|
|
build.mkdir(parents=True, exist_ok=False)
|
|
link = build / "profile"
|
|
# Use relative symlink so the build dir can be moved with the repo.
|
|
import os
|
|
|
|
rel = Path(os.path.relpath(profile_src, build))
|
|
link.symlink_to(rel)
|