"""Rootfs builder — creates the root filesystem.""" from __future__ import annotations import shutil import tempfile from pathlib import Path from .distros import get as get_distro from .distros.base import set_mode def build(config: dict, output: Path) -> Path: """Build a rootfs and return its path.""" set_mode(config.get("_mode", "root")) distro_name = config["distro"] # map distro name to backend (horizon = void) backend_name = "void" if distro_name == "horizon" else distro_name distro_cls = get_distro(backend_name) # artix vs arch if backend_name in ("artix",): distro = distro_cls(family="artix") elif backend_name in ("debian", "ubuntu"): distro = distro_cls(family=backend_name) elif backend_name in ("fedora", "rocky", "almalinux"): distro = distro_cls(family=backend_name) else: distro = distro_cls() rootfs = Path(tempfile.mkdtemp(prefix="mklive-")) print(f"\n\033[1;36m==>\033[0m \033[1mBuilding rootfs in {rootfs}\033[0m") # 1. bootstrap print(f"\033[1;36m==>\033[0m \033[1m[1/4] Bootstrapping {distro_name}...\033[0m") distro.bootstrap(rootfs, config) # 2. install packages pkgs = config.get("packages", []) if pkgs: print(f"\033[1;36m==>\033[0m \033[1m[2/4] Installing {len(pkgs)} packages...\033[0m") distro.install_packages(rootfs, pkgs) else: print(f"\033[1;36m==>\033[0m \033[1m[2/4] No extra packages to install\033[0m") # 3. configure print(f"\033[1;36m==>\033[0m \033[1m[3/4] Configuring base system...\033[0m") distro.configure_base(rootfs, config) # 3b. overlay files (if any) — artools-style root-overlay merge overlay = config.get("overlay") if overlay: overlay_path = Path(overlay) if overlay_path.is_dir(): import subprocess subprocess.run(["cp", "-a", f"{overlay_path}/.", str(rootfs)], check=False, capture_output=True) print(f" \033[90m merged:\033[0m overlay -> rootfs") # 3c. write /etc/os-release only if user provided a name iso_cfg = config.get("iso", {}) iso_name = iso_cfg.get("name", "") if iso_name: iso_version = iso_cfg.get("version", "1.0") os_id = iso_name.lower().replace(" ", "-").replace("/", "-") osrelease = rootfs / "etc" / "os-release" osrelease.parent.mkdir(parents=True, exist_ok=True) osrelease.write_text( f'NAME="{iso_name}"\n' f'VERSION="{iso_version}"\n' f'ID={os_id}\n' f'VERSION_ID="{iso_version}"\n' f'ID_LIKE="{config["distro"]}"\n' f'PRETTY_NAME="{iso_name} {iso_version}"\n' ) print(f" \033[90m wrote:\033[0m /etc/os-release") # 4. bootloader print(f"\033[1;36m==>\033[0m \033[1m[4/4] Installing bootloader...\033[0m") distro.install_bootloader(rootfs, config) return rootfs def cleanup(rootfs: Path) -> None: """Remove the temporary rootfs.""" shutil.rmtree(rootfs, ignore_errors=True)