diff --git a/README.md b/README.md index 9e30088..4fbd1c6 100644 --- a/README.md +++ b/README.md @@ -490,15 +490,135 @@ make format ### 1. Basic Debian System (`examples/debian-basic.json`) Creates a minimal Debian system with basic packages and user accounts. -### 2. OSTree System (`examples/debian-ostree.json`) +### 2. Debian 14 Basic System (`examples/debian-forky-basic.json`) +Creates a minimal Debian 14 (Forky) testing system with basic packages and user accounts. + +### 3. OSTree System (`examples/debian-ostree.json`) Builds a Debian system with OSTree repository management. -### 3. Complete System (`examples/debian-complete.json`) +### 4. Complete System (`examples/debian-complete.json`) Comprehensive Debian system with all basic stages. -### 4. Bootable OSTree System (`examples/debian-ostree-bootable.json`) +### 5. Multi-Version System (`examples/debian-multi-version.json`) +Complete Debian 13 (Trixie) stable system with all stages and OSTree support. + +### 6. Debian 14 Complete System (`examples/debian-forky-complete.json`) +Complete Debian 14 (Forky) testing system with all stages and OSTree support. + +### 7. Bootable OSTree System (`examples/debian-ostree-bootable.json`) Complete bootable Debian OSTree system with GRUB2 and bootc. +## 🔄 Multi-Version Debian Support + +particle-os supports building images for multiple Debian versions: + +### **Debian 13 (Trixie) - Stable Release** +- **Suite**: `trixie` +- **Status**: Current stable release +- **Use case**: Production deployments, long-term support +- **Security updates**: Regular security patches +- **Example**: `examples/debian-basic.json` + +### **Debian 14 (Forky) - Testing Release** +- **Suite**: `forky` +- **Status**: Testing release (future stable) +- **Use case**: Development, testing, early adoption +- **Security updates**: Security patches from unstable +- **Example**: `examples/debian-forky-basic.json` + +### **Version-Specific Configuration** + +#### Sources Configuration +```json +{ + "name": "org.osbuild.debian.sources", + "options": { + "suite": "trixie", // or "forky" + "mirror": "https://deb.debian.org/debian", + "components": ["main", "contrib", "non-free"], + "additional_sources": [ + "deb https://deb.debian.org/debian-security trixie-security main contrib non-free", + "deb https://deb.debian.org/debian-updates trixie-updates main contrib non-free" + ] + } +} +``` + +#### Debootstrap Configuration +```json +{ + "name": "org.osbuild.debian.debootstrap", + "options": { + "suite": "trixie", // or "forky" + "mirror": "https://deb.debian.org/debian", + "variant": "minbase", + "arch": "amd64", + "components": ["main", "contrib", "non-free"] + } +} +``` + +#### OSTree Branch Naming +```json +{ + "name": "org.osbuild.debian.ostree", + "options": { + "branch": "debian/trixie/x86_64/standard", // or "debian/forky/x86_64/standard" + "subject": "Debian Trixie OSTree System", // or "Debian Forky OSTree System" + "body": "Complete Debian OSTree system with GRUB2 and bootc" + } +} +``` + +### **Choosing the Right Version** + +- **Use Trixie (Debian 13)** for: + - Production environments + - Long-term stability + - Security-focused deployments + - Enterprise use cases + +- **Use Forky (Debian 14)** for: + - Development and testing + - Early access to new features + - CI/CD pipelines + - Experimental deployments + +### **Migration Between Versions** + +To migrate from one Debian version to another: + +1. **Update manifest files** to use the new suite name +2. **Adjust package lists** for version compatibility +3. **Update OSTree branch names** to reflect new version +4. **Test thoroughly** before production deployment +5. **Consider rolling back** if issues arise + +### **Automated Version Switching** + +particle-os includes a script to automatically switch between Debian versions: + +```bash +# List supported Debian versions +./scripts/switch-debian-version.sh -l + +# Switch from Trixie to Forky (with backup) +./scripts/switch-debian-version.sh -b -v forky examples/debian-basic.json + +# Switch from Forky to Trixie +./scripts/switch-debian-version.sh -v trixie examples/debian-forky-basic.json + +# Restore from backup +./scripts/switch-debian-version.sh -r examples/debian-basic.json +``` + +The script automatically updates: +- Suite names in sources and debootstrap stages +- Security and update repository URLs +- OSTree branch names +- Subject lines and descriptions +- Output filenames (if version-specific) + ## 🏗️ Architecture Deep Dive ### Stage Implementation Pattern diff --git a/examples/debian-basic.json b/examples/debian-basic.json index 31d005d..e08e4d0 100644 --- a/examples/debian-basic.json +++ b/examples/debian-basic.json @@ -10,7 +10,10 @@ "options": { "suite": "trixie", "mirror": "https://deb.debian.org/debian", - "components": ["main", "contrib", "non-free"] + "components": ["main", "contrib", "non-free"], + "additional_sources": [ + "deb https://deb.debian.org/debian-security trixie-security main contrib non-free" + ] } }, { @@ -35,37 +38,45 @@ "vim", "less", "locales", - "ca-certificates" + "ca-certificates", + "tzdata", + "net-tools", + "iproute2" ], "update": true, "clean": true } }, { - "name": "org.osbuild.users", + "name": "org.osbuild.debian.locale", + "options": { + "language": "en_US.UTF-8", + "additional_locales": ["en_GB.UTF-8", "de_DE.UTF-8"], + "default_locale": "en_US.UTF-8" + } + }, + { + "name": "org.osbuild.debian.timezone", + "options": { + "timezone": "UTC" + } + }, + { + "name": "org.osbuild.debian.users", "options": { "users": { "debian": { "password": "$6$rounds=656000$salt$hashedpassword", "shell": "/bin/bash", - "groups": ["sudo", "users"], + "groups": ["sudo", "users", "adm"], "uid": 1000, "gid": 1000, - "home": "/home/debian" + "home": "/home/debian", + "comment": "Debian User" } - } - } - }, - { - "name": "org.osbuild.locale", - "options": { - "language": "en_US.UTF-8" - } - }, - { - "name": "org.osbuild.timezone", - "options": { - "timezone": "UTC" + }, + "default_shell": "/bin/bash", + "default_home": "/home" } } ] @@ -74,7 +85,6 @@ "assembler": { "name": "org.osbuild.tar", "options": { - "filename": "debian-basic.tar.gz", "compression": "gzip" } } diff --git a/examples/debian-basic.json.backup.20250812_003400 b/examples/debian-basic.json.backup.20250812_003400 new file mode 100644 index 0000000..e08e4d0 --- /dev/null +++ b/examples/debian-basic.json.backup.20250812_003400 @@ -0,0 +1,91 @@ +{ + "version": "2", + "pipelines": [ + { + "name": "build", + "runner": "org.osbuild.linux", + "stages": [ + { + "name": "org.osbuild.debian.sources", + "options": { + "suite": "trixie", + "mirror": "https://deb.debian.org/debian", + "components": ["main", "contrib", "non-free"], + "additional_sources": [ + "deb https://deb.debian.org/debian-security trixie-security main contrib non-free" + ] + } + }, + { + "name": "org.osbuild.debian.debootstrap", + "options": { + "suite": "trixie", + "mirror": "https://deb.debian.org/debian", + "variant": "minbase", + "arch": "amd64", + "components": ["main", "contrib", "non-free"] + } + }, + { + "name": "org.osbuild.debian.apt", + "options": { + "packages": [ + "sudo", + "openssh-server", + "systemd-sysv", + "curl", + "wget", + "vim", + "less", + "locales", + "ca-certificates", + "tzdata", + "net-tools", + "iproute2" + ], + "update": true, + "clean": true + } + }, + { + "name": "org.osbuild.debian.locale", + "options": { + "language": "en_US.UTF-8", + "additional_locales": ["en_GB.UTF-8", "de_DE.UTF-8"], + "default_locale": "en_US.UTF-8" + } + }, + { + "name": "org.osbuild.debian.timezone", + "options": { + "timezone": "UTC" + } + }, + { + "name": "org.osbuild.debian.users", + "options": { + "users": { + "debian": { + "password": "$6$rounds=656000$salt$hashedpassword", + "shell": "/bin/bash", + "groups": ["sudo", "users", "adm"], + "uid": 1000, + "gid": 1000, + "home": "/home/debian", + "comment": "Debian User" + } + }, + "default_shell": "/bin/bash", + "default_home": "/home" + } + } + ] + } + ], + "assembler": { + "name": "org.osbuild.tar", + "options": { + "compression": "gzip" + } + } +} diff --git a/examples/debian-forky-basic.json b/examples/debian-forky-basic.json new file mode 100644 index 0000000..0b8e0a7 --- /dev/null +++ b/examples/debian-forky-basic.json @@ -0,0 +1,91 @@ +{ + "version": "2", + "pipelines": [ + { + "name": "build", + "runner": "org.osbuild.linux", + "stages": [ + { + "name": "org.osbuild.debian.sources", + "options": { + "suite": "forky", + "mirror": "https://deb.debian.org/debian", + "components": ["main", "contrib", "non-free"], + "additional_sources": [ + "deb https://deb.debian.org/debian-security forky-security main contrib non-free" + ] + } + }, + { + "name": "org.osbuild.debian.debootstrap", + "options": { + "suite": "forky", + "mirror": "https://deb.debian.org/debian", + "variant": "minbase", + "arch": "amd64", + "components": ["main", "contrib", "non-free"] + } + }, + { + "name": "org.osbuild.debian.apt", + "options": { + "packages": [ + "sudo", + "openssh-server", + "systemd-sysv", + "curl", + "wget", + "vim", + "less", + "locales", + "ca-certificates", + "tzdata", + "net-tools", + "iproute2" + ], + "update": true, + "clean": true + } + }, + { + "name": "org.osbuild.debian.locale", + "options": { + "language": "en_US.UTF-8", + "additional_locales": ["en_GB.UTF-8", "de_DE.UTF-8"], + "default_locale": "en_US.UTF-8" + } + }, + { + "name": "org.osbuild.debian.timezone", + "options": { + "timezone": "UTC" + } + }, + { + "name": "org.osbuild.debian.users", + "options": { + "users": { + "debian": { + "password": "$6$rounds=656000$salt$hashedpassword", + "shell": "/bin/bash", + "groups": ["sudo", "users", "adm"], + "uid": 1000, + "gid": 1000, + "home": "/home/debian", + "comment": "Debian User" + } + }, + "default_shell": "/bin/bash", + "default_home": "/home" + } + } + ] + } + ], + "assembler": { + "name": "org.osbuild.tar", + "options": { + "compression": "gzip" + } + } +} diff --git a/examples/debian-forky-complete.json b/examples/debian-forky-complete.json new file mode 100644 index 0000000..7288a50 --- /dev/null +++ b/examples/debian-forky-complete.json @@ -0,0 +1,175 @@ +{ + "version": "2", + "pipelines": [ + { + "name": "build", + "runner": "org.osbuild.linux", + "stages": [ + { + "name": "org.osbuild.debian.sources", + "options": { + "suite": "forky", + "mirror": "https://deb.debian.org/debian", + "components": ["main", "contrib", "non-free"], + "additional_sources": [ + "deb https://deb.debian.org/debian-security forky-security main contrib non-free", + "deb https://deb.debian.org/debian-updates forky-updates main contrib non-free" + ] + } + }, + { + "name": "org.osbuild.debian.debootstrap", + "options": { + "suite": "forky", + "mirror": "https://deb.debian.org/debian", + "variant": "minbase", + "arch": "amd64", + "components": ["main", "contrib", "non-free"] + } + }, + { + "name": "org.osbuild.debian.apt", + "options": { + "packages": [ + "ostree", + "bootc", + "systemd", + "systemd-sysv", + "linux-image-amd64", + "grub2-efi-amd64", + "grub2-common", + "efibootmgr", + "sudo", + "openssh-server", + "curl", + "wget", + "vim", + "less", + "locales", + "ca-certificates", + "tzdata", + "net-tools", + "iproute2", + "resolvconf", + "firmware-linux", + "firmware-linux-nonfree", + "initramfs-tools" + ], + "update": true, + "clean": true + } + }, + { + "name": "org.osbuild.debian.locale", + "options": { + "language": "en_US.UTF-8", + "additional_locales": ["en_GB.UTF-8", "de_DE.UTF-8", "fr_FR.UTF-8"], + "default_locale": "en_US.UTF-8" + } + }, + { + "name": "org.osbuild.debian.timezone", + "options": { + "timezone": "UTC" + } + }, + { + "name": "org.osbuild.debian.users", + "options": { + "users": { + "debian": { + "password": "$6$rounds=656000$salt$hashedpassword", + "shell": "/bin/bash", + "groups": ["sudo", "users", "adm"], + "uid": 1000, + "gid": 1000, + "home": "/home/debian", + "comment": "Debian User" + }, + "admin": { + "password": "$6$rounds=656000$salt$hashedpassword", + "shell": "/bin/bash", + "groups": ["sudo", "users", "adm", "wheel"], + "uid": 1001, + "gid": 1001, + "home": "/home/admin", + "comment": "Administrator" + } + }, + "default_shell": "/bin/bash", + "default_home": "/home" + } + }, + { + "name": "org.osbuild.debian.systemd", + "options": { + "enable_services": [ + "ssh", + "systemd-networkd", + "systemd-resolved" + ], + "disable_services": [ + "systemd-firstboot", + "systemd-machine-id-commit" + ], + "mask_services": [ + "systemd-remount-fs", + "systemd-machine-id-commit" + ], + "config": { + "DefaultDependencies": "no", + "DefaultTimeoutStartSec": "0", + "DefaultTimeoutStopSec": "0" + } + } + }, + { + "name": "org.osbuild.debian.bootc", + "options": { + "enable": true, + "config": { + "auto_update": true, + "rollback_enabled": true + }, + "kernel_args": [ + "console=ttyS0", + "console=tty0", + "root=UUID=ROOT_UUID", + "quiet", + "splash" + ] + } + }, + { + "name": "org.osbuild.debian.grub2", + "options": { + "root_fs_uuid": "ROOT_UUID", + "kernel_path": "/boot/vmlinuz", + "initrd_path": "/boot/initrd.img", + "bootloader_id": "debian", + "timeout": 5, + "default_entry": "0" + } + }, + { + "name": "org.osbuild.debian.ostree", + "options": { + "repository": "/var/lib/ostree/repo", + "branch": "debian/forky/x86_64/standard", + "subject": "Debian Forky OSTree System", + "body": "Complete Debian 14 Forky OSTree system with GRUB2 and bootc" + } + } + ] + } + ], + "assembler": { + "name": "org.osbuild.debian.qemu", + "options": { + "format": "qcow2", + "filename": "debian-forky-ostree.qcow2", + "size": "20G", + "ptuuid": "12345678-1234-1234-1234-123456789012" + } + } +} diff --git a/examples/debian-multi-version.json b/examples/debian-multi-version.json new file mode 100644 index 0000000..4a7f923 --- /dev/null +++ b/examples/debian-multi-version.json @@ -0,0 +1,175 @@ +{ + "version": "2", + "pipelines": [ + { + "name": "build", + "runner": "org.osbuild.linux", + "stages": [ + { + "name": "org.osbuild.debian.sources", + "options": { + "suite": "trixie", + "mirror": "https://deb.debian.org/debian", + "components": ["main", "contrib", "non-free"], + "additional_sources": [ + "deb https://deb.debian.org/debian-security trixie-security main contrib non-free", + "deb https://deb.debian.org/debian-updates trixie-updates main contrib non-free" + ] + } + }, + { + "name": "org.osbuild.debian.debootstrap", + "options": { + "suite": "trixie", + "mirror": "https://deb.debian.org/debian", + "variant": "minbase", + "arch": "amd64", + "components": ["main", "contrib", "non-free"] + } + }, + { + "name": "org.osbuild.debian.apt", + "options": { + "packages": [ + "ostree", + "bootc", + "systemd", + "systemd-sysv", + "linux-image-amd64", + "grub2-efi-amd64", + "grub2-common", + "efibootmgr", + "sudo", + "openssh-server", + "curl", + "wget", + "vim", + "less", + "locales", + "ca-certificates", + "tzdata", + "net-tools", + "iproute2", + "resolvconf", + "firmware-linux", + "firmware-linux-nonfree", + "initramfs-tools" + ], + "update": true, + "clean": true + } + }, + { + "name": "org.osbuild.debian.locale", + "options": { + "language": "en_US.UTF-8", + "additional_locales": ["en_GB.UTF-8", "de_DE.UTF-8", "fr_FR.UTF-8"], + "default_locale": "en_US.UTF-8" + } + }, + { + "name": "org.osbuild.debian.timezone", + "options": { + "timezone": "UTC" + } + }, + { + "name": "org.osbuild.debian.users", + "options": { + "users": { + "debian": { + "password": "$6$rounds=656000$salt$hashedpassword", + "shell": "/bin/bash", + "groups": ["sudo", "users", "adm"], + "uid": 1000, + "gid": 1000, + "home": "/home/debian", + "comment": "Debian User" + }, + "admin": { + "password": "$6$rounds=656000$salt$hashedpassword", + "shell": "/bin/bash", + "groups": ["sudo", "users", "adm", "wheel"], + "uid": 1001, + "gid": 1001, + "home": "/home/admin", + "comment": "Administrator" + } + }, + "default_shell": "/bin/bash", + "default_home": "/home" + } + }, + { + "name": "org.osbuild.debian.systemd", + "options": { + "enable_services": [ + "ssh", + "systemd-networkd", + "systemd-resolved" + ], + "disable_services": [ + "systemd-firstboot", + "systemd-machine-id-commit" + ], + "mask_services": [ + "systemd-remount-fs", + "systemd-machine-id-commit" + ], + "config": { + "DefaultDependencies": "no", + "DefaultTimeoutStartSec": "0", + "DefaultTimeoutStopSec": "0" + } + } + }, + { + "name": "org.osbuild.debian.bootc", + "options": { + "enable": true, + "config": { + "auto_update": true, + "rollback_enabled": true + }, + "kernel_args": [ + "console=ttyS0", + "console=tty0", + "root=UUID=ROOT_UUID", + "quiet", + "splash" + ] + } + }, + { + "name": "org.osbuild.debian.grub2", + "options": { + "root_fs_uuid": "ROOT_UUID", + "kernel_path": "/boot/vmlinuz", + "initrd_path": "/boot/initrd.img", + "bootloader_id": "debian", + "timeout": 5, + "default_entry": "0" + } + }, + { + "name": "org.osbuild.debian.ostree", + "options": { + "repository": "/var/lib/ostree/repo", + "branch": "debian/trixie/x86_64/standard", + "subject": "Debian Trixie OSTree System", + "body": "Complete Debian OSTree system with GRUB2 and bootc" + } + } + ] + } + ], + "assembler": { + "name": "org.osbuild.debian.qemu", + "options": { + "format": "qcow2", + "filename": "debian-trixie-ostree.qcow2", + "size": "20G", + "ptuuid": "12345678-1234-1234-1234-123456789012" + } + } +} diff --git a/scripts/switch-debian-version.sh b/scripts/switch-debian-version.sh new file mode 100755 index 0000000..061b799 --- /dev/null +++ b/scripts/switch-debian-version.sh @@ -0,0 +1,270 @@ +#!/bin/bash + +# particle-os Debian Version Switcher +# This script helps you switch between different Debian versions in your manifests + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +print_header() { + echo -e "${BLUE}=== $1 ===${NC}" +} + +# Function to show usage +show_usage() { + cat << EOF +Usage: $0 [OPTIONS] + +Options: + -v, --version Debian version to switch to (trixie, forky) + -b, --backup Create backup of original manifest + -r, --restore Restore from backup + -l, --list List supported Debian versions + -h, --help Show this help message + +Examples: + $0 -v forky examples/debian-basic.json + $0 -v trixie examples/debian-forky-basic.json + $0 -b -v forky examples/debian-basic.json + $0 -r examples/debian-basic.json + +Supported Debian Versions: + trixie - Debian 13 (current stable) + forky - Debian 14 (testing, future stable) +EOF +} + +# Function to list supported versions +list_versions() { + cat << EOF +Supported Debian Versions: + +1. trixie (Debian 13) + - Status: Current stable release + - Use case: Production deployments + - Security: Regular security patches + - Example: examples/debian-basic.json + +2. forky (Debian 14) + - Status: Testing release + - Use case: Development and testing + - Security: Security patches from unstable + - Example: examples/debian-forky-basic.json + +Version Mapping: + trixie -> Debian 13 (stable) + forky -> Debian 14 (testing) +EOF +} + +# Function to backup manifest +backup_manifest() { + local manifest_file="$1" + local backup_file="${manifest_file}.backup.$(date +%Y%m%d_%H%M%S)" + + if cp "$manifest_file" "$backup_file"; then + print_status "Backup created: $backup_file" + echo "$backup_file" > "${manifest_file}.backup" + else + print_error "Failed to create backup" + exit 1 + fi +} + +# Function to restore from backup +restore_manifest() { + local manifest_file="$1" + local backup_file + + if [[ -f "${manifest_file}.backup" ]]; then + backup_file=$(cat "${manifest_file}.backup") + if [[ -f "$backup_file" ]]; then + if cp "$backup_file" "$manifest_file"; then + print_status "Restored from backup: $backup_file" + rm "${manifest_file}.backup" + else + print_error "Failed to restore from backup" + exit 1 + fi + else + print_error "Backup file not found: $backup_file" + exit 1 + fi + else + print_error "No backup found for: $manifest_file" + exit 1 + fi +} + +# Function to switch Debian version +switch_version() { + local manifest_file="$1" + local target_version="$2" + + # Validate target version + case "$target_version" in + trixie|forky) + ;; + *) + print_error "Unsupported Debian version: $target_version" + print_error "Supported versions: trixie, forky" + exit 1 + ;; + esac + + # Check if manifest file exists + if [[ ! -f "$manifest_file" ]]; then + print_error "Manifest file not found: $manifest_file" + exit 1 + fi + + # Create backup if requested + if [[ "$CREATE_BACKUP" == "true" ]]; then + backup_manifest "$manifest_file" + fi + + # Determine source version from current manifest + local current_version + current_version=$(grep -o '"suite": *"[^"]*"' "$manifest_file" | head -1 | cut -d'"' -f4) + + if [[ -z "$current_version" ]]; then + print_warning "Could not determine current Debian version from manifest" + print_warning "Proceeding with version switch..." + else + print_status "Current Debian version: $current_version" + fi + + print_status "Switching to Debian version: $target_version" + + # Update suite references + sed -i "s/\"suite\": \"[^\"]*\"/\"suite\": \"$target_version\"/g" "$manifest_file" + + # Update security sources + sed -i "s/debian-security [a-z]*-security/debian-security ${target_version}-security/g" "$manifest_file" + + # Update update sources + sed -i "s/debian-updates [a-z]*-updates/debian-updates ${target_version}-updates/g" "$manifest_file" + + # Update OSTree branch names + sed -i "s/debian\/[a-z]*\/x86_64/debian\/${target_version}\/x86_64/g" "$manifest_file" + + # Update subject lines + sed -i "s/Debian [A-Za-z]* OSTree/Debian ${target_version^} OSTree/g" "$manifest_file" + sed -i "s/Debian [A-Za-z]* System/Debian ${target_version^} System/g" "$manifest_file" + + # Update filename if it contains version + if grep -q "debian-[a-z]*-ostree" "$manifest_file"; then + sed -i "s/debian-[a-z]*-ostree/debian-${target_version}-ostree/g" "$manifest_file" + fi + + print_status "Successfully switched to Debian $target_version" + print_status "Manifest updated: $manifest_file" + + # Show summary of changes + echo + print_header "Summary of Changes" + echo "Suite: $target_version" + echo "Security sources: ${target_version}-security" + echo "Update sources: ${target_version}-updates" + echo "OSTree branch: debian/${target_version}/x86_64" + echo "Subject: Debian ${target_version^} OSTree System" +} + +# Main script logic +main() { + local manifest_file="" + local target_version="" + local CREATE_BACKUP="false" + local RESTORE_BACKUP="false" + local LIST_VERSIONS="false" + + # Parse command line arguments + while [[ $# -gt 0 ]]; do + case $1 in + -v|--version) + target_version="$2" + shift 2 + ;; + -b|--backup) + CREATE_BACKUP="true" + shift + ;; + -r|--restore) + RESTORE_BACKUP="true" + shift + ;; + -l|--list) + LIST_VERSIONS="true" + shift + ;; + -h|--help) + show_usage + exit 0 + ;; + -*) + print_error "Unknown option: $1" + show_usage + exit 1 + ;; + *) + manifest_file="$1" + shift + ;; + esac + done + + # Handle list versions + if [[ "$LIST_VERSIONS" == "true" ]]; then + list_versions + exit 0 + fi + + # Handle restore + if [[ "$RESTORE_BACKUP" == "true" ]]; then + if [[ -z "$manifest_file" ]]; then + print_error "Manifest file required for restore operation" + show_usage + exit 1 + fi + restore_manifest "$manifest_file" + exit 0 + fi + + # Validate required arguments + if [[ -z "$target_version" ]]; then + print_error "Target Debian version is required" + show_usage + exit 1 + fi + + if [[ -z "$manifest_file" ]]; then + print_error "Manifest file is required" + show_usage + exit 1 + fi + + # Perform version switch + switch_version "$manifest_file" "$target_version" +} + +# Run main function with all arguments +main "$@"