diff --git a/euri_mklive/rootfs.py b/euri_mklive/rootfs.py index a85f06f..ed459b4 100644 --- a/euri_mklive/rootfs.py +++ b/euri_mklive/rootfs.py @@ -14,15 +14,18 @@ def build(config: dict, output: Path) -> Path: """Build a rootfs and return its path.""" set_mode(config.get("_mode", "root")) distro_name = config["distro"] - distro_cls = get_distro(distro_name) + + # 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 distro_name in ("artix",): + if backend_name in ("artix",): distro = distro_cls(family="artix") - elif distro_name in ("debian", "ubuntu"): - distro = distro_cls(family=distro_name) - elif distro_name in ("fedora", "rocky", "almalinux"): - distro = distro_cls(family=distro_name) + 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() @@ -45,6 +48,34 @@ def build(config: dict, output: Path) -> Path: 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) diff --git a/euri_mklive/tui.py b/euri_mklive/tui.py index dfd1906..fe2fb72 100644 --- a/euri_mklive/tui.py +++ b/euri_mklive/tui.py @@ -20,6 +20,7 @@ from .distros import REGISTRY console = Console() DISTRO_INFO = { + "horizon": {"desc": "Euri Linux Horizon — void+dinit+musl, Euri branding", "libc": ["musl"], "inits": ["dinit"]}, "void": {"desc": "Void Linux — musl/glibc, runit/dinit, independent", "libc": ["musl", "glibc"], "inits": ["dinit", "runit"]}, "debian": {"desc": "Debian — stable, apt, systemd", "libc": ["glibc"], "inits": ["systemd"]}, "ubuntu": {"desc": "Ubuntu — Debian-based, apt, systemd", "libc": ["glibc"], "inits": ["systemd"]}, @@ -199,8 +200,8 @@ def select_setup_mode() -> str: """Pick recommended or custom mode.""" console.print(Panel( "[bold]How would you like to configure your ISO?[/]\n\n" - " [cyan]Recommended[/] — pick a desktop, we handle the rest\n" - " (void + dinit + musl, base packages included)\n\n" + " [cyan]Recommended[/] — Euri Linux Horizon preset\n" + " (void + dinit + musl, pick your desktop)\n\n" " [white]Custom[/] — choose every detail yourself\n" " (any distro, init, libc, packages, etc.)", border_style="cyan", @@ -210,7 +211,7 @@ def select_setup_mode() -> str: choice = questionary.select( "Setup mode:", choices=[ - "Recommended — easy setup, just pick your desktop", + "Recommended — Euri Linux Horizon", "Custom — full control over everything", ], ).ask() @@ -221,24 +222,29 @@ def select_setup_mode() -> str: def run_recommended() -> dict: - """Simplified flow — pick DE/WM, we handle the rest.""" + """Euri Linux Horizon preset — void + dinit + musl, full branding.""" banner() mode = select_mode() - # auto-pick distro/init/libc/arch - distro = "void" + distro = "horizon" init = "dinit" libc = "musl" arch = "x86_64" - console.print("[bold]Recommended setup[/]\n") - console.print(f" Distro: [cyan]void[/] (independent, fast, musl)") - console.print(f" Init: [cyan]dinit[/] (modern service manager)") - console.print(f" Libc: [cyan]musl[/] (small, secure)") - console.print(f" Arch: [cyan]x86_64[/]") + + console.print(Panel( + "[bold cyan]Euri Linux Horizon[/]\n\n" + " Distro: [cyan]void[/] (independent, fast, musl)\n" + " Init: [cyan]dinit[/] (modern service manager)\n" + " Libc: [cyan]musl[/] (small, secure)\n" + " Arch: [cyan]x86_64[/]\n\n" + " [dim]Pick your desktop environment or window manager.[/]", + border_style="cyan", + padding=(0, 1), + )) console.print() # DE/WM selection with explanations - de_name, de_pkgs = select_de_wm(distro, explain=True) + de_name, de_pkgs = select_de_wm("void", explain=True) # auto-pick package groups auto_groups = ["Base", "Networking", "Audio", "Firmware"] @@ -268,6 +274,7 @@ def run_recommended() -> dict: seen.add(p) merged.append(p) + iso_version = "1.0" cfg = { "distro": distro, "arch": arch, @@ -280,8 +287,8 @@ def run_recommended() -> dict: "users": [], "iso": { "name": "Euri Linux Horizon", - "version": "1.0", - "label": "HORIZON", + "version": iso_version, + "label": f"HORIZON_{iso_version}", }, "_mode": mode, } @@ -506,18 +513,18 @@ def select_packages() -> list[str]: def configure_iso() -> dict: """Configure ISO metadata.""" console.print("[bold]ISO metadata[/]\n") - console.print(" [dim]These identify your ISO image. Defaults are fine for testing.[/]\n") + console.print(" [dim]These identify your ISO image. Leave empty to skip.[/]\n") - name = questionary.text("ISO name:", default="Euri Linux Horizon").ask() + name = questionary.text("ISO name:", default="").ask() if name is None: sys.exit(0) version = questionary.text("Version:", default="1.0").ask() if version is None: sys.exit(0) - hostname = questionary.text("Hostname:", default="euri").ask() + hostname = questionary.text("Hostname:", default="live").ask() if hostname is None: sys.exit(0) - label = questionary.text("ISO label:", default="HORIZON").ask() + label = questionary.text("ISO label:", default="").ask() if label is None: sys.exit(0) diff --git a/pyproject.toml b/pyproject.toml index f192a2d..abde928 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "euri-mklive" -version = "0.3.0" +version = "0.4.0" description = "Universal CLI ISO builder — any distro, from any distro" requires-python = ">=3.10" dependencies = ["pyyaml>=6", "click>=8", "rich>=13", "questionary>=2"]