From 3c4870b1048082fa0064ea935418f5694937b1f7 Mon Sep 17 00:00:00 2001 From: N0VA Date: Tue, 3 Feb 2026 16:20:59 +0100 Subject: [PATCH] Implement basic partitioning backend and CLI interface --- iridium_installer/backend/__init__.py | 0 iridium_installer/backend/disk.py | 76 +++++++++++++++++++++++++++ iridium_installer/main.py | 66 ++++++++++++++--------- 3 files changed, 118 insertions(+), 24 deletions(-) create mode 100644 iridium_installer/backend/__init__.py create mode 100644 iridium_installer/backend/disk.py diff --git a/iridium_installer/backend/__init__.py b/iridium_installer/backend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/iridium_installer/backend/disk.py b/iridium_installer/backend/disk.py new file mode 100644 index 0000000..2bec226 --- /dev/null +++ b/iridium_installer/backend/disk.py @@ -0,0 +1,76 @@ +import subprocess +import logging + +logger = logging.getLogger(__name__) + +def run_command(cmd, check=True): + logger.info(f"Running command: {' '.join(cmd)}") + try: + result = subprocess.run(cmd, check=check, capture_output=True, text=True) + return result + except subprocess.CalledProcessError as e: + logger.error(f"Command failed: {e.stderr}") + raise + +def get_partition_device(disk_device, partition_number): + """ + Returns the partition device path. + Handles NVMe style (p1) vs sd style (1). + """ + if disk_device[-1].isdigit(): + return f"{disk_device}p{partition_number}" + return f"{disk_device}{partition_number}" + +def auto_partition_disk(disk_device): + """ + Automatically partitions the disk with a standard layout: + 1. EFI System Partition (1GB) + 2. Swap (4GB) - simpler fixed size for now + 3. Root (Remaining) + """ + logger.info(f"Starting auto-partitioning on {disk_device}") + + # 1. Zap the disk (destroy all data) + run_command(["sgdisk", "-Z", disk_device]) + + # 2. Create new GPT table + run_command(["sgdisk", "-o", disk_device]) + + # 3. Create EFI Partition (Part 1, 1GB, Type EF00) + # -n :: + run_command(["sgdisk", "-n", "1:0:+1024M", "-t", "1:ef00", "-c", "1:EFI System", disk_device]) + + # 4. Create Swap Partition (Part 2, 4GB, Type 8200) + run_command(["sgdisk", "-n", "2:0:+4096M", "-t", "2:8200", "-c", "2:Swap", disk_device]) + + # 5. Create Root Partition (Part 3, Rest, Type 8300) + run_command(["sgdisk", "-n", "3:0:0", "-t", "3:8300", "-c", "3:Root", disk_device]) + + # Inform kernel of changes + run_command(["partprobe", disk_device]) + + # Wait a bit for nodes to appear? Usually partprobe handles it but sometimes there's a race. + import time + time.sleep(1) + + # 6. Format Partitions + efi_part = get_partition_device(disk_device, 1) + swap_part = get_partition_device(disk_device, 2) + root_part = get_partition_device(disk_device, 3) + + logger.info("Formatting EFI partition...") + run_command(["mkfs.vfat", "-F32", efi_part]) + + logger.info("Formatting Swap partition...") + run_command(["mkswap", swap_part]) + + logger.info("Formatting Root partition...") + run_command(["mkfs.ext4", "-F", root_part]) + + logger.info("Partitioning and formatting complete.") + + return { + "efi": efi_part, + "swap": swap_part, + "root": root_part + } diff --git a/iridium_installer/main.py b/iridium_installer/main.py index 62aa348..2704b42 100644 --- a/iridium_installer/main.py +++ b/iridium_installer/main.py @@ -1,30 +1,9 @@ import argparse import sys +import logging -import gi - -gi.require_version("Gtk", "4.0") -gi.require_version("Adw", "1") - -from gi.repository import Adw, Gio, Gtk - -from .ui.window import InstallerWindow - - -class IridiumInstallerApp(Adw.Application): - def __init__(self, mock_mode=False): - super().__init__( - application_id="org.iridium.Installer", - flags=Gio.ApplicationFlags.FLAGS_NONE, - ) - self.mock_mode = mock_mode - - def do_activate(self): - win = self.props.active_window - if not win: - win = InstallerWindow(application=self, mock_mode=self.mock_mode) - win.present() - +# Configure logging +logging.basicConfig(level=logging.INFO) def main(): parser = argparse.ArgumentParser(description="Iridium OS Installer") @@ -33,8 +12,47 @@ def main(): action="store_true", help="Run in mock mode (no actual changes to disk)", ) + parser.add_argument( + "--partition-disk", + help="Automatically partition the specified disk (WARNING: DESTROYS DATA)", + ) args = parser.parse_args() + if args.partition_disk: + from .backend.disk import auto_partition_disk + try: + print(f"Starting partitioning on {args.partition_disk}...") + result = auto_partition_disk(args.partition_disk) + print("Partitioning successful!") + print(f"EFI: {result['efi']}") + print(f"Swap: {result['swap']}") + print(f"Root: {result['root']}") + return 0 + except Exception as e: + print(f"Partitioning failed: {e}", file=sys.stderr) + return 1 + + import gi + gi.require_version("Gtk", "4.0") + gi.require_version("Adw", "1") + + from gi.repository import Adw, Gio + from .ui.window import InstallerWindow + + class IridiumInstallerApp(Adw.Application): + def __init__(self, mock_mode=False): + super().__init__( + application_id="org.iridium.Installer", + flags=Gio.ApplicationFlags.FLAGS_NONE, + ) + self.mock_mode = mock_mode + + def do_activate(self): + win = self.props.active_window + if not win: + win = InstallerWindow(application=self, mock_mode=self.mock_mode) + win.present() + app = IridiumInstallerApp(mock_mode=args.mock) return app.run(sys.argv)