feat: wire backends to bundled binaries via _tool()
Backends now resolve package managers from euri_mklive/bin/ first, falling back to system PATH. No more host_deps for package managers.
This commit is contained in:
@@ -7,7 +7,7 @@ from .base import Distro
|
||||
|
||||
class Alpine(Distro):
|
||||
name = "alpine"
|
||||
host_deps = ["apk-tools", "squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
host_deps = ["squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
|
||||
MIRROR = "https://dl-cdn.alpinelinux.org/alpine/latest-stable"
|
||||
|
||||
@@ -17,7 +17,7 @@ class Alpine(Distro):
|
||||
init = config.get("init", "openrc")
|
||||
|
||||
cmd = [
|
||||
"apk",
|
||||
self._tool("apk"),
|
||||
"-X", f"{mirror}/{branch}/main",
|
||||
"-U",
|
||||
"--allow-untrusted",
|
||||
@@ -36,7 +36,7 @@ class Alpine(Distro):
|
||||
def install_packages(self, rootfs: Path, packages: list[str]) -> None:
|
||||
if not packages:
|
||||
return
|
||||
self._run_chroot(rootfs, ["apk", "add", *packages])
|
||||
self._run_chroot(rootfs, [self._tool("apk"), "add", *packages])
|
||||
|
||||
def configure_base(self, rootfs: Path, config: dict) -> None:
|
||||
hostname = config.get("hostname", "euri")
|
||||
@@ -57,7 +57,8 @@ class Alpine(Distro):
|
||||
self._run_chroot(rootfs, ["rc-update", "add", svc, "default"])
|
||||
|
||||
def install_bootloader(self, rootfs: Path, config: dict) -> None:
|
||||
self._run_chroot(rootfs, ["apk", "add", "grub", "grub-efi", "os-prober"])
|
||||
pm = self._tool("apk")
|
||||
self._run_chroot(rootfs, [pm, "add", "grub", "grub-efi", "os-prober"])
|
||||
self._run_chroot(rootfs, ["grub-install", "--target=i386-pc", "/dev/sda"])
|
||||
self._run_chroot(rootfs, ["grub-install", "--target=x86_64-efi", "--efi-directory=/boot/efi"])
|
||||
self._run_chroot(rootfs, ["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])
|
||||
|
||||
@@ -19,19 +19,16 @@ class Arch(Distro):
|
||||
base_pkgs = ["base", "base-devel", f"{init}", *config.get("base_packages", [])]
|
||||
|
||||
if self.family == "artix":
|
||||
# basestrap for Artix
|
||||
elogind_pkg = f"elogind-{init}"
|
||||
cmd = ["basestrap", "-i", str(rootfs), *base_pkgs, elogind_pkg]
|
||||
cmd = [self._tool("pacstrap"), "-i", str(rootfs), *base_pkgs, elogind_pkg]
|
||||
else:
|
||||
# pacstrap for Arch
|
||||
cmd = ["pacstrap", "-K", str(rootfs), *base_pkgs]
|
||||
cmd = [self._tool("pacstrap"), "-K", str(rootfs), *base_pkgs]
|
||||
|
||||
self._run(cmd)
|
||||
|
||||
def install_packages(self, rootfs: Path, packages: list[str]) -> None:
|
||||
# always include the package manager itself
|
||||
pkgs = ["pacman", *packages]
|
||||
self._run_chroot(rootfs, ["pacman", "-Syu", "--noconfirm", *pkgs])
|
||||
pm = self._tool("pacman")
|
||||
self._run_chroot(rootfs, [pm, "-Syu", "--noconfirm", *packages])
|
||||
|
||||
def configure_base(self, rootfs: Path, config: dict) -> None:
|
||||
hostname = config.get("hostname", "euri")
|
||||
@@ -73,7 +70,8 @@ class Arch(Distro):
|
||||
|
||||
def install_bootloader(self, rootfs: Path, config: dict) -> None:
|
||||
init = config.get("init", "dinit")
|
||||
self._run_chroot(rootfs, ["pacman", "-S", "--noconfirm", "grub", "efibootmgr", "os-prober"])
|
||||
pm = self._tool("pacman")
|
||||
self._run_chroot(rootfs, [pm, "-S", "--noconfirm", "grub", "efibootmgr", "os-prober"])
|
||||
self._run_chroot(rootfs, ["grub-install", "--target=i386-pc", "/dev/sda"])
|
||||
self._run_chroot(rootfs, ["grub-install", "--target=x86_64-efi", "--efi-directory=/boot/efi", "--bootloader-id=grub"])
|
||||
self._run_chroot(rootfs, ["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])
|
||||
|
||||
@@ -2,16 +2,18 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import shutil
|
||||
import subprocess
|
||||
from abc import ABC, abstractmethod
|
||||
from pathlib import Path
|
||||
|
||||
_BUNDLED = Path(__file__).resolve().parent.parent / "bin"
|
||||
|
||||
|
||||
class Distro(ABC):
|
||||
"""Base class every distro backend must implement."""
|
||||
|
||||
name: str
|
||||
# host packages needed to bootstrap (e.g. debootstrap, pacstrap)
|
||||
host_deps: list[str]
|
||||
|
||||
@abstractmethod
|
||||
@@ -30,6 +32,20 @@ class Distro(ABC):
|
||||
def install_bootloader(self, rootfs: Path, config: dict) -> None:
|
||||
"""Install and configure the bootloader inside the rootfs."""
|
||||
|
||||
@staticmethod
|
||||
def _tool(name: str) -> str:
|
||||
bundled = _BUNDLED / name
|
||||
if bundled.is_file():
|
||||
return str(bundled)
|
||||
if bundled.is_dir():
|
||||
script = bundled / name
|
||||
if script.is_file():
|
||||
return str(script)
|
||||
path = shutil.which(name)
|
||||
if path:
|
||||
return path
|
||||
return name
|
||||
|
||||
@staticmethod
|
||||
def _run(cmd: list[str], **kw) -> subprocess.CompletedProcess:
|
||||
print(f" \033[90m$\033[0m \033[1m{' '.join(cmd)}\033[0m")
|
||||
|
||||
@@ -7,7 +7,7 @@ from .base import Distro
|
||||
|
||||
class Debian(Distro):
|
||||
name = "debian"
|
||||
host_deps = ["debootstrap", "squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
host_deps = ["squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
|
||||
SUITES = {
|
||||
"debian": "bookworm",
|
||||
@@ -23,12 +23,20 @@ class Debian(Distro):
|
||||
self.family = family
|
||||
|
||||
def bootstrap(self, rootfs: Path, config: dict) -> None:
|
||||
import os
|
||||
|
||||
suite = config.get("suite", self.SUITES.get(self.family, "bookworm"))
|
||||
mirror = config.get("mirror", self.MIRRORS.get(self.family))
|
||||
variant = config.get("variant", "minbase")
|
||||
debootstrap = self._tool("debootstrap")
|
||||
|
||||
env = {**os.environ}
|
||||
debootstrap_dir = Path(debootstrap).parent
|
||||
if (debootstrap_dir / "scripts").is_dir():
|
||||
env["DEBOOTSTRAP_DIR"] = str(debootstrap_dir)
|
||||
|
||||
cmd = [
|
||||
"debootstrap",
|
||||
debootstrap,
|
||||
"--variant", variant,
|
||||
"--include", ",".join(config.get("base_packages", ["base-files", "apt"])),
|
||||
"--arch", config.get("arch", "amd64"),
|
||||
@@ -36,7 +44,7 @@ class Debian(Distro):
|
||||
str(rootfs),
|
||||
mirror,
|
||||
]
|
||||
self._run(cmd)
|
||||
self._run(cmd, env=env)
|
||||
|
||||
def install_packages(self, rootfs: Path, packages: list[str]) -> None:
|
||||
if not packages:
|
||||
|
||||
@@ -7,7 +7,7 @@ from .base import Distro
|
||||
|
||||
class Fedora(Distro):
|
||||
name = "fedora"
|
||||
host_deps = ["dnf", "squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
host_deps = ["squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
|
||||
GROUPS = {
|
||||
"fedora": "@core",
|
||||
@@ -23,7 +23,7 @@ class Fedora(Distro):
|
||||
group = self.GROUPS.get(self.family, "@core")
|
||||
|
||||
cmd = [
|
||||
"dnf",
|
||||
self._tool("dnf5"),
|
||||
"--installroot", str(rootfs),
|
||||
"-y",
|
||||
f"--releasever={release}",
|
||||
@@ -38,7 +38,7 @@ class Fedora(Distro):
|
||||
def install_packages(self, rootfs: Path, packages: list[str]) -> None:
|
||||
if not packages:
|
||||
return
|
||||
self._run_chroot(rootfs, ["dnf", "-y", "install", *packages])
|
||||
self._run_chroot(rootfs, [self._tool("dnf5"), "-y", "install", *packages])
|
||||
|
||||
def configure_base(self, rootfs: Path, config: dict) -> None:
|
||||
hostname = config.get("hostname", "euri")
|
||||
|
||||
@@ -8,7 +8,7 @@ from ..dinit import install_all
|
||||
|
||||
class Void(Distro):
|
||||
name = "void"
|
||||
host_deps = ["xbps-install", "squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
host_deps = ["squashfs-tools", "xorriso", "mtools", "dosfstools"]
|
||||
|
||||
REPOS = {
|
||||
"glibc": "https://repo-default.voidlinux.org/current",
|
||||
@@ -26,7 +26,7 @@ class Void(Distro):
|
||||
base_pkgs.append("dinit")
|
||||
|
||||
cmd = [
|
||||
"xbps-install",
|
||||
self._tool("xbps-install"),
|
||||
"-S",
|
||||
"-r", str(rootfs),
|
||||
"-R", repo,
|
||||
@@ -37,12 +37,12 @@ class Void(Distro):
|
||||
|
||||
# remove runit if we're using dinit
|
||||
if init == "dinit":
|
||||
self._run_chroot(rootfs, ["xbps-remove", "-y", "runit"])
|
||||
self._run_chroot(rootfs, [self._tool("xbps-remove"), "-y", "runit"])
|
||||
|
||||
def install_packages(self, rootfs: Path, packages: list[str]) -> None:
|
||||
if not packages:
|
||||
return
|
||||
self._run_chroot(rootfs, ["xbps-install", "-Sy", *packages])
|
||||
self._run_chroot(rootfs, [self._tool("xbps-install"), "-Sy", *packages])
|
||||
|
||||
def configure_base(self, rootfs: Path, config: dict) -> None:
|
||||
hostname = config.get("hostname", "euri")
|
||||
@@ -78,7 +78,7 @@ class Void(Distro):
|
||||
def install_bootloader(self, rootfs: Path, config: dict) -> None:
|
||||
libc = config.get("libc", "musl")
|
||||
pkgs = ["grub", "grub-x86_64-efi", "efibootmgr"]
|
||||
self._run_chroot(rootfs, ["xbps-install", "-Sy", *pkgs])
|
||||
self._run_chroot(rootfs, [self._tool("xbps-install"), "-Sy", *pkgs])
|
||||
self._run_chroot(rootfs, ["grub-install", "--target=i386-pc", "/dev/sda"])
|
||||
self._run_chroot(rootfs, ["grub-install", "--target=x86_64-efi", "--efi-directory=/boot/efi", "--bootloader-id=Void"])
|
||||
self._run_chroot(rootfs, ["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])
|
||||
|
||||
Reference in New Issue
Block a user