refactor(codebase): cleanup formatting and fix bootloader handler import
- commit
- 28e451b1705d2afb2142cd83785f07ce185a0a37
- author
- brice · · 2026-01-24 03:30 UTC
- parent
- 6cba902
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
72 files · +497 -500
M cmd/archup-installer/main.go +1 -1
| @@ -5,7 +5,6 @@ import ( | |||
| 5 | 5 | "fmt" | |
| 6 | 6 | "os" | |
| 7 | 7 | ||
| 8 | - | tea "github.com/charmbracelet/bubbletea" | |
| 9 | 8 | apphandlers "github.com/bnema/archup/internal/application/handlers" | |
| 10 | 9 | "github.com/bnema/archup/internal/application/services" | |
| 11 | 10 | "github.com/bnema/archup/internal/cleanup" | |
| @@ -16,6 +15,7 @@ import ( | |||
| 16 | 15 | "github.com/bnema/archup/internal/infrastructure/persistence" | |
| 17 | 16 | "github.com/bnema/archup/internal/interfaces/tui" | |
| 18 | 17 | "github.com/bnema/archup/internal/logger" | |
| 18 | + | tea "github.com/charmbracelet/bubbletea" | |
| 19 | 19 | ) | |
| 20 | 20 | ||
| 21 | 21 | // version is set via ldflags at build time | |
| @@ -5,7 +5,6 @@ import ( | |||||
| 5 | "fmt" | 5 | "fmt" | ||
| 6 | "os" | 6 | "os" | ||
| 7 | 7 | ||||
| 8 | - | tea "github.com/charmbracelet/bubbletea" | |||
| 9 | apphandlers "github.com/bnema/archup/internal/application/handlers" | 8 | apphandlers "github.com/bnema/archup/internal/application/handlers" | ||
| 10 | "github.com/bnema/archup/internal/application/services" | 9 | "github.com/bnema/archup/internal/application/services" | ||
| 11 | "github.com/bnema/archup/internal/cleanup" | 10 | "github.com/bnema/archup/internal/cleanup" | ||
| @@ -16,6 +15,7 @@ import ( | |||||
| 16 | "github.com/bnema/archup/internal/infrastructure/persistence" | 15 | "github.com/bnema/archup/internal/infrastructure/persistence" | ||
| 17 | "github.com/bnema/archup/internal/interfaces/tui" | 16 | "github.com/bnema/archup/internal/interfaces/tui" | ||
| 18 | "github.com/bnema/archup/internal/logger" | 17 | "github.com/bnema/archup/internal/logger" | ||
| 18 | + | tea "github.com/charmbracelet/bubbletea" | |||
| 19 | ) | 19 | ) | ||
| 20 | 20 | ||||
| 21 | // version is set via ldflags at build time | 21 | // version is set via ldflags at build time | ||
M internal/application/commands/configure_system.go +7 -7
| @@ -2,13 +2,13 @@ package commands | |||
| 2 | 2 | ||
| 3 | 3 | // ConfigureSystemCommand contains data for system configuration | |
| 4 | 4 | type ConfigureSystemCommand struct { | |
| 5 | - | MountPoint string // Root mount point where system is installed | |
| 6 | - | Hostname string // System hostname | |
| 7 | - | Timezone string // IANA timezone (e.g., "UTC", "Europe/Paris") | |
| 8 | - | Locale string // System locale (e.g., "en_US.UTF-8") | |
| 9 | - | Keymap string // Keyboard layout | |
| 10 | - | Username string // Standard user username | |
| 11 | - | UserShell string // Shell for user (e.g., "/bin/bash") | |
| 5 | + | MountPoint string // Root mount point where system is installed | |
| 6 | + | Hostname string // System hostname | |
| 7 | + | Timezone string // IANA timezone (e.g., "UTC", "Europe/Paris") | |
| 8 | + | Locale string // System locale (e.g., "en_US.UTF-8") | |
| 9 | + | Keymap string // Keyboard layout | |
| 10 | + | Username string // Standard user username | |
| 11 | + | UserShell string // Shell for user (e.g., "/bin/bash") | |
| 12 | 12 | UserPassword string // User password | |
| 13 | 13 | RootPassword string // Root password | |
| 14 | 14 | } | |
| @@ -2,13 +2,13 @@ package commands | |||||
| 2 | 2 | ||||
| 3 | // ConfigureSystemCommand contains data for system configuration | 3 | // ConfigureSystemCommand contains data for system configuration | ||
| 4 | type ConfigureSystemCommand struct { | 4 | type ConfigureSystemCommand struct { | ||
| 5 | - | MountPoint string // Root mount point where system is installed | 5 | + | MountPoint string // Root mount point where system is installed |
| 6 | - | Hostname string // System hostname | 6 | + | Hostname string // System hostname |
| 7 | - | Timezone string // IANA timezone (e.g., "UTC", "Europe/Paris") | 7 | + | Timezone string // IANA timezone (e.g., "UTC", "Europe/Paris") |
| 8 | - | Locale string // System locale (e.g., "en_US.UTF-8") | 8 | + | Locale string // System locale (e.g., "en_US.UTF-8") |
| 9 | - | Keymap string // Keyboard layout | 9 | + | Keymap string // Keyboard layout |
| 10 | - | Username string // Standard user username | 10 | + | Username string // Standard user username |
| 11 | - | UserShell string // Shell for user (e.g., "/bin/bash") | 11 | + | UserShell string // Shell for user (e.g., "/bin/bash") |
| 12 | UserPassword string // User password | 12 | UserPassword string // User password | ||
| 13 | RootPassword string // Root password | 13 | RootPassword string // Root password | ||
| 14 | } | 14 | } | ||
M internal/application/commands/install_base.go +4 -4
| @@ -4,9 +4,9 @@ import "github.com/bnema/archup/internal/domain/packages" | |||
| 4 | 4 | ||
| 5 | 5 | // InstallBaseCommand contains data for base system installation | |
| 6 | 6 | type InstallBaseCommand struct { | |
| 7 | - | TargetDisk string // Target disk with partitions | |
| 8 | - | MountPoint string // Root mount point (usually "/mnt") | |
| 9 | - | Packages []string // Additional packages to install (in addition to base) | |
| 7 | + | TargetDisk string // Target disk with partitions | |
| 8 | + | MountPoint string // Root mount point (usually "/mnt") | |
| 9 | + | Packages []string // Additional packages to install (in addition to base) | |
| 10 | 10 | KernelVariant packages.KernelVariant // KernelStable, KernelZen, KernelLTS, KernelHardened, KernelCachyOS | |
| 11 | - | IncludeMicrocode bool // Whether to install CPU microcode | |
| 11 | + | IncludeMicrocode bool // Whether to install CPU microcode | |
| 12 | 12 | } | |
| @@ -4,9 +4,9 @@ import "github.com/bnema/archup/internal/domain/packages" | |||||
| 4 | 4 | ||||
| 5 | // InstallBaseCommand contains data for base system installation | 5 | // InstallBaseCommand contains data for base system installation | ||
| 6 | type InstallBaseCommand struct { | 6 | type InstallBaseCommand struct { | ||
| 7 | - | TargetDisk string // Target disk with partitions | 7 | + | TargetDisk string // Target disk with partitions |
| 8 | - | MountPoint string // Root mount point (usually "/mnt") | 8 | + | MountPoint string // Root mount point (usually "/mnt") |
| 9 | - | Packages []string // Additional packages to install (in addition to base) | 9 | + | Packages []string // Additional packages to install (in addition to base) |
| 10 | KernelVariant packages.KernelVariant // KernelStable, KernelZen, KernelLTS, KernelHardened, KernelCachyOS | 10 | KernelVariant packages.KernelVariant // KernelStable, KernelZen, KernelLTS, KernelHardened, KernelCachyOS | ||
| 11 | - | IncludeMicrocode bool // Whether to install CPU microcode | 11 | + | IncludeMicrocode bool // Whether to install CPU microcode |
| 12 | } | 12 | } | ||
M internal/application/commands/install_bootloader.go +3 -3
| @@ -4,8 +4,8 @@ import "github.com/bnema/archup/internal/domain/bootloader" | |||
| 4 | 4 | ||
| 5 | 5 | // InstallBootloaderCommand contains data for bootloader installation | |
| 6 | 6 | type InstallBootloaderCommand struct { | |
| 7 | - | MountPoint string // Root mount point | |
| 7 | + | MountPoint string // Root mount point | |
| 8 | 8 | BootloaderType bootloader.BootloaderType // BootloaderTypeLimine or BootloaderTypeSystemdBoot | |
| 9 | - | TimeoutSeconds int // Boot menu timeout (0-600 seconds) | |
| 10 | - | Branding string // Bootloader display name | |
| 9 | + | TimeoutSeconds int // Boot menu timeout (0-600 seconds) | |
| 10 | + | Branding string // Bootloader display name | |
| 11 | 11 | } | |
| @@ -4,8 +4,8 @@ import "github.com/bnema/archup/internal/domain/bootloader" | |||||
| 4 | 4 | ||||
| 5 | // InstallBootloaderCommand contains data for bootloader installation | 5 | // InstallBootloaderCommand contains data for bootloader installation | ||
| 6 | type InstallBootloaderCommand struct { | 6 | type InstallBootloaderCommand struct { | ||
| 7 | - | MountPoint string // Root mount point | 7 | + | MountPoint string // Root mount point |
| 8 | BootloaderType bootloader.BootloaderType // BootloaderTypeLimine or BootloaderTypeSystemdBoot | 8 | BootloaderType bootloader.BootloaderType // BootloaderTypeLimine or BootloaderTypeSystemdBoot | ||
| 9 | - | TimeoutSeconds int // Boot menu timeout (0-600 seconds) | 9 | + | TimeoutSeconds int // Boot menu timeout (0-600 seconds) |
| 10 | - | Branding string // Bootloader display name | 10 | + | Branding string // Bootloader display name |
| 11 | } | 11 | } | ||
M internal/application/commands/partition.go +3 -3
| @@ -4,9 +4,9 @@ import "github.com/bnema/archup/internal/domain/disk" | |||
| 4 | 4 | ||
| 5 | 5 | // PartitionDiskCommand contains data for disk partitioning | |
| 6 | 6 | type PartitionDiskCommand struct { | |
| 7 | - | TargetDisk string // e.g., "/dev/sda" | |
| 8 | - | RootSizeGB int64 // Size of root partition in GB | |
| 9 | - | BootSizeGB int64 // Size of boot partition in GB (usually 512MB-1GB) | |
| 7 | + | TargetDisk string // e.g., "/dev/sda" | |
| 8 | + | RootSizeGB int64 // Size of root partition in GB | |
| 9 | + | BootSizeGB int64 // Size of boot partition in GB (usually 512MB-1GB) | |
| 10 | 10 | EncryptionType disk.EncryptionType // EncryptionTypeNone, EncryptionTypeLUKS, EncryptionTypeLUKSLVM | |
| 11 | 11 | EncryptionPassword string // Password for encrypted partitions (if applicable) | |
| 12 | 12 | FilesystemType disk.FilesystemType // FilesystemExt4, FilesystemBtrfs, FilesystemFAT32 | |
| @@ -4,9 +4,9 @@ import "github.com/bnema/archup/internal/domain/disk" | |||||
| 4 | 4 | ||||
| 5 | // PartitionDiskCommand contains data for disk partitioning | 5 | // PartitionDiskCommand contains data for disk partitioning | ||
| 6 | type PartitionDiskCommand struct { | 6 | type PartitionDiskCommand struct { | ||
| 7 | - | TargetDisk string // e.g., "/dev/sda" | 7 | + | TargetDisk string // e.g., "/dev/sda" |
| 8 | - | RootSizeGB int64 // Size of root partition in GB | 8 | + | RootSizeGB int64 // Size of root partition in GB |
| 9 | - | BootSizeGB int64 // Size of boot partition in GB (usually 512MB-1GB) | 9 | + | BootSizeGB int64 // Size of boot partition in GB (usually 512MB-1GB) |
| 10 | EncryptionType disk.EncryptionType // EncryptionTypeNone, EncryptionTypeLUKS, EncryptionTypeLUKSLVM | 10 | EncryptionType disk.EncryptionType // EncryptionTypeNone, EncryptionTypeLUKS, EncryptionTypeLUKSLVM | ||
| 11 | EncryptionPassword string // Password for encrypted partitions (if applicable) | 11 | EncryptionPassword string // Password for encrypted partitions (if applicable) | ||
| 12 | FilesystemType disk.FilesystemType // FilesystemExt4, FilesystemBtrfs, FilesystemFAT32 | 12 | FilesystemType disk.FilesystemType // FilesystemExt4, FilesystemBtrfs, FilesystemFAT32 | ||
M internal/application/commands/post_install.go +3 -3
| @@ -2,8 +2,8 @@ package commands | |||
| 2 | 2 | ||
| 3 | 3 | // PostInstallCommand contains data for post-installation tasks | |
| 4 | 4 | type PostInstallCommand struct { | |
| 5 | - | MountPoint string // Root mount point | |
| 6 | - | Username string // Standard user username | |
| 5 | + | MountPoint string // Root mount point | |
| 6 | + | Username string // Standard user username | |
| 7 | 7 | RunPostBootScripts bool // Whether to run post-boot scripts | |
| 8 | - | PlymouthTheme string // Plymouth theme to install (optional) | |
| 8 | + | PlymouthTheme string // Plymouth theme to install (optional) | |
| 9 | 9 | } | |
| @@ -2,8 +2,8 @@ package commands | |||||
| 2 | 2 | ||||
| 3 | // PostInstallCommand contains data for post-installation tasks | 3 | // PostInstallCommand contains data for post-installation tasks | ||
| 4 | type PostInstallCommand struct { | 4 | type PostInstallCommand struct { | ||
| 5 | - | MountPoint string // Root mount point | 5 | + | MountPoint string // Root mount point |
| 6 | - | Username string // Standard user username | 6 | + | Username string // Standard user username |
| 7 | RunPostBootScripts bool // Whether to run post-boot scripts | 7 | RunPostBootScripts bool // Whether to run post-boot scripts | ||
| 8 | - | PlymouthTheme string // Plymouth theme to install (optional) | 8 | + | PlymouthTheme string // Plymouth theme to install (optional) |
| 9 | } | 9 | } | ||
M internal/application/commands/setup_repos.go +4 -4
| @@ -4,9 +4,9 @@ import "github.com/bnema/archup/internal/domain/packages" | |||
| 4 | 4 | ||
| 5 | 5 | // SetupRepositoriesCommand contains data for repository configuration | |
| 6 | 6 | type SetupRepositoriesCommand struct { | |
| 7 | - | MountPoint string // Root mount point | |
| 8 | - | EnableMultilib bool // Enable multilib repository | |
| 9 | - | EnableChaotic bool // Enable Chaotic-AUR repository | |
| 7 | + | MountPoint string // Root mount point | |
| 8 | + | EnableMultilib bool // Enable multilib repository | |
| 9 | + | EnableChaotic bool // Enable Chaotic-AUR repository | |
| 10 | 10 | AURHelper packages.AURHelper // AURHelperParu or AURHelperYay | |
| 11 | - | AdditionalRepos []string // Additional repository URLs | |
| 11 | + | AdditionalRepos []string // Additional repository URLs | |
| 12 | 12 | } | |
| @@ -4,9 +4,9 @@ import "github.com/bnema/archup/internal/domain/packages" | |||||
| 4 | 4 | ||||
| 5 | // SetupRepositoriesCommand contains data for repository configuration | 5 | // SetupRepositoriesCommand contains data for repository configuration | ||
| 6 | type SetupRepositoriesCommand struct { | 6 | type SetupRepositoriesCommand struct { | ||
| 7 | - | MountPoint string // Root mount point | 7 | + | MountPoint string // Root mount point |
| 8 | - | EnableMultilib bool // Enable multilib repository | 8 | + | EnableMultilib bool // Enable multilib repository |
| 9 | - | EnableChaotic bool // Enable Chaotic-AUR repository | 9 | + | EnableChaotic bool // Enable Chaotic-AUR repository |
| 10 | AURHelper packages.AURHelper // AURHelperParu or AURHelperYay | 10 | AURHelper packages.AURHelper // AURHelperParu or AURHelperYay | ||
| 11 | - | AdditionalRepos []string // Additional repository URLs | 11 | + | AdditionalRepos []string // Additional repository URLs |
| 12 | } | 12 | } | ||
M internal/application/dto/installation_status.go +10 -10
| @@ -4,16 +4,16 @@ import "time" | |||
| 4 | 4 | ||
| 5 | 5 | // InstallationStatus represents the overall installation status | |
| 6 | 6 | type InstallationStatus struct { | |
| 7 | - | ID string // Installation ID (UUID) | |
| 8 | - | State string // Current state (NotStarted, PreflightChecks, etc.) | |
| 9 | - | Hostname string // Configured hostname | |
| 10 | - | Username string // Configured username | |
| 11 | - | TargetDisk string // Target installation disk | |
| 12 | - | EncryptionType string // Encryption type (none, LUKS, LUKS-LVM) | |
| 13 | - | Progress int // Progress percentage (0-100) | |
| 7 | + | ID string // Installation ID (UUID) | |
| 8 | + | State string // Current state (NotStarted, PreflightChecks, etc.) | |
| 9 | + | Hostname string // Configured hostname | |
| 10 | + | Username string // Configured username | |
| 11 | + | TargetDisk string // Target installation disk | |
| 12 | + | EncryptionType string // Encryption type (none, LUKS, LUKS-LVM) | |
| 13 | + | Progress int // Progress percentage (0-100) | |
| 14 | 14 | StartedAt *time.Time // When installation started | |
| 15 | 15 | CompletedAt *time.Time // When installation completed | |
| 16 | - | CurrentPhase string // Current phase name | |
| 17 | - | LastError string // Last error message (if any) | |
| 18 | - | EstimatedRemaining int // Estimated remaining time in seconds | |
| 16 | + | CurrentPhase string // Current phase name | |
| 17 | + | LastError string // Last error message (if any) | |
| 18 | + | EstimatedRemaining int // Estimated remaining time in seconds | |
| 19 | 19 | } | |
| @@ -4,16 +4,16 @@ import "time" | |||||
| 4 | 4 | ||||
| 5 | // InstallationStatus represents the overall installation status | 5 | // InstallationStatus represents the overall installation status | ||
| 6 | type InstallationStatus struct { | 6 | type InstallationStatus struct { | ||
| 7 | - | ID string // Installation ID (UUID) | 7 | + | ID string // Installation ID (UUID) |
| 8 | - | State string // Current state (NotStarted, PreflightChecks, etc.) | 8 | + | State string // Current state (NotStarted, PreflightChecks, etc.) |
| 9 | - | Hostname string // Configured hostname | 9 | + | Hostname string // Configured hostname |
| 10 | - | Username string // Configured username | 10 | + | Username string // Configured username |
| 11 | - | TargetDisk string // Target installation disk | 11 | + | TargetDisk string // Target installation disk |
| 12 | - | EncryptionType string // Encryption type (none, LUKS, LUKS-LVM) | 12 | + | EncryptionType string // Encryption type (none, LUKS, LUKS-LVM) |
| 13 | - | Progress int // Progress percentage (0-100) | 13 | + | Progress int // Progress percentage (0-100) |
| 14 | StartedAt *time.Time // When installation started | 14 | StartedAt *time.Time // When installation started | ||
| 15 | CompletedAt *time.Time // When installation completed | 15 | CompletedAt *time.Time // When installation completed | ||
| 16 | - | CurrentPhase string // Current phase name | 16 | + | CurrentPhase string // Current phase name |
| 17 | - | LastError string // Last error message (if any) | 17 | + | LastError string // Last error message (if any) |
| 18 | - | EstimatedRemaining int // Estimated remaining time in seconds | 18 | + | EstimatedRemaining int // Estimated remaining time in seconds |
| 19 | } | 19 | } | ||
M internal/application/dto/preflight_result.go +3 -3
| @@ -2,9 +2,9 @@ package dto | |||
| 2 | 2 | ||
| 3 | 3 | // SystemInfo contains basic system information | |
| 4 | 4 | type SystemInfo struct { | |
| 5 | - | Architecture string | |
| 6 | - | IsUEFI bool | |
| 7 | - | Distribution string | |
| 5 | + | Architecture string | |
| 6 | + | IsUEFI bool | |
| 7 | + | Distribution string | |
| 8 | 8 | SecureBootEnabled bool | |
| 9 | 9 | } | |
| 10 | 10 | ||
| @@ -2,9 +2,9 @@ package dto | |||||
| 2 | 2 | ||||
| 3 | // SystemInfo contains basic system information | 3 | // SystemInfo contains basic system information | ||
| 4 | type SystemInfo struct { | 4 | type SystemInfo struct { | ||
| 5 | - | Architecture string | 5 | + | Architecture string |
| 6 | - | IsUEFI bool | 6 | + | IsUEFI bool |
| 7 | - | Distribution string | 7 | + | Distribution string |
| 8 | SecureBootEnabled bool | 8 | SecureBootEnabled bool | ||
| 9 | } | 9 | } | ||
| 10 | 10 | ||||
M internal/application/dto/progress_update.go +7 -7
| @@ -4,11 +4,11 @@ import "time" | |||
| 4 | 4 | ||
| 5 | 5 | // ProgressUpdate represents a progress update during installation | |
| 6 | 6 | type ProgressUpdate struct { | |
| 7 | - | Phase string // Current phase name | |
| 8 | - | PhaseNumber int // Current phase number (1-8) | |
| 9 | - | TotalPhases int // Total phases (8) | |
| 10 | - | ProgressPercent int // Overall progress percentage (0-100) | |
| 11 | - | Message string // Status message | |
| 12 | - | IsError bool // Whether this is an error | |
| 13 | - | Timestamp time.Time // When this update occurred | |
| 7 | + | Phase string // Current phase name | |
| 8 | + | PhaseNumber int // Current phase number (1-8) | |
| 9 | + | TotalPhases int // Total phases (8) | |
| 10 | + | ProgressPercent int // Overall progress percentage (0-100) | |
| 11 | + | Message string // Status message | |
| 12 | + | IsError bool // Whether this is an error | |
| 13 | + | Timestamp time.Time // When this update occurred | |
| 14 | 14 | } | |
| @@ -4,11 +4,11 @@ import "time" | |||||
| 4 | 4 | ||||
| 5 | // ProgressUpdate represents a progress update during installation | 5 | // ProgressUpdate represents a progress update during installation | ||
| 6 | type ProgressUpdate struct { | 6 | type ProgressUpdate struct { | ||
| 7 | - | Phase string // Current phase name | 7 | + | Phase string // Current phase name |
| 8 | - | PhaseNumber int // Current phase number (1-8) | 8 | + | PhaseNumber int // Current phase number (1-8) |
| 9 | - | TotalPhases int // Total phases (8) | 9 | + | TotalPhases int // Total phases (8) |
| 10 | - | ProgressPercent int // Overall progress percentage (0-100) | 10 | + | ProgressPercent int // Overall progress percentage (0-100) |
| 11 | - | Message string // Status message | 11 | + | Message string // Status message |
| 12 | - | IsError bool // Whether this is an error | 12 | + | IsError bool // Whether this is an error |
| 13 | - | Timestamp time.Time // When this update occurred | 13 | + | Timestamp time.Time // When this update occurred |
| 14 | } | 14 | } | ||
M internal/application/handlers/bootloader_handler.go +5 -3
| @@ -28,11 +28,12 @@ func NewBootloaderHandler(chrExec ports.ChrootExecutor, logger ports.Logger) *Bo | |||
| 28 | 28 | func (h *BootloaderHandler) Handle(ctx context.Context, cmd commands.InstallBootloaderCommand) (*dto.BootloaderResult, error) { | |
| 29 | 29 | h.logger.Info("Starting bootloader installation", "type", cmd.BootloaderType) | |
| 30 | 30 | ||
| 31 | + | h.logger.Info("Validating bootloader configuration...") | |
| 31 | 32 | result := &dto.BootloaderResult{ | |
| 32 | - | Success: false, | |
| 33 | + | Success: false, | |
| 33 | 34 | BootloaderType: "", | |
| 34 | - | Timeout: cmd.TimeoutSeconds, | |
| 35 | - | ErrorDetail: "", | |
| 35 | + | Timeout: cmd.TimeoutSeconds, | |
| 36 | + | ErrorDetail: "", | |
| 36 | 37 | } | |
| 37 | 38 | ||
| 38 | 39 | // Create bootloader domain object | |
| @@ -46,6 +47,7 @@ func (h *BootloaderHandler) Handle(ctx context.Context, cmd commands.InstallBoot | |||
| 46 | 47 | h.logger.Info("Bootloader configuration validated", "type", bl.Type()) | |
| 47 | 48 | ||
| 48 | 49 | // In a real implementation, this would configure and install the bootloader | |
| 50 | + | h.logger.Info("Installing bootloader...", "type", bl.Type()) | |
| 49 | 51 | // For Limine: configure limine.cfg | |
| 50 | 52 | // For systemd-boot: configure bootctl and entry files | |
| 51 | 53 | ||
| @@ -28,11 +28,12 @@ func NewBootloaderHandler(chrExec ports.ChrootExecutor, logger ports.Logger) *Bo | |||||
| 28 | func (h *BootloaderHandler) Handle(ctx context.Context, cmd commands.InstallBootloaderCommand) (*dto.BootloaderResult, error) { | 28 | func (h *BootloaderHandler) Handle(ctx context.Context, cmd commands.InstallBootloaderCommand) (*dto.BootloaderResult, error) { | ||
| 29 | h.logger.Info("Starting bootloader installation", "type", cmd.BootloaderType) | 29 | h.logger.Info("Starting bootloader installation", "type", cmd.BootloaderType) | ||
| 30 | 30 | ||||
| 31 | + | h.logger.Info("Validating bootloader configuration...") | |||
| 31 | result := &dto.BootloaderResult{ | 32 | result := &dto.BootloaderResult{ | ||
| 32 | - | Success: false, | 33 | + | Success: false, |
| 33 | BootloaderType: "", | 34 | BootloaderType: "", | ||
| 34 | - | Timeout: cmd.TimeoutSeconds, | 35 | + | Timeout: cmd.TimeoutSeconds, |
| 35 | - | ErrorDetail: "", | 36 | + | ErrorDetail: "", |
| 36 | } | 37 | } | ||
| 37 | 38 | ||||
| 38 | // Create bootloader domain object | 39 | // Create bootloader domain object | ||
| @@ -46,6 +47,7 @@ func (h *BootloaderHandler) Handle(ctx context.Context, cmd commands.InstallBoot | |||||
| 46 | h.logger.Info("Bootloader configuration validated", "type", bl.Type()) | 47 | h.logger.Info("Bootloader configuration validated", "type", bl.Type()) | ||
| 47 | 48 | ||||
| 48 | // In a real implementation, this would configure and install the bootloader | 49 | // In a real implementation, this would configure and install the bootloader | ||
| 50 | + | h.logger.Info("Installing bootloader...", "type", bl.Type()) | |||
| 49 | // For Limine: configure limine.cfg | 51 | // For Limine: configure limine.cfg | ||
| 50 | // For systemd-boot: configure bootctl and entry files | 52 | // For systemd-boot: configure bootctl and entry files | ||
| 51 | 53 | ||||
M internal/application/handlers/install_base_handler.go +6 -6
| @@ -12,10 +12,10 @@ import ( | |||
| 12 | 12 | ||
| 13 | 13 | // InstallBaseHandler handles base system installation | |
| 14 | 14 | type InstallBaseHandler struct { | |
| 15 | - | fs ports.FileSystem | |
| 16 | - | cmdExec ports.CommandExecutor | |
| 17 | - | chrExec ports.ChrootExecutor | |
| 18 | - | logger ports.Logger | |
| 15 | + | fs ports.FileSystem | |
| 16 | + | cmdExec ports.CommandExecutor | |
| 17 | + | chrExec ports.ChrootExecutor | |
| 18 | + | logger ports.Logger | |
| 19 | 19 | } | |
| 20 | 20 | ||
| 21 | 21 | // NewInstallBaseHandler creates a new base installation handler | |
| @@ -33,9 +33,9 @@ func (h *InstallBaseHandler) Handle(ctx context.Context, cmd commands.InstallBas | |||
| 33 | 33 | h.logger.Info("Starting base system installation", "kernel", cmd.KernelVariant) | |
| 34 | 34 | ||
| 35 | 35 | result := &dto.InstallBaseResult{ | |
| 36 | - | Success: false, | |
| 36 | + | Success: false, | |
| 37 | 37 | PackagesInstalled: []string{}, | |
| 38 | - | ErrorDetail: "", | |
| 38 | + | ErrorDetail: "", | |
| 39 | 39 | } | |
| 40 | 40 | ||
| 41 | 41 | // Validate kernel variant | |
| @@ -12,10 +12,10 @@ import ( | |||||
| 12 | 12 | ||||
| 13 | // InstallBaseHandler handles base system installation | 13 | // InstallBaseHandler handles base system installation | ||
| 14 | type InstallBaseHandler struct { | 14 | type InstallBaseHandler struct { | ||
| 15 | - | fs ports.FileSystem | 15 | + | fs ports.FileSystem |
| 16 | - | cmdExec ports.CommandExecutor | 16 | + | cmdExec ports.CommandExecutor |
| 17 | - | chrExec ports.ChrootExecutor | 17 | + | chrExec ports.ChrootExecutor |
| 18 | - | logger ports.Logger | 18 | + | logger ports.Logger |
| 19 | } | 19 | } | ||
| 20 | 20 | ||||
| 21 | // NewInstallBaseHandler creates a new base installation handler | 21 | // NewInstallBaseHandler creates a new base installation handler | ||
| @@ -33,9 +33,9 @@ func (h *InstallBaseHandler) Handle(ctx context.Context, cmd commands.InstallBas | |||||
| 33 | h.logger.Info("Starting base system installation", "kernel", cmd.KernelVariant) | 33 | h.logger.Info("Starting base system installation", "kernel", cmd.KernelVariant) | ||
| 34 | 34 | ||||
| 35 | result := &dto.InstallBaseResult{ | 35 | result := &dto.InstallBaseResult{ | ||
| 36 | - | Success: false, | 36 | + | Success: false, |
| 37 | PackagesInstalled: []string{}, | 37 | PackagesInstalled: []string{}, | ||
| 38 | - | ErrorDetail: "", | 38 | + | ErrorDetail: "", |
| 39 | } | 39 | } | ||
| 40 | 40 | ||||
| 41 | // Validate kernel variant | 41 | // Validate kernel variant | ||
M internal/application/handlers/partition_handler_test.go +10 -10
| @@ -73,11 +73,11 @@ func TestPartitionHandler_Handle_InvalidDisk(t *testing.T) { | |||
| 73 | 73 | handler := NewPartitionHandler(mockExec, mockLogger) | |
| 74 | 74 | ||
| 75 | 75 | cmd := commands.PartitionDiskCommand{ | |
| 76 | - | TargetDisk: "", | |
| 77 | - | RootSizeGB: 50, | |
| 78 | - | BootSizeGB: 1, | |
| 79 | - | EncryptionType: disk.EncryptionTypeNone, | |
| 80 | - | FilesystemType: disk.FilesystemExt4, | |
| 76 | + | TargetDisk: "", | |
| 77 | + | RootSizeGB: 50, | |
| 78 | + | BootSizeGB: 1, | |
| 79 | + | EncryptionType: disk.EncryptionTypeNone, | |
| 80 | + | FilesystemType: disk.FilesystemExt4, | |
| 81 | 81 | } | |
| 82 | 82 | ||
| 83 | 83 | result, err := handler.Handle(context.Background(), cmd) | |
| @@ -104,11 +104,11 @@ func TestPartitionHandler_Handle_RootPartitionTooSmall(t *testing.T) { | |||
| 104 | 104 | handler := NewPartitionHandler(mockExec, mockLogger) | |
| 105 | 105 | ||
| 106 | 106 | cmd := commands.PartitionDiskCommand{ | |
| 107 | - | TargetDisk: "/dev/sda", | |
| 108 | - | RootSizeGB: 1, // Too small | |
| 109 | - | BootSizeGB: 1, | |
| 110 | - | EncryptionType: disk.EncryptionTypeNone, | |
| 111 | - | FilesystemType: disk.FilesystemExt4, | |
| 107 | + | TargetDisk: "/dev/sda", | |
| 108 | + | RootSizeGB: 1, // Too small | |
| 109 | + | BootSizeGB: 1, | |
| 110 | + | EncryptionType: disk.EncryptionTypeNone, | |
| 111 | + | FilesystemType: disk.FilesystemExt4, | |
| 112 | 112 | } | |
| 113 | 113 | ||
| 114 | 114 | result, err := handler.Handle(context.Background(), cmd) | |
| @@ -73,11 +73,11 @@ func TestPartitionHandler_Handle_InvalidDisk(t *testing.T) { | |||||
| 73 | handler := NewPartitionHandler(mockExec, mockLogger) | 73 | handler := NewPartitionHandler(mockExec, mockLogger) | ||
| 74 | 74 | ||||
| 75 | cmd := commands.PartitionDiskCommand{ | 75 | cmd := commands.PartitionDiskCommand{ | ||
| 76 | - | TargetDisk: "", | 76 | + | TargetDisk: "", |
| 77 | - | RootSizeGB: 50, | 77 | + | RootSizeGB: 50, |
| 78 | - | BootSizeGB: 1, | 78 | + | BootSizeGB: 1, |
| 79 | - | EncryptionType: disk.EncryptionTypeNone, | 79 | + | EncryptionType: disk.EncryptionTypeNone, |
| 80 | - | FilesystemType: disk.FilesystemExt4, | 80 | + | FilesystemType: disk.FilesystemExt4, |
| 81 | } | 81 | } | ||
| 82 | 82 | ||||
| 83 | result, err := handler.Handle(context.Background(), cmd) | 83 | result, err := handler.Handle(context.Background(), cmd) | ||
| @@ -104,11 +104,11 @@ func TestPartitionHandler_Handle_RootPartitionTooSmall(t *testing.T) { | |||||
| 104 | handler := NewPartitionHandler(mockExec, mockLogger) | 104 | handler := NewPartitionHandler(mockExec, mockLogger) | ||
| 105 | 105 | ||||
| 106 | cmd := commands.PartitionDiskCommand{ | 106 | cmd := commands.PartitionDiskCommand{ | ||
| 107 | - | TargetDisk: "/dev/sda", | 107 | + | TargetDisk: "/dev/sda", |
| 108 | - | RootSizeGB: 1, // Too small | 108 | + | RootSizeGB: 1, // Too small |
| 109 | - | BootSizeGB: 1, | 109 | + | BootSizeGB: 1, |
| 110 | - | EncryptionType: disk.EncryptionTypeNone, | 110 | + | EncryptionType: disk.EncryptionTypeNone, |
| 111 | - | FilesystemType: disk.FilesystemExt4, | 111 | + | FilesystemType: disk.FilesystemExt4, |
| 112 | } | 112 | } | ||
| 113 | 113 | ||||
| 114 | result, err := handler.Handle(context.Background(), cmd) | 114 | result, err := handler.Handle(context.Background(), cmd) | ||
M internal/application/handlers/post_install_handler.go +6 -6
| @@ -11,17 +11,17 @@ import ( | |||
| 11 | 11 | ||
| 12 | 12 | // PostInstallHandler handles post-installation tasks | |
| 13 | 13 | type PostInstallHandler struct { | |
| 14 | - | chrExec ports.ChrootExecutor | |
| 14 | + | chrExec ports.ChrootExecutor | |
| 15 | 15 | scriptExec ports.ScriptExecutor | |
| 16 | - | logger ports.Logger | |
| 16 | + | logger ports.Logger | |
| 17 | 17 | } | |
| 18 | 18 | ||
| 19 | 19 | // NewPostInstallHandler creates a new post-installation handler | |
| 20 | 20 | func NewPostInstallHandler(chrExec ports.ChrootExecutor, scriptExec ports.ScriptExecutor, logger ports.Logger) *PostInstallHandler { | |
| 21 | 21 | return &PostInstallHandler{ | |
| 22 | - | chrExec: chrExec, | |
| 22 | + | chrExec: chrExec, | |
| 23 | 23 | scriptExec: scriptExec, | |
| 24 | - | logger: logger, | |
| 24 | + | logger: logger, | |
| 25 | 25 | } | |
| 26 | 26 | } | |
| 27 | 27 | ||
| @@ -30,8 +30,8 @@ func (h *PostInstallHandler) Handle(ctx context.Context, cmd commands.PostInstal | |||
| 30 | 30 | h.logger.Info("Starting post-installation tasks", "username", cmd.Username) | |
| 31 | 31 | ||
| 32 | 32 | result := &dto.PostInstallResult{ | |
| 33 | - | Success: false, | |
| 34 | - | TasksRun: []string{}, | |
| 33 | + | Success: false, | |
| 34 | + | TasksRun: []string{}, | |
| 35 | 35 | ErrorDetail: "", | |
| 36 | 36 | } | |
| 37 | 37 | ||
| @@ -11,17 +11,17 @@ import ( | |||||
| 11 | 11 | ||||
| 12 | // PostInstallHandler handles post-installation tasks | 12 | // PostInstallHandler handles post-installation tasks | ||
| 13 | type PostInstallHandler struct { | 13 | type PostInstallHandler struct { | ||
| 14 | - | chrExec ports.ChrootExecutor | 14 | + | chrExec ports.ChrootExecutor |
| 15 | scriptExec ports.ScriptExecutor | 15 | scriptExec ports.ScriptExecutor | ||
| 16 | - | logger ports.Logger | 16 | + | logger ports.Logger |
| 17 | } | 17 | } | ||
| 18 | 18 | ||||
| 19 | // NewPostInstallHandler creates a new post-installation handler | 19 | // NewPostInstallHandler creates a new post-installation handler | ||
| 20 | func NewPostInstallHandler(chrExec ports.ChrootExecutor, scriptExec ports.ScriptExecutor, logger ports.Logger) *PostInstallHandler { | 20 | func NewPostInstallHandler(chrExec ports.ChrootExecutor, scriptExec ports.ScriptExecutor, logger ports.Logger) *PostInstallHandler { | ||
| 21 | return &PostInstallHandler{ | 21 | return &PostInstallHandler{ | ||
| 22 | - | chrExec: chrExec, | 22 | + | chrExec: chrExec, |
| 23 | scriptExec: scriptExec, | 23 | scriptExec: scriptExec, | ||
| 24 | - | logger: logger, | 24 | + | logger: logger, |
| 25 | } | 25 | } | ||
| 26 | } | 26 | } | ||
| 27 | 27 | ||||
| @@ -30,8 +30,8 @@ func (h *PostInstallHandler) Handle(ctx context.Context, cmd commands.PostInstal | |||||
| 30 | h.logger.Info("Starting post-installation tasks", "username", cmd.Username) | 30 | h.logger.Info("Starting post-installation tasks", "username", cmd.Username) | ||
| 31 | 31 | ||||
| 32 | result := &dto.PostInstallResult{ | 32 | result := &dto.PostInstallResult{ | ||
| 33 | - | Success: false, | 33 | + | Success: false, |
| 34 | - | TasksRun: []string{}, | 34 | + | TasksRun: []string{}, |
| 35 | ErrorDetail: "", | 35 | ErrorDetail: "", | ||
| 36 | } | 36 | } | ||
| 37 | 37 | ||||
M internal/application/handlers/preflight_handler.go +4 -4
| @@ -12,10 +12,10 @@ import ( | |||
| 12 | 12 | ||
| 13 | 13 | // PreflightHandler handles preflight checks | |
| 14 | 14 | type PreflightHandler struct { | |
| 15 | - | fs ports.FileSystem | |
| 16 | - | cmdExec ports.CommandExecutor | |
| 17 | - | logger ports.Logger | |
| 18 | - | rules *system.SystemValidationRules | |
| 15 | + | fs ports.FileSystem | |
| 16 | + | cmdExec ports.CommandExecutor | |
| 17 | + | logger ports.Logger | |
| 18 | + | rules *system.SystemValidationRules | |
| 19 | 19 | } | |
| 20 | 20 | ||
| 21 | 21 | // NewPreflightHandler creates a new preflight handler | |
| @@ -12,10 +12,10 @@ import ( | |||||
| 12 | 12 | ||||
| 13 | // PreflightHandler handles preflight checks | 13 | // PreflightHandler handles preflight checks | ||
| 14 | type PreflightHandler struct { | 14 | type PreflightHandler struct { | ||
| 15 | - | fs ports.FileSystem | 15 | + | fs ports.FileSystem |
| 16 | - | cmdExec ports.CommandExecutor | 16 | + | cmdExec ports.CommandExecutor |
| 17 | - | logger ports.Logger | 17 | + | logger ports.Logger |
| 18 | - | rules *system.SystemValidationRules | 18 | + | rules *system.SystemValidationRules |
| 19 | } | 19 | } | ||
| 20 | 20 | ||||
| 21 | // NewPreflightHandler creates a new preflight handler | 21 | // NewPreflightHandler creates a new preflight handler | ||
M internal/application/handlers/repos_handler.go +5 -5
| @@ -29,11 +29,11 @@ func (h *ReposHandler) Handle(ctx context.Context, cmd commands.SetupRepositorie | |||
| 29 | 29 | h.logger.Info("Starting repository configuration", "multilib", cmd.EnableMultilib, "chaotic", cmd.EnableChaotic) | |
| 30 | 30 | ||
| 31 | 31 | result := &dto.RepositoriesResult{ | |
| 32 | - | Success: false, | |
| 33 | - | Multilib: cmd.EnableMultilib, | |
| 34 | - | Chaotic: cmd.EnableChaotic, | |
| 35 | - | AURHelper: "", | |
| 36 | - | ErrorDetail: "", | |
| 32 | + | Success: false, | |
| 33 | + | Multilib: cmd.EnableMultilib, | |
| 34 | + | Chaotic: cmd.EnableChaotic, | |
| 35 | + | AURHelper: "", | |
| 36 | + | ErrorDetail: "", | |
| 37 | 37 | } | |
| 38 | 38 | ||
| 39 | 39 | // Create repository domain object | |
| @@ -29,11 +29,11 @@ func (h *ReposHandler) Handle(ctx context.Context, cmd commands.SetupRepositorie | |||||
| 29 | h.logger.Info("Starting repository configuration", "multilib", cmd.EnableMultilib, "chaotic", cmd.EnableChaotic) | 29 | h.logger.Info("Starting repository configuration", "multilib", cmd.EnableMultilib, "chaotic", cmd.EnableChaotic) | ||
| 30 | 30 | ||||
| 31 | result := &dto.RepositoriesResult{ | 31 | result := &dto.RepositoriesResult{ | ||
| 32 | - | Success: false, | 32 | + | Success: false, |
| 33 | - | Multilib: cmd.EnableMultilib, | 33 | + | Multilib: cmd.EnableMultilib, |
| 34 | - | Chaotic: cmd.EnableChaotic, | 34 | + | Chaotic: cmd.EnableChaotic, |
| 35 | - | AURHelper: "", | 35 | + | AURHelper: "", |
| 36 | - | ErrorDetail: "", | 36 | + | ErrorDetail: "", |
| 37 | } | 37 | } | ||
| 38 | 38 | ||||
| 39 | // Create repository domain object | 39 | // Create repository domain object | ||
M internal/application/services/installation_service.go +17 -17
| @@ -18,13 +18,13 @@ type InstallationService struct { | |||
| 18 | 18 | installAgg *installation.Installation | |
| 19 | 19 | ||
| 20 | 20 | // Handlers | |
| 21 | - | preflightHandler *handlers.PreflightHandler | |
| 22 | - | partitionHandler *handlers.PartitionHandler | |
| 23 | - | baseHandler *handlers.InstallBaseHandler | |
| 24 | - | configHandler *handlers.ConfigureSystemHandler | |
| 25 | - | bootloaderHandler *handlers.BootloaderHandler | |
| 26 | - | reposHandler *handlers.ReposHandler | |
| 27 | - | postInstallHandler *handlers.PostInstallHandler | |
| 21 | + | preflightHandler *handlers.PreflightHandler | |
| 22 | + | partitionHandler *handlers.PartitionHandler | |
| 23 | + | baseHandler *handlers.InstallBaseHandler | |
| 24 | + | configHandler *handlers.ConfigureSystemHandler | |
| 25 | + | bootloaderHandler *handlers.BootloaderHandler | |
| 26 | + | reposHandler *handlers.ReposHandler | |
| 27 | + | postInstallHandler *handlers.PostInstallHandler | |
| 28 | 28 | ||
| 29 | 29 | // Ports | |
| 30 | 30 | repo ports.InstallationRepository | |
| @@ -50,16 +50,16 @@ func NewInstallationService( | |||
| 50 | 50 | postInstallHandler *handlers.PostInstallHandler, | |
| 51 | 51 | ) *InstallationService { | |
| 52 | 52 | return &InstallationService{ | |
| 53 | - | repo: repo, | |
| 54 | - | logger: logger, | |
| 55 | - | preflightHandler: preflightHandler, | |
| 56 | - | partitionHandler: partitionHandler, | |
| 57 | - | baseHandler: baseHandler, | |
| 58 | - | configHandler: configHandler, | |
| 59 | - | bootloaderHandler: bootloaderHandler, | |
| 60 | - | reposHandler: reposHandler, | |
| 61 | - | postInstallHandler: postInstallHandler, | |
| 62 | - | tracker: NewProgressTracker(), | |
| 53 | + | repo: repo, | |
| 54 | + | logger: logger, | |
| 55 | + | preflightHandler: preflightHandler, | |
| 56 | + | partitionHandler: partitionHandler, | |
| 57 | + | baseHandler: baseHandler, | |
| 58 | + | configHandler: configHandler, | |
| 59 | + | bootloaderHandler: bootloaderHandler, | |
| 60 | + | reposHandler: reposHandler, | |
| 61 | + | postInstallHandler: postInstallHandler, | |
| 62 | + | tracker: NewProgressTracker(), | |
| 63 | 63 | } | |
| 64 | 64 | } | |
| 65 | 65 | ||
| @@ -18,13 +18,13 @@ type InstallationService struct { | |||||
| 18 | installAgg *installation.Installation | 18 | installAgg *installation.Installation | ||
| 19 | 19 | ||||
| 20 | // Handlers | 20 | // Handlers | ||
| 21 | - | preflightHandler *handlers.PreflightHandler | 21 | + | preflightHandler *handlers.PreflightHandler |
| 22 | - | partitionHandler *handlers.PartitionHandler | 22 | + | partitionHandler *handlers.PartitionHandler |
| 23 | - | baseHandler *handlers.InstallBaseHandler | 23 | + | baseHandler *handlers.InstallBaseHandler |
| 24 | - | configHandler *handlers.ConfigureSystemHandler | 24 | + | configHandler *handlers.ConfigureSystemHandler |
| 25 | - | bootloaderHandler *handlers.BootloaderHandler | 25 | + | bootloaderHandler *handlers.BootloaderHandler |
| 26 | - | reposHandler *handlers.ReposHandler | 26 | + | reposHandler *handlers.ReposHandler |
| 27 | - | postInstallHandler *handlers.PostInstallHandler | 27 | + | postInstallHandler *handlers.PostInstallHandler |
| 28 | 28 | ||||
| 29 | // Ports | 29 | // Ports | ||
| 30 | repo ports.InstallationRepository | 30 | repo ports.InstallationRepository | ||
| @@ -50,16 +50,16 @@ func NewInstallationService( | |||||
| 50 | postInstallHandler *handlers.PostInstallHandler, | 50 | postInstallHandler *handlers.PostInstallHandler, | ||
| 51 | ) *InstallationService { | 51 | ) *InstallationService { | ||
| 52 | return &InstallationService{ | 52 | return &InstallationService{ | ||
| 53 | - | repo: repo, | 53 | + | repo: repo, |
| 54 | - | logger: logger, | 54 | + | logger: logger, |
| 55 | - | preflightHandler: preflightHandler, | 55 | + | preflightHandler: preflightHandler, |
| 56 | - | partitionHandler: partitionHandler, | 56 | + | partitionHandler: partitionHandler, |
| 57 | - | baseHandler: baseHandler, | 57 | + | baseHandler: baseHandler, |
| 58 | - | configHandler: configHandler, | 58 | + | configHandler: configHandler, |
| 59 | - | bootloaderHandler: bootloaderHandler, | 59 | + | bootloaderHandler: bootloaderHandler, |
| 60 | - | reposHandler: reposHandler, | 60 | + | reposHandler: reposHandler, |
| 61 | - | postInstallHandler: postInstallHandler, | 61 | + | postInstallHandler: postInstallHandler, |
| 62 | - | tracker: NewProgressTracker(), | 62 | + | tracker: NewProgressTracker(), |
| 63 | } | 63 | } | ||
| 64 | } | 64 | } | ||
| 65 | 65 | ||||
M internal/application/services/installation_service_test.go +5 -5
| @@ -180,11 +180,11 @@ func TestInstallationService_RunPartition(t *testing.T) { | |||
| 180 | 180 | service.Start(ctx, "myarch", "testuser", "/dev/sda", "none") | |
| 181 | 181 | ||
| 182 | 182 | cmd := commands.PartitionDiskCommand{ | |
| 183 | - | TargetDisk: "/dev/sda", | |
| 184 | - | RootSizeGB: 50, | |
| 185 | - | BootSizeGB: 1, | |
| 186 | - | EncryptionType: disk.EncryptionTypeNone, | |
| 187 | - | FilesystemType: disk.FilesystemExt4, | |
| 183 | + | TargetDisk: "/dev/sda", | |
| 184 | + | RootSizeGB: 50, | |
| 185 | + | BootSizeGB: 1, | |
| 186 | + | EncryptionType: disk.EncryptionTypeNone, | |
| 187 | + | FilesystemType: disk.FilesystemExt4, | |
| 188 | 188 | } | |
| 189 | 189 | ||
| 190 | 190 | result, err := service.RunPartition(ctx, cmd) | |
| @@ -180,11 +180,11 @@ func TestInstallationService_RunPartition(t *testing.T) { | |||||
| 180 | service.Start(ctx, "myarch", "testuser", "/dev/sda", "none") | 180 | service.Start(ctx, "myarch", "testuser", "/dev/sda", "none") | ||
| 181 | 181 | ||||
| 182 | cmd := commands.PartitionDiskCommand{ | 182 | cmd := commands.PartitionDiskCommand{ | ||
| 183 | - | TargetDisk: "/dev/sda", | 183 | + | TargetDisk: "/dev/sda", |
| 184 | - | RootSizeGB: 50, | 184 | + | RootSizeGB: 50, |
| 185 | - | BootSizeGB: 1, | 185 | + | BootSizeGB: 1, |
| 186 | - | EncryptionType: disk.EncryptionTypeNone, | 186 | + | EncryptionType: disk.EncryptionTypeNone, |
| 187 | - | FilesystemType: disk.FilesystemExt4, | 187 | + | FilesystemType: disk.FilesystemExt4, |
| 188 | } | 188 | } | ||
| 189 | 189 | ||||
| 190 | result, err := service.RunPartition(ctx, cmd) | 190 | result, err := service.RunPartition(ctx, cmd) | ||
M internal/config/config.go +52 -53
| @@ -19,12 +19,12 @@ const ( | |||
| 19 | 19 | LimineConfigTemplate = "configs/limine.conf.template" | |
| 20 | 20 | ChaoticConfigFile = "configs/chaotic-aur.conf" | |
| 21 | 21 | StarshipConfigTemplate = "configs/shell/starship.toml" | |
| 22 | - | ShellConfigTemplate = "configs/shell/shell" | |
| 23 | - | ShellInitTemplate = "configs/shell/init" | |
| 24 | - | ShellAliasesTemplate = "configs/shell/aliases" | |
| 25 | - | ShellEnvsTemplate = "configs/shell/envs" | |
| 26 | - | ShellRcTemplate = "configs/shell/rc" | |
| 27 | - | BashrcTemplate = "configs/shell/bashrc" | |
| 22 | + | ShellConfigTemplate = "configs/shell/shell" | |
| 23 | + | ShellInitTemplate = "configs/shell/init" | |
| 24 | + | ShellAliasesTemplate = "configs/shell/aliases" | |
| 25 | + | ShellEnvsTemplate = "configs/shell/envs" | |
| 26 | + | ShellRcTemplate = "configs/shell/rc" | |
| 27 | + | BashrcTemplate = "configs/shell/bashrc" | |
| 28 | 28 | ) | |
| 29 | 29 | ||
| 30 | 30 | // Encryption types | |
| @@ -36,7 +36,7 @@ const ( | |||
| 36 | 36 | ||
| 37 | 37 | // Bootloader types | |
| 38 | 38 | const ( | |
| 39 | - | BootloaderLimine = "limine" | |
| 39 | + | BootloaderLimine = "limine" | |
| 40 | 40 | BootloaderSystemdBoot = "systemd-boot" | |
| 41 | 41 | ) | |
| 42 | 42 | ||
| @@ -49,7 +49,6 @@ const ( | |||
| 49 | 49 | KernelLinuxCachyOS = "linux-cachyos" | |
| 50 | 50 | ) | |
| 51 | 51 | ||
| 52 | - | ||
| 53 | 52 | // System paths | |
| 54 | 53 | const ( | |
| 55 | 54 | PathMnt = "/mnt" | |
| @@ -89,10 +88,10 @@ const ( | |||
| 89 | 88 | ||
| 90 | 89 | // Locale defaults | |
| 91 | 90 | const ( | |
| 92 | - | LocaleDefault = "en_US.UTF-8" | |
| 93 | - | LocaleDefaultGen = "en_US.UTF-8 UTF-8" | |
| 94 | - | TimezoneDefault = "" | |
| 95 | - | KeymapDefault = "us" | |
| 91 | + | LocaleDefault = "en_US.UTF-8" | |
| 92 | + | LocaleDefaultGen = "en_US.UTF-8 UTF-8" | |
| 93 | + | TimezoneDefault = "" | |
| 94 | + | KeymapDefault = "us" | |
| 96 | 95 | ) | |
| 97 | 96 | ||
| 98 | 97 | // Zram configuration | |
| @@ -116,18 +115,19 @@ const ( | |||
| 116 | 115 | ||
| 117 | 116 | // Boot paths | |
| 118 | 117 | const ( | |
| 119 | - | PathMntBoot = "/mnt/boot" | |
| 120 | - | PathMntBootEFI = "/mnt/boot/EFI" | |
| 121 | - | PathMntBootEFILimine = "/mnt/boot/EFI/limine" | |
| 122 | - | PathMntEtcMkinitcpio = "/mnt/etc/mkinitcpio.conf" | |
| 123 | - | PathUsrShareLimine = "/mnt/usr/share/limine" | |
| 124 | - | FileLimineBootloader = "BOOTX64.EFI" | |
| 125 | - | FileLimineConfig = "limine.conf" | |
| 118 | + | PathMntBoot = "/mnt/boot" | |
| 119 | + | PathMntBootEFI = "/mnt/boot/EFI" | |
| 120 | + | PathMntBootEFILimine = "/mnt/boot/EFI/limine" | |
| 121 | + | PathMntBootLimineConf = "/mnt/boot/limine.conf" | |
| 122 | + | PathMntEtcMkinitcpio = "/mnt/etc/mkinitcpio.conf" | |
| 123 | + | PathUsrShareLimine = "/mnt/usr/share/limine" | |
| 124 | + | FileLimineBootloader = "BOOTX64.EFI" | |
| 125 | + | FileLimineConfig = "limine.conf" | |
| 126 | 126 | ) | |
| 127 | 127 | ||
| 128 | 128 | // Mkinitcpio hooks | |
| 129 | 129 | const ( | |
| 130 | - | MkinitcpioHooksPlymouth = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth filesystems fsck)" | |
| 130 | + | MkinitcpioHooksPlymouth = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth filesystems fsck)" | |
| 131 | 131 | MkinitcpioHooksEncrypted = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth encrypt filesystems fsck)" | |
| 132 | 132 | ) | |
| 133 | 133 | ||
| @@ -155,16 +155,15 @@ const ( | |||
| 155 | 155 | PathMntEtcPacmanConf = "/mnt/etc/pacman.conf" | |
| 156 | 156 | ) | |
| 157 | 157 | ||
| 158 | - | ||
| 159 | 158 | // PostInstall paths | |
| 160 | 159 | const ( | |
| 161 | - | PathMntBootLogo = "/mnt/boot/arch-logo.png" | |
| 162 | - | PathMntPlymouthThemes = "/mnt/usr/share/plymouth/themes" | |
| 163 | - | PathMntEtcDefaultLimine = "/mnt/etc/default/limine" | |
| 164 | - | PathMntEtcPacmanDHooks = "/mnt/etc/pacman.d/hooks" | |
| 165 | - | PathBootEFILimineConf = "/boot/EFI/limine/limine.conf" | |
| 166 | - | ArchLogoURL = "assets/Arch_Linux__Crystal__icon.png" | |
| 167 | - | PlymouthThemeName = "archup" | |
| 160 | + | PathMntBootLogo = "/mnt/boot/arch-logo.png" | |
| 161 | + | PathMntPlymouthThemes = "/mnt/usr/share/plymouth/themes" | |
| 162 | + | PathMntEtcDefaultLimine = "/mnt/etc/default/limine" | |
| 163 | + | PathMntEtcPacmanDHooks = "/mnt/etc/pacman.d/hooks" | |
| 164 | + | PathBootLimineConf = "/boot/limine.conf" | |
| 165 | + | ArchLogoURL = "assets/Arch_Linux__Crystal__icon.png" | |
| 166 | + | PlymouthThemeName = "archup" | |
| 168 | 167 | ) | |
| 169 | 168 | ||
| 170 | 169 | // Plymouth files | |
| @@ -203,16 +202,16 @@ const PostBootServiceTemplate = "install/mandatory/post-boot/archup-first-boot.s | |||
| 203 | 202 | // This mirrors the shell script's config format for compatibility | |
| 204 | 203 | type Config struct { | |
| 205 | 204 | // Preflight | |
| 206 | - | Hostname string | |
| 207 | - | Username string | |
| 208 | - | UserPassword string | |
| 209 | - | RootPassword string | |
| 210 | - | Email string // Optional, for git and SSH configuration | |
| 211 | - | Keymap string | |
| 212 | - | Timezone string | |
| 213 | - | Locale string | |
| 214 | - | Bootloader string // "limine" or "systemd-boot" | |
| 215 | - | EncryptionType string // "none", "luks", or "luks-lvm" | |
| 205 | + | Hostname string | |
| 206 | + | Username string | |
| 207 | + | UserPassword string | |
| 208 | + | RootPassword string | |
| 209 | + | Email string // Optional, for git and SSH configuration | |
| 210 | + | Keymap string | |
| 211 | + | Timezone string | |
| 212 | + | Locale string | |
| 213 | + | Bootloader string // "limine" or "systemd-boot" | |
| 214 | + | EncryptionType string // "none", "luks", or "luks-lvm" | |
| 216 | 215 | EncryptPassword string // Separate encryption password if different from user password | |
| 217 | 216 | ||
| 218 | 217 | // Form-only fields (not persisted) | |
| @@ -220,18 +219,18 @@ type Config struct { | |||
| 220 | 219 | UseSamePasswordForEncryption bool // Checkbox state for using same password for encryption | |
| 221 | 220 | ||
| 222 | 221 | // Partitioning | |
| 223 | - | TargetDisk string | |
| 224 | - | BootPartition string | |
| 225 | - | RootPartition string | |
| 226 | - | SwapPartition string | |
| 227 | - | EFIPartition string | |
| 228 | - | CryptDevice string // /dev/mapper/cryptroot if encrypted | |
| 222 | + | TargetDisk string | |
| 223 | + | BootPartition string | |
| 224 | + | RootPartition string | |
| 225 | + | SwapPartition string | |
| 226 | + | EFIPartition string | |
| 227 | + | CryptDevice string // /dev/mapper/cryptroot if encrypted | |
| 229 | 228 | ||
| 230 | 229 | // Base | |
| 231 | - | KernelChoice string // "linux", "linux-zen", "linux-lts", "linux-hardened" | |
| 232 | - | Microcode string // "intel-ucode" or "amd-ucode" | |
| 233 | - | CPUVendor string // "Intel", "AMD", or "Unknown" | |
| 234 | - | AMDPState string // "active", "passive", "guided", or empty | |
| 230 | + | KernelChoice string // "linux", "linux-zen", "linux-lts", "linux-hardened" | |
| 231 | + | Microcode string // "intel-ucode" or "amd-ucode" | |
| 232 | + | CPUVendor string // "Intel", "AMD", or "Unknown" | |
| 233 | + | AMDPState string // "active", "passive", "guided", or empty | |
| 235 | 234 | ||
| 236 | 235 | // Config | |
| 237 | 236 | NetworkManager string // "NetworkManager" by default | |
| @@ -242,11 +241,11 @@ type Config struct { | |||
| 242 | 241 | EnableChaotic bool | |
| 243 | 242 | ||
| 244 | 243 | // Paths | |
| 245 | - | ConfigPath string | |
| 246 | - | LogPath string | |
| 247 | - | InstallPath string // ~/.local/share/archup/install | |
| 248 | - | RepoURL string | |
| 249 | - | RawURL string | |
| 244 | + | ConfigPath string | |
| 245 | + | LogPath string | |
| 246 | + | InstallPath string // ~/.local/share/archup/install | |
| 247 | + | RepoURL string | |
| 248 | + | RawURL string | |
| 250 | 249 | } | |
| 251 | 250 | ||
| 252 | 251 | // NewConfig creates a new Config with sensible defaults | |
| @@ -19,12 +19,12 @@ const ( | |||||
| 19 | LimineConfigTemplate = "configs/limine.conf.template" | 19 | LimineConfigTemplate = "configs/limine.conf.template" | ||
| 20 | ChaoticConfigFile = "configs/chaotic-aur.conf" | 20 | ChaoticConfigFile = "configs/chaotic-aur.conf" | ||
| 21 | StarshipConfigTemplate = "configs/shell/starship.toml" | 21 | StarshipConfigTemplate = "configs/shell/starship.toml" | ||
| 22 | - | ShellConfigTemplate = "configs/shell/shell" | 22 | + | ShellConfigTemplate = "configs/shell/shell" |
| 23 | - | ShellInitTemplate = "configs/shell/init" | 23 | + | ShellInitTemplate = "configs/shell/init" |
| 24 | - | ShellAliasesTemplate = "configs/shell/aliases" | 24 | + | ShellAliasesTemplate = "configs/shell/aliases" |
| 25 | - | ShellEnvsTemplate = "configs/shell/envs" | 25 | + | ShellEnvsTemplate = "configs/shell/envs" |
| 26 | - | ShellRcTemplate = "configs/shell/rc" | 26 | + | ShellRcTemplate = "configs/shell/rc" |
| 27 | - | BashrcTemplate = "configs/shell/bashrc" | 27 | + | BashrcTemplate = "configs/shell/bashrc" |
| 28 | ) | 28 | ) | ||
| 29 | 29 | ||||
| 30 | // Encryption types | 30 | // Encryption types | ||
| @@ -36,7 +36,7 @@ const ( | |||||
| 36 | 36 | ||||
| 37 | // Bootloader types | 37 | // Bootloader types | ||
| 38 | const ( | 38 | const ( | ||
| 39 | - | BootloaderLimine = "limine" | 39 | + | BootloaderLimine = "limine" |
| 40 | BootloaderSystemdBoot = "systemd-boot" | 40 | BootloaderSystemdBoot = "systemd-boot" | ||
| 41 | ) | 41 | ) | ||
| 42 | 42 | ||||
| @@ -49,7 +49,6 @@ const ( | |||||
| 49 | KernelLinuxCachyOS = "linux-cachyos" | 49 | KernelLinuxCachyOS = "linux-cachyos" | ||
| 50 | ) | 50 | ) | ||
| 51 | 51 | ||||
| 52 | - | ||||
| 53 | // System paths | 52 | // System paths | ||
| 54 | const ( | 53 | const ( | ||
| 55 | PathMnt = "/mnt" | 54 | PathMnt = "/mnt" | ||
| @@ -89,10 +88,10 @@ const ( | |||||
| 89 | 88 | ||||
| 90 | // Locale defaults | 89 | // Locale defaults | ||
| 91 | const ( | 90 | const ( | ||
| 92 | - | LocaleDefault = "en_US.UTF-8" | 91 | + | LocaleDefault = "en_US.UTF-8" |
| 93 | - | LocaleDefaultGen = "en_US.UTF-8 UTF-8" | 92 | + | LocaleDefaultGen = "en_US.UTF-8 UTF-8" |
| 94 | - | TimezoneDefault = "" | 93 | + | TimezoneDefault = "" |
| 95 | - | KeymapDefault = "us" | 94 | + | KeymapDefault = "us" |
| 96 | ) | 95 | ) | ||
| 97 | 96 | ||||
| 98 | // Zram configuration | 97 | // Zram configuration | ||
| @@ -116,18 +115,19 @@ const ( | |||||
| 116 | 115 | ||||
| 117 | // Boot paths | 116 | // Boot paths | ||
| 118 | const ( | 117 | const ( | ||
| 119 | - | PathMntBoot = "/mnt/boot" | 118 | + | PathMntBoot = "/mnt/boot" |
| 120 | - | PathMntBootEFI = "/mnt/boot/EFI" | 119 | + | PathMntBootEFI = "/mnt/boot/EFI" |
| 121 | - | PathMntBootEFILimine = "/mnt/boot/EFI/limine" | 120 | + | PathMntBootEFILimine = "/mnt/boot/EFI/limine" |
| 122 | - | PathMntEtcMkinitcpio = "/mnt/etc/mkinitcpio.conf" | 121 | + | PathMntBootLimineConf = "/mnt/boot/limine.conf" |
| 123 | - | PathUsrShareLimine = "/mnt/usr/share/limine" | 122 | + | PathMntEtcMkinitcpio = "/mnt/etc/mkinitcpio.conf" |
| 124 | - | FileLimineBootloader = "BOOTX64.EFI" | 123 | + | PathUsrShareLimine = "/mnt/usr/share/limine" |
| 125 | - | FileLimineConfig = "limine.conf" | 124 | + | FileLimineBootloader = "BOOTX64.EFI" |
| 125 | + | FileLimineConfig = "limine.conf" | |||
| 126 | ) | 126 | ) | ||
| 127 | 127 | ||||
| 128 | // Mkinitcpio hooks | 128 | // Mkinitcpio hooks | ||
| 129 | const ( | 129 | const ( | ||
| 130 | - | MkinitcpioHooksPlymouth = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth filesystems fsck)" | 130 | + | MkinitcpioHooksPlymouth = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth filesystems fsck)" |
| 131 | MkinitcpioHooksEncrypted = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth encrypt filesystems fsck)" | 131 | MkinitcpioHooksEncrypted = "HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block plymouth encrypt filesystems fsck)" | ||
| 132 | ) | 132 | ) | ||
| 133 | 133 | ||||
| @@ -155,16 +155,15 @@ const ( | |||||
| 155 | PathMntEtcPacmanConf = "/mnt/etc/pacman.conf" | 155 | PathMntEtcPacmanConf = "/mnt/etc/pacman.conf" | ||
| 156 | ) | 156 | ) | ||
| 157 | 157 | ||||
| 158 | - | ||||
| 159 | // PostInstall paths | 158 | // PostInstall paths | ||
| 160 | const ( | 159 | const ( | ||
| 161 | - | PathMntBootLogo = "/mnt/boot/arch-logo.png" | 160 | + | PathMntBootLogo = "/mnt/boot/arch-logo.png" |
| 162 | - | PathMntPlymouthThemes = "/mnt/usr/share/plymouth/themes" | 161 | + | PathMntPlymouthThemes = "/mnt/usr/share/plymouth/themes" |
| 163 | - | PathMntEtcDefaultLimine = "/mnt/etc/default/limine" | 162 | + | PathMntEtcDefaultLimine = "/mnt/etc/default/limine" |
| 164 | - | PathMntEtcPacmanDHooks = "/mnt/etc/pacman.d/hooks" | 163 | + | PathMntEtcPacmanDHooks = "/mnt/etc/pacman.d/hooks" |
| 165 | - | PathBootEFILimineConf = "/boot/EFI/limine/limine.conf" | 164 | + | PathBootLimineConf = "/boot/limine.conf" |
| 166 | - | ArchLogoURL = "assets/Arch_Linux__Crystal__icon.png" | 165 | + | ArchLogoURL = "assets/Arch_Linux__Crystal__icon.png" |
| 167 | - | PlymouthThemeName = "archup" | 166 | + | PlymouthThemeName = "archup" |
| 168 | ) | 167 | ) | ||
| 169 | 168 | ||||
| 170 | // Plymouth files | 169 | // Plymouth files | ||
| @@ -203,16 +202,16 @@ const PostBootServiceTemplate = "install/mandatory/post-boot/archup-first-boot.s | |||||
| 203 | // This mirrors the shell script's config format for compatibility | 202 | // This mirrors the shell script's config format for compatibility | ||
| 204 | type Config struct { | 203 | type Config struct { | ||
| 205 | // Preflight | 204 | // Preflight | ||
| 206 | - | Hostname string | 205 | + | Hostname string |
| 207 | - | Username string | 206 | + | Username string |
| 208 | - | UserPassword string | 207 | + | UserPassword string |
| 209 | - | RootPassword string | 208 | + | RootPassword string |
| 210 | - | Email string // Optional, for git and SSH configuration | 209 | + | Email string // Optional, for git and SSH configuration |
| 211 | - | Keymap string | 210 | + | Keymap string |
| 212 | - | Timezone string | 211 | + | Timezone string |
| 213 | - | Locale string | 212 | + | Locale string |
| 214 | - | Bootloader string // "limine" or "systemd-boot" | 213 | + | Bootloader string // "limine" or "systemd-boot" |
| 215 | - | EncryptionType string // "none", "luks", or "luks-lvm" | 214 | + | EncryptionType string // "none", "luks", or "luks-lvm" |
| 216 | EncryptPassword string // Separate encryption password if different from user password | 215 | EncryptPassword string // Separate encryption password if different from user password | ||
| 217 | 216 | ||||
| 218 | // Form-only fields (not persisted) | 217 | // Form-only fields (not persisted) | ||
| @@ -220,18 +219,18 @@ type Config struct { | |||||
| 220 | UseSamePasswordForEncryption bool // Checkbox state for using same password for encryption | 219 | UseSamePasswordForEncryption bool // Checkbox state for using same password for encryption | ||
| 221 | 220 | ||||
| 222 | // Partitioning | 221 | // Partitioning | ||
| 223 | - | TargetDisk string | 222 | + | TargetDisk string |
| 224 | - | BootPartition string | 223 | + | BootPartition string |
| 225 | - | RootPartition string | 224 | + | RootPartition string |
| 226 | - | SwapPartition string | 225 | + | SwapPartition string |
| 227 | - | EFIPartition string | 226 | + | EFIPartition string |
| 228 | - | CryptDevice string // /dev/mapper/cryptroot if encrypted | 227 | + | CryptDevice string // /dev/mapper/cryptroot if encrypted |
| 229 | 228 | ||||
| 230 | // Base | 229 | // Base | ||
| 231 | - | KernelChoice string // "linux", "linux-zen", "linux-lts", "linux-hardened" | 230 | + | KernelChoice string // "linux", "linux-zen", "linux-lts", "linux-hardened" |
| 232 | - | Microcode string // "intel-ucode" or "amd-ucode" | 231 | + | Microcode string // "intel-ucode" or "amd-ucode" |
| 233 | - | CPUVendor string // "Intel", "AMD", or "Unknown" | 232 | + | CPUVendor string // "Intel", "AMD", or "Unknown" |
| 234 | - | AMDPState string // "active", "passive", "guided", or empty | 233 | + | AMDPState string // "active", "passive", "guided", or empty |
| 235 | 234 | ||||
| 236 | // Config | 235 | // Config | ||
| 237 | NetworkManager string // "NetworkManager" by default | 236 | NetworkManager string // "NetworkManager" by default | ||
| @@ -242,11 +241,11 @@ type Config struct { | |||||
| 242 | EnableChaotic bool | 241 | EnableChaotic bool | ||
| 243 | 242 | ||||
| 244 | // Paths | 243 | // Paths | ||
| 245 | - | ConfigPath string | 244 | + | ConfigPath string |
| 246 | - | LogPath string | 245 | + | LogPath string |
| 247 | - | InstallPath string // ~/.local/share/archup/install | 246 | + | InstallPath string // ~/.local/share/archup/install |
| 248 | - | RepoURL string | 247 | + | RepoURL string |
| 249 | - | RawURL string | 248 | + | RawURL string |
| 250 | } | 249 | } | ||
| 251 | 250 | ||||
| 252 | // NewConfig creates a new Config with sensible defaults | 251 | // NewConfig creates a new Config with sensible defaults | ||
M internal/domain/bootloader/bootloader.go +4 -4
| @@ -25,10 +25,10 @@ func (b BootloaderType) String() string { | |||
| 25 | 25 | ||
| 26 | 26 | // Bootloader is an immutable value object representing bootloader configuration | |
| 27 | 27 | type Bootloader struct { | |
| 28 | - | bootType BootloaderType | |
| 29 | - | timeout int // seconds | |
| 30 | - | branding string | |
| 31 | - | efiPath string | |
| 28 | + | bootType BootloaderType | |
| 29 | + | timeout int // seconds | |
| 30 | + | branding string | |
| 31 | + | efiPath string | |
| 32 | 32 | } | |
| 33 | 33 | ||
| 34 | 34 | // NewBootloader creates a new Bootloader value object with validation | |
| @@ -25,10 +25,10 @@ func (b BootloaderType) String() string { | |||||
| 25 | 25 | ||||
| 26 | // Bootloader is an immutable value object representing bootloader configuration | 26 | // Bootloader is an immutable value object representing bootloader configuration | ||
| 27 | type Bootloader struct { | 27 | type Bootloader struct { | ||
| 28 | - | bootType BootloaderType | 28 | + | bootType BootloaderType |
| 29 | - | timeout int // seconds | 29 | + | timeout int // seconds |
| 30 | - | branding string | 30 | + | branding string |
| 31 | - | efiPath string | 31 | + | efiPath string |
| 32 | } | 32 | } | ||
| 33 | 33 | ||||
| 34 | // NewBootloader creates a new Bootloader value object with validation | 34 | // NewBootloader creates a new Bootloader value object with validation | ||
M internal/domain/bootloader/bootloader_test.go +2 -2
| @@ -26,8 +26,8 @@ func TestNewBootloader_Valid(t *testing.T) { | |||
| 26 | 26 | ||
| 27 | 27 | func TestNewBootloader_InvalidTimeout(t *testing.T) { | |
| 28 | 28 | tests := []struct { | |
| 29 | - | name string | |
| 30 | - | timeout int | |
| 29 | + | name string | |
| 30 | + | timeout int | |
| 31 | 31 | shouldErr bool | |
| 32 | 32 | }{ | |
| 33 | 33 | {"negative timeout", -1, true}, | |
| @@ -26,8 +26,8 @@ func TestNewBootloader_Valid(t *testing.T) { | |||||
| 26 | 26 | ||||
| 27 | func TestNewBootloader_InvalidTimeout(t *testing.T) { | 27 | func TestNewBootloader_InvalidTimeout(t *testing.T) { | ||
| 28 | tests := []struct { | 28 | tests := []struct { | ||
| 29 | - | name string | 29 | + | name string |
| 30 | - | timeout int | 30 | + | timeout int |
| 31 | shouldErr bool | 31 | shouldErr bool | ||
| 32 | }{ | 32 | }{ | ||
| 33 | {"negative timeout", -1, true}, | 33 | {"negative timeout", -1, true}, | ||
M internal/domain/disk/disk_test.go +7 -7
| @@ -124,9 +124,9 @@ func TestNewPartition_FAT32NotForRoot(t *testing.T) { | |||
| 124 | 124 | ||
| 125 | 125 | func TestPartition_IsBootPartition(t *testing.T) { | |
| 126 | 126 | tests := []struct { | |
| 127 | - | name string | |
| 128 | - | mount string | |
| 129 | - | isBoot bool | |
| 127 | + | name string | |
| 128 | + | mount string | |
| 129 | + | isBoot bool | |
| 130 | 130 | }{ | |
| 131 | 131 | {"boot partition", "/boot", true}, | |
| 132 | 132 | {"efi boot partition", "/boot/efi", true}, | |
| @@ -146,10 +146,10 @@ func TestPartition_IsBootPartition(t *testing.T) { | |||
| 146 | 146 | ||
| 147 | 147 | func TestPartition_IsEFI(t *testing.T) { | |
| 148 | 148 | tests := []struct { | |
| 149 | - | name string | |
| 150 | - | fs FilesystemType | |
| 151 | - | mount string | |
| 152 | - | isEFI bool | |
| 149 | + | name string | |
| 150 | + | fs FilesystemType | |
| 151 | + | mount string | |
| 152 | + | isEFI bool | |
| 153 | 153 | shouldErr bool | |
| 154 | 154 | }{ | |
| 155 | 155 | {"EFI partition", FilesystemFAT32, "/boot/efi", true, false}, | |
| @@ -124,9 +124,9 @@ func TestNewPartition_FAT32NotForRoot(t *testing.T) { | |||||
| 124 | 124 | ||||
| 125 | func TestPartition_IsBootPartition(t *testing.T) { | 125 | func TestPartition_IsBootPartition(t *testing.T) { | ||
| 126 | tests := []struct { | 126 | tests := []struct { | ||
| 127 | - | name string | 127 | + | name string |
| 128 | - | mount string | 128 | + | mount string |
| 129 | - | isBoot bool | 129 | + | isBoot bool |
| 130 | }{ | 130 | }{ | ||
| 131 | {"boot partition", "/boot", true}, | 131 | {"boot partition", "/boot", true}, | ||
| 132 | {"efi boot partition", "/boot/efi", true}, | 132 | {"efi boot partition", "/boot/efi", true}, | ||
| @@ -146,10 +146,10 @@ func TestPartition_IsBootPartition(t *testing.T) { | |||||
| 146 | 146 | ||||
| 147 | func TestPartition_IsEFI(t *testing.T) { | 147 | func TestPartition_IsEFI(t *testing.T) { | ||
| 148 | tests := []struct { | 148 | tests := []struct { | ||
| 149 | - | name string | 149 | + | name string |
| 150 | - | fs FilesystemType | 150 | + | fs FilesystemType |
| 151 | - | mount string | 151 | + | mount string |
| 152 | - | isEFI bool | 152 | + | isEFI bool |
| 153 | shouldErr bool | 153 | shouldErr bool | ||
| 154 | }{ | 154 | }{ | ||
| 155 | {"EFI partition", FilesystemFAT32, "/boot/efi", true, false}, | 155 | {"EFI partition", FilesystemFAT32, "/boot/efi", true, false}, | ||
M internal/domain/disk/partition.go +3 -3
| @@ -33,10 +33,10 @@ func (f FilesystemType) String() string { | |||
| 33 | 33 | ||
| 34 | 34 | // Partition is an immutable value object representing a disk partition | |
| 35 | 35 | type Partition struct { | |
| 36 | - | device string // e.g., /dev/sda1 | |
| 37 | - | size int64 // Size in megabytes | |
| 36 | + | device string // e.g., /dev/sda1 | |
| 37 | + | size int64 // Size in megabytes | |
| 38 | 38 | filesystem FilesystemType | |
| 39 | - | mountPoint string // e.g., /, /boot, /home | |
| 39 | + | mountPoint string // e.g., /, /boot, /home | |
| 40 | 40 | encrypted bool | |
| 41 | 41 | } | |
| 42 | 42 | ||
| @@ -33,10 +33,10 @@ func (f FilesystemType) String() string { | |||||
| 33 | 33 | ||||
| 34 | // Partition is an immutable value object representing a disk partition | 34 | // Partition is an immutable value object representing a disk partition | ||
| 35 | type Partition struct { | 35 | type Partition struct { | ||
| 36 | - | device string // e.g., /dev/sda1 | 36 | + | device string // e.g., /dev/sda1 |
| 37 | - | size int64 // Size in megabytes | 37 | + | size int64 // Size in megabytes |
| 38 | filesystem FilesystemType | 38 | filesystem FilesystemType | ||
| 39 | - | mountPoint string // e.g., /, /boot, /home | 39 | + | mountPoint string // e.g., /, /boot, /home |
| 40 | encrypted bool | 40 | encrypted bool | ||
| 41 | } | 41 | } | ||
| 42 | 42 | ||||
M internal/domain/installation/events.go +2 -2
| @@ -105,9 +105,9 @@ func (e *PhaseCompletedEvent) EventType() string { | |||
| 105 | 105 | // PhaseFailedEvent represents failure of a phase | |
| 106 | 106 | type PhaseFailedEvent struct { | |
| 107 | 107 | BaseDomainEvent | |
| 108 | - | Phase State | |
| 108 | + | Phase State | |
| 109 | 109 | ErrorMessage string | |
| 110 | - | Recoverable bool | |
| 110 | + | Recoverable bool | |
| 111 | 111 | } | |
| 112 | 112 | ||
| 113 | 113 | func NewPhaseFailedEvent(aggregateID string, phase State, errorMessage string, recoverable bool) *PhaseFailedEvent { | |
| @@ -105,9 +105,9 @@ func (e *PhaseCompletedEvent) EventType() string { | |||||
| 105 | // PhaseFailedEvent represents failure of a phase | 105 | // PhaseFailedEvent represents failure of a phase | ||
| 106 | type PhaseFailedEvent struct { | 106 | type PhaseFailedEvent struct { | ||
| 107 | BaseDomainEvent | 107 | BaseDomainEvent | ||
| 108 | - | Phase State | 108 | + | Phase State |
| 109 | ErrorMessage string | 109 | ErrorMessage string | ||
| 110 | - | Recoverable bool | 110 | + | Recoverable bool |
| 111 | } | 111 | } | ||
| 112 | 112 | ||||
| 113 | func NewPhaseFailedEvent(aggregateID string, phase State, errorMessage string, recoverable bool) *PhaseFailedEvent { | 113 | func NewPhaseFailedEvent(aggregateID string, phase State, errorMessage string, recoverable bool) *PhaseFailedEvent { | ||
M internal/domain/installation/installation.go +5 -5
| @@ -26,8 +26,8 @@ type Installation struct { | |||
| 26 | 26 | encryptionType string | |
| 27 | 27 | ||
| 28 | 28 | // Installation metadata | |
| 29 | - | createdAt time.Time | |
| 30 | - | startedAt *time.Time | |
| 29 | + | createdAt time.Time | |
| 30 | + | startedAt *time.Time | |
| 31 | 31 | completedAt *time.Time | |
| 32 | 32 | ||
| 33 | 33 | // Domain events that have occurred during this installation | |
| @@ -65,9 +65,9 @@ func NewInstallation( | |||
| 65 | 65 | ||
| 66 | 66 | // Validate encryptionType | |
| 67 | 67 | validEncryption := map[string]bool{ | |
| 68 | - | "none": true, | |
| 69 | - | "luks": true, | |
| 70 | - | "luks-lvm": true, | |
| 68 | + | "none": true, | |
| 69 | + | "luks": true, | |
| 70 | + | "luks-lvm": true, | |
| 71 | 71 | } | |
| 72 | 72 | if !validEncryption[encryptionType] { | |
| 73 | 73 | return nil, fmt.Errorf("invalid encryption type: %s", encryptionType) | |
| @@ -26,8 +26,8 @@ type Installation struct { | |||||
| 26 | encryptionType string | 26 | encryptionType string | ||
| 27 | 27 | ||||
| 28 | // Installation metadata | 28 | // Installation metadata | ||
| 29 | - | createdAt time.Time | 29 | + | createdAt time.Time |
| 30 | - | startedAt *time.Time | 30 | + | startedAt *time.Time |
| 31 | completedAt *time.Time | 31 | completedAt *time.Time | ||
| 32 | 32 | ||||
| 33 | // Domain events that have occurred during this installation | 33 | // Domain events that have occurred during this installation | ||
| @@ -65,9 +65,9 @@ func NewInstallation( | |||||
| 65 | 65 | ||||
| 66 | // Validate encryptionType | 66 | // Validate encryptionType | ||
| 67 | validEncryption := map[string]bool{ | 67 | validEncryption := map[string]bool{ | ||
| 68 | - | "none": true, | 68 | + | "none": true, |
| 69 | - | "luks": true, | 69 | + | "luks": true, |
| 70 | - | "luks-lvm": true, | 70 | + | "luks-lvm": true, |
| 71 | } | 71 | } | ||
| 72 | if !validEncryption[encryptionType] { | 72 | if !validEncryption[encryptionType] { | ||
| 73 | return nil, fmt.Errorf("invalid encryption type: %s", encryptionType) | 73 | return nil, fmt.Errorf("invalid encryption type: %s", encryptionType) | ||
M internal/domain/packages/packages_test.go +4 -4
| @@ -159,10 +159,10 @@ func TestNewRepository_Valid(t *testing.T) { | |||
| 159 | 159 | ||
| 160 | 160 | func TestNewRepository_AllCombinations(t *testing.T) { | |
| 161 | 161 | tests := []struct { | |
| 162 | - | name string | |
| 163 | - | multilib bool | |
| 164 | - | chaotic bool | |
| 165 | - | helper AURHelper | |
| 162 | + | name string | |
| 163 | + | multilib bool | |
| 164 | + | chaotic bool | |
| 165 | + | helper AURHelper | |
| 166 | 166 | }{ | |
| 167 | 167 | {"minimal", false, false, AURHelperParu}, | |
| 168 | 168 | {"chaotic only", false, true, AURHelperParu}, | |
| @@ -159,10 +159,10 @@ func TestNewRepository_Valid(t *testing.T) { | |||||
| 159 | 159 | ||||
| 160 | func TestNewRepository_AllCombinations(t *testing.T) { | 160 | func TestNewRepository_AllCombinations(t *testing.T) { | ||
| 161 | tests := []struct { | 161 | tests := []struct { | ||
| 162 | - | name string | 162 | + | name string |
| 163 | - | multilib bool | 163 | + | multilib bool |
| 164 | - | chaotic bool | 164 | + | chaotic bool |
| 165 | - | helper AURHelper | 165 | + | helper AURHelper |
| 166 | }{ | 166 | }{ | ||
| 167 | {"minimal", false, false, AURHelperParu}, | 167 | {"minimal", false, false, AURHelperParu}, | ||
| 168 | {"chaotic only", false, true, AURHelperParu}, | 168 | {"chaotic only", false, true, AURHelperParu}, | ||
M internal/domain/system/system_test.go +4 -4
| @@ -453,9 +453,9 @@ func TestValidateArchLinux(t *testing.T) { | |||
| 453 | 453 | ctx := context.Background() | |
| 454 | 454 | ||
| 455 | 455 | tests := []struct { | |
| 456 | - | name string | |
| 456 | + | name string | |
| 457 | 457 | fileExists bool | |
| 458 | - | shouldErr bool | |
| 458 | + | shouldErr bool | |
| 459 | 459 | }{ | |
| 460 | 460 | {"arch-release exists", true, false}, | |
| 461 | 461 | {"arch-release missing", false, true}, | |
| @@ -592,9 +592,9 @@ func TestValidateUEFIBoot(t *testing.T) { | |||
| 592 | 592 | ctx := context.Background() | |
| 593 | 593 | ||
| 594 | 594 | tests := []struct { | |
| 595 | - | name string | |
| 595 | + | name string | |
| 596 | 596 | efivarsExists bool | |
| 597 | - | shouldErr bool | |
| 597 | + | shouldErr bool | |
| 598 | 598 | }{ | |
| 599 | 599 | {"efivars exists", true, false}, | |
| 600 | 600 | {"efivars missing", false, true}, | |
| @@ -453,9 +453,9 @@ func TestValidateArchLinux(t *testing.T) { | |||||
| 453 | ctx := context.Background() | 453 | ctx := context.Background() | ||
| 454 | 454 | ||||
| 455 | tests := []struct { | 455 | tests := []struct { | ||
| 456 | - | name string | 456 | + | name string |
| 457 | fileExists bool | 457 | fileExists bool | ||
| 458 | - | shouldErr bool | 458 | + | shouldErr bool |
| 459 | }{ | 459 | }{ | ||
| 460 | {"arch-release exists", true, false}, | 460 | {"arch-release exists", true, false}, | ||
| 461 | {"arch-release missing", false, true}, | 461 | {"arch-release missing", false, true}, | ||
| @@ -592,9 +592,9 @@ func TestValidateUEFIBoot(t *testing.T) { | |||||
| 592 | ctx := context.Background() | 592 | ctx := context.Background() | ||
| 593 | 593 | ||||
| 594 | tests := []struct { | 594 | tests := []struct { | ||
| 595 | - | name string | 595 | + | name string |
| 596 | efivarsExists bool | 596 | efivarsExists bool | ||
| 597 | - | shouldErr bool | 597 | + | shouldErr bool |
| 598 | }{ | 598 | }{ | ||
| 599 | {"efivars exists", true, false}, | 599 | {"efivars exists", true, false}, | ||
| 600 | {"efivars missing", false, true}, | 600 | {"efivars missing", false, true}, | ||
M internal/domain/system/validation.go +15 -15
| @@ -82,17 +82,17 @@ func (r *SystemValidationRules) SanitizeHostname(hostname string) string { | |||
| 82 | 82 | func (r *SystemValidationRules) SuggestedLocaleForTimezone(timezone string) string { | |
| 83 | 83 | // Common timezone -> locale pairings (not enforced, just suggestions) | |
| 84 | 84 | suggestions := map[string]string{ | |
| 85 | - | "America/New_York": "en_US.UTF-8", | |
| 86 | - | "America/Chicago": "en_US.UTF-8", | |
| 87 | - | "America/Denver": "en_US.UTF-8", | |
| 88 | - | "America/Los_Angeles": "en_US.UTF-8", | |
| 89 | - | "Europe/London": "en_GB.UTF-8", | |
| 90 | - | "Europe/Paris": "fr_FR.UTF-8", | |
| 91 | - | "Europe/Berlin": "de_DE.UTF-8", | |
| 92 | - | "Europe/Madrid": "es_ES.UTF-8", | |
| 93 | - | "Asia/Tokyo": "ja_JP.UTF-8", | |
| 94 | - | "Australia/Sydney": "en_AU.UTF-8", | |
| 95 | - | "UTC": "en_US.UTF-8", | |
| 85 | + | "America/New_York": "en_US.UTF-8", | |
| 86 | + | "America/Chicago": "en_US.UTF-8", | |
| 87 | + | "America/Denver": "en_US.UTF-8", | |
| 88 | + | "America/Los_Angeles": "en_US.UTF-8", | |
| 89 | + | "Europe/London": "en_GB.UTF-8", | |
| 90 | + | "Europe/Paris": "fr_FR.UTF-8", | |
| 91 | + | "Europe/Berlin": "de_DE.UTF-8", | |
| 92 | + | "Europe/Madrid": "es_ES.UTF-8", | |
| 93 | + | "Asia/Tokyo": "ja_JP.UTF-8", | |
| 94 | + | "Australia/Sydney": "en_AU.UTF-8", | |
| 95 | + | "UTC": "en_US.UTF-8", | |
| 96 | 96 | } | |
| 97 | 97 | ||
| 98 | 98 | if locale, exists := suggestions[timezone]; exists { | |
| @@ -127,10 +127,10 @@ func (r *SystemValidationRules) SuggestedKeymapForLocale(locale string) string { | |||
| 127 | 127 | func (r *SystemValidationRules) IsValidLocaleVariant(locale string) bool { | |
| 128 | 128 | // Common valid variants | |
| 129 | 129 | validVariants := map[string]bool{ | |
| 130 | - | "UTF-8": true, | |
| 131 | - | "utf8": true, | |
| 132 | - | "UTF8": true, | |
| 133 | - | "ISO8859-1": true, | |
| 130 | + | "UTF-8": true, | |
| 131 | + | "utf8": true, | |
| 132 | + | "UTF8": true, | |
| 133 | + | "ISO8859-1": true, | |
| 134 | 134 | "ISO-8859-1": true, | |
| 135 | 135 | } | |
| 136 | 136 | ||
| @@ -82,17 +82,17 @@ func (r *SystemValidationRules) SanitizeHostname(hostname string) string { | |||||
| 82 | func (r *SystemValidationRules) SuggestedLocaleForTimezone(timezone string) string { | 82 | func (r *SystemValidationRules) SuggestedLocaleForTimezone(timezone string) string { | ||
| 83 | // Common timezone -> locale pairings (not enforced, just suggestions) | 83 | // Common timezone -> locale pairings (not enforced, just suggestions) | ||
| 84 | suggestions := map[string]string{ | 84 | suggestions := map[string]string{ | ||
| 85 | - | "America/New_York": "en_US.UTF-8", | 85 | + | "America/New_York": "en_US.UTF-8", |
| 86 | - | "America/Chicago": "en_US.UTF-8", | 86 | + | "America/Chicago": "en_US.UTF-8", |
| 87 | - | "America/Denver": "en_US.UTF-8", | 87 | + | "America/Denver": "en_US.UTF-8", |
| 88 | - | "America/Los_Angeles": "en_US.UTF-8", | 88 | + | "America/Los_Angeles": "en_US.UTF-8", |
| 89 | - | "Europe/London": "en_GB.UTF-8", | 89 | + | "Europe/London": "en_GB.UTF-8", |
| 90 | - | "Europe/Paris": "fr_FR.UTF-8", | 90 | + | "Europe/Paris": "fr_FR.UTF-8", |
| 91 | - | "Europe/Berlin": "de_DE.UTF-8", | 91 | + | "Europe/Berlin": "de_DE.UTF-8", |
| 92 | - | "Europe/Madrid": "es_ES.UTF-8", | 92 | + | "Europe/Madrid": "es_ES.UTF-8", |
| 93 | - | "Asia/Tokyo": "ja_JP.UTF-8", | 93 | + | "Asia/Tokyo": "ja_JP.UTF-8", |
| 94 | - | "Australia/Sydney": "en_AU.UTF-8", | 94 | + | "Australia/Sydney": "en_AU.UTF-8", |
| 95 | - | "UTC": "en_US.UTF-8", | 95 | + | "UTC": "en_US.UTF-8", |
| 96 | } | 96 | } | ||
| 97 | 97 | ||||
| 98 | if locale, exists := suggestions[timezone]; exists { | 98 | if locale, exists := suggestions[timezone]; exists { | ||
| @@ -127,10 +127,10 @@ func (r *SystemValidationRules) SuggestedKeymapForLocale(locale string) string { | |||||
| 127 | func (r *SystemValidationRules) IsValidLocaleVariant(locale string) bool { | 127 | func (r *SystemValidationRules) IsValidLocaleVariant(locale string) bool { | ||
| 128 | // Common valid variants | 128 | // Common valid variants | ||
| 129 | validVariants := map[string]bool{ | 129 | validVariants := map[string]bool{ | ||
| 130 | - | "UTF-8": true, | 130 | + | "UTF-8": true, |
| 131 | - | "utf8": true, | 131 | + | "utf8": true, |
| 132 | - | "UTF8": true, | 132 | + | "UTF8": true, |
| 133 | - | "ISO8859-1": true, | 133 | + | "ISO8859-1": true, |
| 134 | "ISO-8859-1": true, | 134 | "ISO-8859-1": true, | ||
| 135 | } | 135 | } | ||
| 136 | 136 | ||||
M internal/domain/user/user.go +5 -5
| @@ -133,11 +133,11 @@ func ValidateShell(shell string) error { | |||
| 133 | 133 | ||
| 134 | 134 | // Common valid shells | |
| 135 | 135 | validShells := map[string]bool{ | |
| 136 | - | "/bin/bash": true, | |
| 137 | - | "/bin/sh": true, | |
| 138 | - | "/bin/zsh": true, | |
| 139 | - | "/bin/fish": true, | |
| 140 | - | "/usr/bin/zsh": true, | |
| 136 | + | "/bin/bash": true, | |
| 137 | + | "/bin/sh": true, | |
| 138 | + | "/bin/zsh": true, | |
| 139 | + | "/bin/fish": true, | |
| 140 | + | "/usr/bin/zsh": true, | |
| 141 | 141 | "/usr/bin/fish": true, | |
| 142 | 142 | } | |
| 143 | 143 | ||
| @@ -133,11 +133,11 @@ func ValidateShell(shell string) error { | |||||
| 133 | 133 | ||||
| 134 | // Common valid shells | 134 | // Common valid shells | ||
| 135 | validShells := map[string]bool{ | 135 | validShells := map[string]bool{ | ||
| 136 | - | "/bin/bash": true, | 136 | + | "/bin/bash": true, |
| 137 | - | "/bin/sh": true, | 137 | + | "/bin/sh": true, |
| 138 | - | "/bin/zsh": true, | 138 | + | "/bin/zsh": true, |
| 139 | - | "/bin/fish": true, | 139 | + | "/bin/fish": true, |
| 140 | - | "/usr/bin/zsh": true, | 140 | + | "/usr/bin/zsh": true, |
| 141 | "/usr/bin/fish": true, | 141 | "/usr/bin/fish": true, | ||
| 142 | } | 142 | } | ||
| 143 | 143 | ||||
M internal/infrastructure/executor/script.go +2 -2
| @@ -12,8 +12,8 @@ import ( | |||
| 12 | 12 | ||
| 13 | 13 | // ScriptExecutor implements the ScriptExecutor port for shell scripts | |
| 14 | 14 | type ScriptExecutor struct { | |
| 15 | - | fs ports.FileSystem | |
| 16 | - | cmdExec ports.CommandExecutor | |
| 15 | + | fs ports.FileSystem | |
| 16 | + | cmdExec ports.CommandExecutor | |
| 17 | 17 | scriptDir string | |
| 18 | 18 | } | |
| 19 | 19 | ||
| @@ -12,8 +12,8 @@ import ( | |||||
| 12 | 12 | ||||
| 13 | // ScriptExecutor implements the ScriptExecutor port for shell scripts | 13 | // ScriptExecutor implements the ScriptExecutor port for shell scripts | ||
| 14 | type ScriptExecutor struct { | 14 | type ScriptExecutor struct { | ||
| 15 | - | fs ports.FileSystem | 15 | + | fs ports.FileSystem |
| 16 | - | cmdExec ports.CommandExecutor | 16 | + | cmdExec ports.CommandExecutor |
| 17 | scriptDir string | 17 | scriptDir string | ||
| 18 | } | 18 | } | ||
| 19 | 19 | ||||
M internal/interfaces/tui/app.go +6 -6
| @@ -3,12 +3,12 @@ package tui | |||
| 3 | 3 | import ( | |
| 4 | 4 | "context" | |
| 5 | 5 | ||
| 6 | - | tea "github.com/charmbracelet/bubbletea" | |
| 7 | 6 | "github.com/bnema/archup/internal/application/services" | |
| 8 | 7 | "github.com/bnema/archup/internal/domain/ports" | |
| 9 | 8 | "github.com/bnema/archup/internal/interfaces/tui/handlers" | |
| 10 | 9 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 11 | 10 | "github.com/bnema/archup/internal/interfaces/tui/views" | |
| 11 | + | tea "github.com/charmbracelet/bubbletea" | |
| 12 | 12 | ) | |
| 13 | 13 | ||
| 14 | 14 | // App is the main TUI application coordinator | |
| @@ -37,11 +37,11 @@ type App struct { | |||
| 37 | 37 | type Screen string | |
| 38 | 38 | ||
| 39 | 39 | const ( | |
| 40 | - | ScreenForm Screen = "form" | |
| 41 | - | ScreenInstalling Screen = "installing" | |
| 42 | - | ScreenProgress Screen = "progress" | |
| 43 | - | ScreenSummary Screen = "summary" | |
| 44 | - | ScreenError Screen = "error" | |
| 40 | + | ScreenForm Screen = "form" | |
| 41 | + | ScreenInstalling Screen = "installing" | |
| 42 | + | ScreenProgress Screen = "progress" | |
| 43 | + | ScreenSummary Screen = "summary" | |
| 44 | + | ScreenError Screen = "error" | |
| 45 | 45 | ) | |
| 46 | 46 | ||
| 47 | 47 | // NewApp creates a new TUI application | |
| @@ -3,12 +3,12 @@ package tui | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "context" | 4 | "context" | ||
| 5 | 5 | ||||
| 6 | - | tea "github.com/charmbracelet/bubbletea" | |||
| 7 | "github.com/bnema/archup/internal/application/services" | 6 | "github.com/bnema/archup/internal/application/services" | ||
| 8 | "github.com/bnema/archup/internal/domain/ports" | 7 | "github.com/bnema/archup/internal/domain/ports" | ||
| 9 | "github.com/bnema/archup/internal/interfaces/tui/handlers" | 8 | "github.com/bnema/archup/internal/interfaces/tui/handlers" | ||
| 10 | "github.com/bnema/archup/internal/interfaces/tui/models" | 9 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 11 | "github.com/bnema/archup/internal/interfaces/tui/views" | 10 | "github.com/bnema/archup/internal/interfaces/tui/views" | ||
| 11 | + | tea "github.com/charmbracelet/bubbletea" | |||
| 12 | ) | 12 | ) | ||
| 13 | 13 | ||||
| 14 | // App is the main TUI application coordinator | 14 | // App is the main TUI application coordinator | ||
| @@ -37,11 +37,11 @@ type App struct { | |||||
| 37 | type Screen string | 37 | type Screen string | ||
| 38 | 38 | ||||
| 39 | const ( | 39 | const ( | ||
| 40 | - | ScreenForm Screen = "form" | 40 | + | ScreenForm Screen = "form" |
| 41 | - | ScreenInstalling Screen = "installing" | 41 | + | ScreenInstalling Screen = "installing" |
| 42 | - | ScreenProgress Screen = "progress" | 42 | + | ScreenProgress Screen = "progress" |
| 43 | - | ScreenSummary Screen = "summary" | 43 | + | ScreenSummary Screen = "summary" |
| 44 | - | ScreenError Screen = "error" | 44 | + | ScreenError Screen = "error" |
| 45 | ) | 45 | ) | ||
| 46 | 46 | ||||
| 47 | // NewApp creates a new TUI application | 47 | // NewApp creates a new TUI application | ||
M internal/interfaces/tui/factory.go +0 -1
| @@ -16,4 +16,3 @@ func NewInstallationModel() InstallationModel { | |||
| 16 | 16 | func NewProgressModel() ProgressModel { | |
| 17 | 17 | return models.NewProgressModel() | |
| 18 | 18 | } | |
| 19 | - | ||
| @@ -16,4 +16,3 @@ func NewInstallationModel() InstallationModel { | |||||
| 16 | func NewProgressModel() ProgressModel { | 16 | func NewProgressModel() ProgressModel { | ||
| 17 | return models.NewProgressModel() | 17 | return models.NewProgressModel() | ||
| 18 | } | 18 | } | ||
| 19 | - | ||||
M internal/interfaces/tui/handlers/form_handler.go +1 -1
| @@ -1,8 +1,8 @@ | |||
| 1 | 1 | package handlers | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | - | tea "github.com/charmbracelet/bubbletea" | |
| 5 | 4 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 5 | + | tea "github.com/charmbracelet/bubbletea" | |
| 6 | 6 | ) | |
| 7 | 7 | ||
| 8 | 8 | // HandleFormUpdate processes form input and updates the form model | |
| @@ -1,8 +1,8 @@ | |||||
| 1 | package handlers | 1 | package handlers | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | - | tea "github.com/charmbracelet/bubbletea" | |||
| 5 | "github.com/bnema/archup/internal/interfaces/tui/models" | 4 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 5 | + | tea "github.com/charmbracelet/bubbletea" | |||
| 6 | ) | 6 | ) | ||
| 7 | 7 | ||||
| 8 | // HandleFormUpdate processes form input and updates the form model | 8 | // HandleFormUpdate processes form input and updates the form model | ||
M internal/interfaces/tui/handlers/form_handler_test.go +1 -1
| @@ -3,8 +3,8 @@ package handlers | |||
| 3 | 3 | import ( | |
| 4 | 4 | "testing" | |
| 5 | 5 | ||
| 6 | - | tea "github.com/charmbracelet/bubbletea" | |
| 7 | 6 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 7 | + | tea "github.com/charmbracelet/bubbletea" | |
| 8 | 8 | ) | |
| 9 | 9 | ||
| 10 | 10 | func TestHandleFormUpdate_Navigation(t *testing.T) { | |
| @@ -3,8 +3,8 @@ package handlers | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "testing" | 4 | "testing" | ||
| 5 | 5 | ||||
| 6 | - | tea "github.com/charmbracelet/bubbletea" | |||
| 7 | "github.com/bnema/archup/internal/interfaces/tui/models" | 6 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 7 | + | tea "github.com/charmbracelet/bubbletea" | |||
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
| 10 | func TestHandleFormUpdate_Navigation(t *testing.T) { | 10 | func TestHandleFormUpdate_Navigation(t *testing.T) { | ||
M internal/interfaces/tui/handlers/install_handler.go +1 -1
| @@ -1,9 +1,9 @@ | |||
| 1 | 1 | package handlers | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | - | tea "github.com/charmbracelet/bubbletea" | |
| 5 | 4 | "github.com/bnema/archup/internal/application/dto" | |
| 6 | 5 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 6 | + | tea "github.com/charmbracelet/bubbletea" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | // NOTE: This package uses AppContext interface to avoid importing parent tui package | |
| @@ -1,9 +1,9 @@ | |||||
| 1 | package handlers | 1 | package handlers | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | - | tea "github.com/charmbracelet/bubbletea" | |||
| 5 | "github.com/bnema/archup/internal/application/dto" | 4 | "github.com/bnema/archup/internal/application/dto" | ||
| 6 | "github.com/bnema/archup/internal/interfaces/tui/models" | 5 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 6 | + | tea "github.com/charmbracelet/bubbletea" | |||
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | // NOTE: This package uses AppContext interface to avoid importing parent tui package | 9 | // NOTE: This package uses AppContext interface to avoid importing parent tui package | ||
M internal/interfaces/tui/interfaces.go +1 -1
| @@ -1,9 +1,9 @@ | |||
| 1 | 1 | package tui | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | - | tea "github.com/charmbracelet/bubbletea" | |
| 5 | 4 | "github.com/bnema/archup/internal/application/dto" | |
| 6 | 5 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 6 | + | tea "github.com/charmbracelet/bubbletea" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | // FormModel manages form state for user input | |
| @@ -1,9 +1,9 @@ | |||||
| 1 | package tui | 1 | package tui | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | - | tea "github.com/charmbracelet/bubbletea" | |||
| 5 | "github.com/bnema/archup/internal/application/dto" | 4 | "github.com/bnema/archup/internal/application/dto" | ||
| 6 | "github.com/bnema/archup/internal/interfaces/tui/models" | 5 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 6 | + | tea "github.com/charmbracelet/bubbletea" | |||
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | // FormModel manages form state for user input | 9 | // FormModel manages form state for user input | ||
M internal/interfaces/tui/models/form.go +8 -8
| @@ -41,14 +41,14 @@ type FormModelImpl struct { | |||
| 41 | 41 | BaseModel | |
| 42 | 42 | ||
| 43 | 43 | // Form fields | |
| 44 | - | hostname textinput.Model | |
| 45 | - | username textinput.Model | |
| 46 | - | userPassword textinput.Model | |
| 47 | - | rootPassword textinput.Model | |
| 48 | - | targetDisk textinput.Model | |
| 49 | - | timezone textinput.Model | |
| 50 | - | locale textinput.Model | |
| 51 | - | keymap textinput.Model | |
| 44 | + | hostname textinput.Model | |
| 45 | + | username textinput.Model | |
| 46 | + | userPassword textinput.Model | |
| 47 | + | rootPassword textinput.Model | |
| 48 | + | targetDisk textinput.Model | |
| 49 | + | timezone textinput.Model | |
| 50 | + | locale textinput.Model | |
| 51 | + | keymap textinput.Model | |
| 52 | 52 | ||
| 53 | 53 | // UI state | |
| 54 | 54 | focusIndex int | |
| @@ -41,14 +41,14 @@ type FormModelImpl struct { | |||||
| 41 | BaseModel | 41 | BaseModel | ||
| 42 | 42 | ||||
| 43 | // Form fields | 43 | // Form fields | ||
| 44 | - | hostname textinput.Model | 44 | + | hostname textinput.Model |
| 45 | - | username textinput.Model | 45 | + | username textinput.Model |
| 46 | - | userPassword textinput.Model | 46 | + | userPassword textinput.Model |
| 47 | - | rootPassword textinput.Model | 47 | + | rootPassword textinput.Model |
| 48 | - | targetDisk textinput.Model | 48 | + | targetDisk textinput.Model |
| 49 | - | timezone textinput.Model | 49 | + | timezone textinput.Model |
| 50 | - | locale textinput.Model | 50 | + | locale textinput.Model |
| 51 | - | keymap textinput.Model | 51 | + | keymap textinput.Model |
| 52 | 52 | ||||
| 53 | // UI state | 53 | // UI state | ||
| 54 | focusIndex int | 54 | focusIndex int | ||
M internal/interfaces/tui/models/installation.go +3 -3
| @@ -5,17 +5,17 @@ import ( | |||
| 5 | 5 | "strings" | |
| 6 | 6 | "time" | |
| 7 | 7 | ||
| 8 | + | "github.com/bnema/archup/internal/application/dto" | |
| 8 | 9 | tea "github.com/charmbracelet/bubbletea" | |
| 9 | 10 | "github.com/charmbracelet/lipgloss" | |
| 10 | - | "github.com/bnema/archup/internal/application/dto" | |
| 11 | 11 | ) | |
| 12 | 12 | ||
| 13 | 13 | // InstallationModelImpl implements InstallationModel interface | |
| 14 | 14 | type InstallationModelImpl struct { | |
| 15 | 15 | BaseModel | |
| 16 | 16 | ||
| 17 | - | status *dto.InstallationStatus | |
| 18 | - | err string | |
| 17 | + | status *dto.InstallationStatus | |
| 18 | + | err string | |
| 19 | 19 | complete bool | |
| 20 | 20 | } | |
| 21 | 21 | ||
| @@ -5,17 +5,17 @@ import ( | |||||
| 5 | "strings" | 5 | "strings" | ||
| 6 | "time" | 6 | "time" | ||
| 7 | 7 | ||||
| 8 | + | "github.com/bnema/archup/internal/application/dto" | |||
| 8 | tea "github.com/charmbracelet/bubbletea" | 9 | tea "github.com/charmbracelet/bubbletea" | ||
| 9 | "github.com/charmbracelet/lipgloss" | 10 | "github.com/charmbracelet/lipgloss" | ||
| 10 | - | "github.com/bnema/archup/internal/application/dto" | |||
| 11 | ) | 11 | ) | ||
| 12 | 12 | ||||
| 13 | // InstallationModelImpl implements InstallationModel interface | 13 | // InstallationModelImpl implements InstallationModel interface | ||
| 14 | type InstallationModelImpl struct { | 14 | type InstallationModelImpl struct { | ||
| 15 | BaseModel | 15 | BaseModel | ||
| 16 | 16 | ||||
| 17 | - | status *dto.InstallationStatus | 17 | + | status *dto.InstallationStatus |
| 18 | - | err string | 18 | + | err string |
| 19 | complete bool | 19 | complete bool | ||
| 20 | } | 20 | } | ||
| 21 | 21 | ||||
M internal/interfaces/tui/models/progress.go +1 -1
| @@ -4,9 +4,9 @@ import ( | |||
| 4 | 4 | "fmt" | |
| 5 | 5 | "strings" | |
| 6 | 6 | ||
| 7 | + | "github.com/bnema/archup/internal/application/dto" | |
| 7 | 8 | tea "github.com/charmbracelet/bubbletea" | |
| 8 | 9 | "github.com/charmbracelet/lipgloss" | |
| 9 | - | "github.com/bnema/archup/internal/application/dto" | |
| 10 | 10 | ) | |
| 11 | 11 | ||
| 12 | 12 | // ProgressModelImpl implements ProgressModel interface | |
| @@ -4,9 +4,9 @@ import ( | |||||
| 4 | "fmt" | 4 | "fmt" | ||
| 5 | "strings" | 5 | "strings" | ||
| 6 | 6 | ||||
| 7 | + | "github.com/bnema/archup/internal/application/dto" | |||
| 7 | tea "github.com/charmbracelet/bubbletea" | 8 | tea "github.com/charmbracelet/bubbletea" | ||
| 8 | "github.com/charmbracelet/lipgloss" | 9 | "github.com/charmbracelet/lipgloss" | ||
| 9 | - | "github.com/bnema/archup/internal/application/dto" | |||
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
| 12 | // ProgressModelImpl implements ProgressModel interface | 12 | // ProgressModelImpl implements ProgressModel interface | ||
M internal/interfaces/tui/views/form_view.go +1 -1
| @@ -3,8 +3,8 @@ package views | |||
| 3 | 3 | import ( | |
| 4 | 4 | "strings" | |
| 5 | 5 | ||
| 6 | - | "github.com/charmbracelet/lipgloss" | |
| 7 | 6 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 7 | + | "github.com/charmbracelet/lipgloss" | |
| 8 | 8 | ) | |
| 9 | 9 | ||
| 10 | 10 | // RenderForm renders the form model to a styled string | |
| @@ -3,8 +3,8 @@ package views | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "strings" | 4 | "strings" | ||
| 5 | 5 | ||||
| 6 | - | "github.com/charmbracelet/lipgloss" | |||
| 7 | "github.com/bnema/archup/internal/interfaces/tui/models" | 6 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 7 | + | "github.com/charmbracelet/lipgloss" | |||
| 8 | ) | 8 | ) | ||
| 9 | 9 | ||||
| 10 | // RenderForm renders the form model to a styled string | 10 | // RenderForm renders the form model to a styled string | ||
M internal/interfaces/tui/views/form_view_test.go +5 -5
| @@ -18,9 +18,9 @@ func TestRenderForm(t *testing.T) { | |||
| 18 | 18 | // Verify key content is present | |
| 19 | 19 | checks := []string{ | |
| 20 | 20 | "ArchUp Installer Configuration", // Title | |
| 21 | - | "Hostname:", // Field labels | |
| 21 | + | "Hostname:", // Field labels | |
| 22 | 22 | "Username:", | |
| 23 | - | "↑↓ Navigate", // Instructions | |
| 23 | + | "↑↓ Navigate", // Instructions | |
| 24 | 24 | } | |
| 25 | 25 | ||
| 26 | 26 | for _, check := range checks { | |
| @@ -123,9 +123,9 @@ func TestFormFieldInteraction(t *testing.T) { | |||
| 123 | 123 | ||
| 124 | 124 | // Set data | |
| 125 | 125 | testData := models.FormData{ | |
| 126 | - | Hostname: "test-host", | |
| 127 | - | Username: "testuser", | |
| 128 | - | TargetDisk: "/dev/sda", | |
| 126 | + | Hostname: "test-host", | |
| 127 | + | Username: "testuser", | |
| 128 | + | TargetDisk: "/dev/sda", | |
| 129 | 129 | EncryptionType: "LUKS", | |
| 130 | 130 | } | |
| 131 | 131 | fm.SetData(testData) | |
| @@ -18,9 +18,9 @@ func TestRenderForm(t *testing.T) { | |||||
| 18 | // Verify key content is present | 18 | // Verify key content is present | ||
| 19 | checks := []string{ | 19 | checks := []string{ | ||
| 20 | "ArchUp Installer Configuration", // Title | 20 | "ArchUp Installer Configuration", // Title | ||
| 21 | - | "Hostname:", // Field labels | 21 | + | "Hostname:", // Field labels |
| 22 | "Username:", | 22 | "Username:", | ||
| 23 | - | "↑↓ Navigate", // Instructions | 23 | + | "↑↓ Navigate", // Instructions |
| 24 | } | 24 | } | ||
| 25 | 25 | ||||
| 26 | for _, check := range checks { | 26 | for _, check := range checks { | ||
| @@ -123,9 +123,9 @@ func TestFormFieldInteraction(t *testing.T) { | |||||
| 123 | 123 | ||||
| 124 | // Set data | 124 | // Set data | ||
| 125 | testData := models.FormData{ | 125 | testData := models.FormData{ | ||
| 126 | - | Hostname: "test-host", | 126 | + | Hostname: "test-host", |
| 127 | - | Username: "testuser", | 127 | + | Username: "testuser", |
| 128 | - | TargetDisk: "/dev/sda", | 128 | + | TargetDisk: "/dev/sda", |
| 129 | EncryptionType: "LUKS", | 129 | EncryptionType: "LUKS", | ||
| 130 | } | 130 | } | ||
| 131 | fm.SetData(testData) | 131 | fm.SetData(testData) | ||
M internal/interfaces/tui/views/progress_view.go +1 -1
| @@ -4,8 +4,8 @@ import ( | |||
| 4 | 4 | "fmt" | |
| 5 | 5 | "strings" | |
| 6 | 6 | ||
| 7 | - | "github.com/charmbracelet/lipgloss" | |
| 8 | 7 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 8 | + | "github.com/charmbracelet/lipgloss" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | 11 | // RenderProgress renders the progress model to a styled string | |
| @@ -4,8 +4,8 @@ import ( | |||||
| 4 | "fmt" | 4 | "fmt" | ||
| 5 | "strings" | 5 | "strings" | ||
| 6 | 6 | ||||
| 7 | - | "github.com/charmbracelet/lipgloss" | |||
| 8 | "github.com/bnema/archup/internal/interfaces/tui/models" | 7 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 8 | + | "github.com/charmbracelet/lipgloss" | |||
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
| 11 | // RenderProgress renders the progress model to a styled string | 11 | // RenderProgress renders the progress model to a styled string | ||
M internal/interfaces/tui/views/progress_view_test.go +7 -7
| @@ -27,13 +27,13 @@ func TestRenderProgress(t *testing.T) { | |||
| 27 | 27 | ||
| 28 | 28 | // Verify key content is present | |
| 29 | 29 | checks := []string{ | |
| 30 | - | "Installation Progress", // Title | |
| 31 | - | "Phase 2/7", // Phase info | |
| 32 | - | "Partitioning", // Phase name | |
| 33 | - | "Partitioning disk...", // Message | |
| 34 | - | "[", // Progress bar start | |
| 35 | - | "]", // Progress bar end | |
| 36 | - | "25%", // Progress percentage | |
| 30 | + | "Installation Progress", // Title | |
| 31 | + | "Phase 2/7", // Phase info | |
| 32 | + | "Partitioning", // Phase name | |
| 33 | + | "Partitioning disk...", // Message | |
| 34 | + | "[", // Progress bar start | |
| 35 | + | "]", // Progress bar end | |
| 36 | + | "25%", // Progress percentage | |
| 37 | 37 | } | |
| 38 | 38 | ||
| 39 | 39 | for _, check := range checks { | |
| @@ -27,13 +27,13 @@ func TestRenderProgress(t *testing.T) { | |||||
| 27 | 27 | ||||
| 28 | // Verify key content is present | 28 | // Verify key content is present | ||
| 29 | checks := []string{ | 29 | checks := []string{ | ||
| 30 | - | "Installation Progress", // Title | 30 | + | "Installation Progress", // Title |
| 31 | - | "Phase 2/7", // Phase info | 31 | + | "Phase 2/7", // Phase info |
| 32 | - | "Partitioning", // Phase name | 32 | + | "Partitioning", // Phase name |
| 33 | - | "Partitioning disk...", // Message | 33 | + | "Partitioning disk...", // Message |
| 34 | - | "[", // Progress bar start | 34 | + | "[", // Progress bar start |
| 35 | - | "]", // Progress bar end | 35 | + | "]", // Progress bar end |
| 36 | - | "25%", // Progress percentage | 36 | + | "25%", // Progress percentage |
| 37 | } | 37 | } | ||
| 38 | 38 | ||||
| 39 | for _, check := range checks { | 39 | for _, check := range checks { | ||
M internal/interfaces/tui/views/summary_view.go +1 -1
| @@ -5,8 +5,8 @@ import ( | |||
| 5 | 5 | "strings" | |
| 6 | 6 | "time" | |
| 7 | 7 | ||
| 8 | - | "github.com/charmbracelet/lipgloss" | |
| 9 | 8 | "github.com/bnema/archup/internal/interfaces/tui/models" | |
| 9 | + | "github.com/charmbracelet/lipgloss" | |
| 10 | 10 | ) | |
| 11 | 11 | ||
| 12 | 12 | // RenderSummary renders the installation summary (success case) | |
| @@ -5,8 +5,8 @@ import ( | |||||
| 5 | "strings" | 5 | "strings" | ||
| 6 | "time" | 6 | "time" | ||
| 7 | 7 | ||||
| 8 | - | "github.com/charmbracelet/lipgloss" | |||
| 9 | "github.com/bnema/archup/internal/interfaces/tui/models" | 8 | "github.com/bnema/archup/internal/interfaces/tui/models" | ||
| 9 | + | "github.com/charmbracelet/lipgloss" | |||
| 10 | ) | 10 | ) | ||
| 11 | 11 | ||||
| 12 | // RenderSummary renders the installation summary (success case) | 12 | // RenderSummary renders the installation summary (success case) | ||
M internal/interfaces/tui/views/summary_view_test.go +18 -18
| @@ -16,14 +16,14 @@ func TestRenderSummary(t *testing.T) { | |||
| 16 | 16 | now := time.Now() | |
| 17 | 17 | completedAt := now.Add(1 * time.Hour) | |
| 18 | 18 | status := &dto.InstallationStatus{ | |
| 19 | - | Hostname: "test-host", | |
| 20 | - | Username: "testuser", | |
| 21 | - | TargetDisk: "/dev/sda", | |
| 22 | - | Progress: 100, | |
| 23 | - | State: "Complete", | |
| 19 | + | Hostname: "test-host", | |
| 20 | + | Username: "testuser", | |
| 21 | + | TargetDisk: "/dev/sda", | |
| 22 | + | Progress: 100, | |
| 23 | + | State: "Complete", | |
| 24 | 24 | CurrentPhase: "PostInstallation", | |
| 25 | - | StartedAt: &now, | |
| 26 | - | CompletedAt: &completedAt, | |
| 25 | + | StartedAt: &now, | |
| 26 | + | CompletedAt: &completedAt, | |
| 27 | 27 | } | |
| 28 | 28 | ||
| 29 | 29 | im.SetStatus(status) | |
| @@ -34,11 +34,11 @@ func TestRenderSummary(t *testing.T) { | |||
| 34 | 34 | ||
| 35 | 35 | // Verify key content is present | |
| 36 | 36 | checks := []string{ | |
| 37 | - | "Installation Complete!", // Title | |
| 38 | - | "test-host", // Hostname | |
| 39 | - | "testuser", // Username | |
| 40 | - | "/dev/sda", // Disk | |
| 41 | - | "Press 'q' to exit", // Instructions | |
| 37 | + | "Installation Complete!", // Title | |
| 38 | + | "test-host", // Hostname | |
| 39 | + | "testuser", // Username | |
| 40 | + | "/dev/sda", // Disk | |
| 41 | + | "Press 'q' to exit", // Instructions | |
| 42 | 42 | } | |
| 43 | 43 | ||
| 44 | 44 | for _, check := range checks { | |
| @@ -63,9 +63,9 @@ func TestRenderError(t *testing.T) { | |||
| 63 | 63 | ||
| 64 | 64 | // Verify key content is present | |
| 65 | 65 | checks := []string{ | |
| 66 | - | "Installation Failed", // Title | |
| 67 | - | errorMsg, // Error message | |
| 68 | - | "Press 'q' or Ctrl+C to exit", // Instructions | |
| 66 | + | "Installation Failed", // Title | |
| 67 | + | errorMsg, // Error message | |
| 68 | + | "Press 'q' or Ctrl+C to exit", // Instructions | |
| 69 | 69 | } | |
| 70 | 70 | ||
| 71 | 71 | for _, check := range checks { | |
| @@ -84,10 +84,10 @@ func TestRenderStatus(t *testing.T) { | |||
| 84 | 84 | ||
| 85 | 85 | // Create status data | |
| 86 | 86 | status := &dto.InstallationStatus{ | |
| 87 | - | Hostname: "test-host", | |
| 87 | + | Hostname: "test-host", | |
| 88 | 88 | CurrentPhase: "Partitioning", | |
| 89 | - | Progress: 35, | |
| 90 | - | State: "Running", | |
| 89 | + | Progress: 35, | |
| 90 | + | State: "Running", | |
| 91 | 91 | } | |
| 92 | 92 | ||
| 93 | 93 | im.SetStatus(status) | |
| @@ -16,14 +16,14 @@ func TestRenderSummary(t *testing.T) { | |||||
| 16 | now := time.Now() | 16 | now := time.Now() | ||
| 17 | completedAt := now.Add(1 * time.Hour) | 17 | completedAt := now.Add(1 * time.Hour) | ||
| 18 | status := &dto.InstallationStatus{ | 18 | status := &dto.InstallationStatus{ | ||
| 19 | - | Hostname: "test-host", | 19 | + | Hostname: "test-host", |
| 20 | - | Username: "testuser", | 20 | + | Username: "testuser", |
| 21 | - | TargetDisk: "/dev/sda", | 21 | + | TargetDisk: "/dev/sda", |
| 22 | - | Progress: 100, | 22 | + | Progress: 100, |
| 23 | - | State: "Complete", | 23 | + | State: "Complete", |
| 24 | CurrentPhase: "PostInstallation", | 24 | CurrentPhase: "PostInstallation", | ||
| 25 | - | StartedAt: &now, | 25 | + | StartedAt: &now, |
| 26 | - | CompletedAt: &completedAt, | 26 | + | CompletedAt: &completedAt, |
| 27 | } | 27 | } | ||
| 28 | 28 | ||||
| 29 | im.SetStatus(status) | 29 | im.SetStatus(status) | ||
| @@ -34,11 +34,11 @@ func TestRenderSummary(t *testing.T) { | |||||
| 34 | 34 | ||||
| 35 | // Verify key content is present | 35 | // Verify key content is present | ||
| 36 | checks := []string{ | 36 | checks := []string{ | ||
| 37 | - | "Installation Complete!", // Title | 37 | + | "Installation Complete!", // Title |
| 38 | - | "test-host", // Hostname | 38 | + | "test-host", // Hostname |
| 39 | - | "testuser", // Username | 39 | + | "testuser", // Username |
| 40 | - | "/dev/sda", // Disk | 40 | + | "/dev/sda", // Disk |
| 41 | - | "Press 'q' to exit", // Instructions | 41 | + | "Press 'q' to exit", // Instructions |
| 42 | } | 42 | } | ||
| 43 | 43 | ||||
| 44 | for _, check := range checks { | 44 | for _, check := range checks { | ||
| @@ -63,9 +63,9 @@ func TestRenderError(t *testing.T) { | |||||
| 63 | 63 | ||||
| 64 | // Verify key content is present | 64 | // Verify key content is present | ||
| 65 | checks := []string{ | 65 | checks := []string{ | ||
| 66 | - | "Installation Failed", // Title | 66 | + | "Installation Failed", // Title |
| 67 | - | errorMsg, // Error message | 67 | + | errorMsg, // Error message |
| 68 | - | "Press 'q' or Ctrl+C to exit", // Instructions | 68 | + | "Press 'q' or Ctrl+C to exit", // Instructions |
| 69 | } | 69 | } | ||
| 70 | 70 | ||||
| 71 | for _, check := range checks { | 71 | for _, check := range checks { | ||
| @@ -84,10 +84,10 @@ func TestRenderStatus(t *testing.T) { | |||||
| 84 | 84 | ||||
| 85 | // Create status data | 85 | // Create status data | ||
| 86 | status := &dto.InstallationStatus{ | 86 | status := &dto.InstallationStatus{ | ||
| 87 | - | Hostname: "test-host", | 87 | + | Hostname: "test-host", |
| 88 | CurrentPhase: "Partitioning", | 88 | CurrentPhase: "Partitioning", | ||
| 89 | - | Progress: 35, | 89 | + | Progress: 35, |
| 90 | - | State: "Running", | 90 | + | State: "Running", |
| 91 | } | 91 | } | ||
| 92 | 92 | ||||
| 93 | im.SetStatus(status) | 93 | im.SetStatus(status) | ||
M internal/logger/logger.go +4 -4
| @@ -13,10 +13,10 @@ import ( | |||
| 13 | 13 | ||
| 14 | 14 | // Logger wraps slog.Logger and adds dry-run mode support | |
| 15 | 15 | type Logger struct { | |
| 16 | - | slog *slog.Logger | |
| 17 | - | logPath string | |
| 18 | - | dryRun bool | |
| 19 | - | logFile *os.File | |
| 16 | + | slog *slog.Logger | |
| 17 | + | logPath string | |
| 18 | + | dryRun bool | |
| 19 | + | logFile *os.File | |
| 20 | 20 | } | |
| 21 | 21 | ||
| 22 | 22 | // syncWriter wraps an io.Writer to sync after every write | |
| @@ -13,10 +13,10 @@ import ( | |||||
| 13 | 13 | ||||
| 14 | // Logger wraps slog.Logger and adds dry-run mode support | 14 | // Logger wraps slog.Logger and adds dry-run mode support | ||
| 15 | type Logger struct { | 15 | type Logger struct { | ||
| 16 | - | slog *slog.Logger | 16 | + | slog *slog.Logger |
| 17 | - | logPath string | 17 | + | logPath string |
| 18 | - | dryRun bool | 18 | + | dryRun bool |
| 19 | - | logFile *os.File | 19 | + | logFile *os.File |
| 20 | } | 20 | } | ||
| 21 | 21 | ||||
| 22 | // syncWriter wraps an io.Writer to sync after every write | 22 | // syncWriter wraps an io.Writer to sync after every write | ||
M internal/phases/base.go +2 -2
| @@ -13,8 +13,8 @@ import ( | |||
| 13 | 13 | // BaseInstallPhase handles base system installation | |
| 14 | 14 | type BaseInstallPhase struct { | |
| 15 | 15 | *BasePhase | |
| 16 | - | fs interfaces.FileSystem | |
| 17 | - | sysExec interfaces.SystemExecutor | |
| 16 | + | fs interfaces.FileSystem | |
| 17 | + | sysExec interfaces.SystemExecutor | |
| 18 | 18 | packages []string | |
| 19 | 19 | } | |
| 20 | 20 | ||
| @@ -13,8 +13,8 @@ import ( | |||||
| 13 | // BaseInstallPhase handles base system installation | 13 | // BaseInstallPhase handles base system installation | ||
| 14 | type BaseInstallPhase struct { | 14 | type BaseInstallPhase struct { | ||
| 15 | *BasePhase | 15 | *BasePhase | ||
| 16 | - | fs interfaces.FileSystem | 16 | + | fs interfaces.FileSystem |
| 17 | - | sysExec interfaces.SystemExecutor | 17 | + | sysExec interfaces.SystemExecutor |
| 18 | packages []string | 18 | packages []string | ||
| 19 | } | 19 | } | ||
| 20 | 20 | ||||
M internal/phases/base_test.go +50 -50
| @@ -73,39 +73,39 @@ func TestBaseInstallPhasePreCheck(t *testing.T) { | |||
| 73 | 73 | // TestBaseInstallPhaseDetectCPU tests CPU vendor detection | |
| 74 | 74 | func TestBaseInstallPhaseDetectCPU(t *testing.T) { | |
| 75 | 75 | tests := []struct { | |
| 76 | - | name string | |
| 77 | - | cpuinfoContent string | |
| 78 | - | expectedVendor string | |
| 76 | + | name string | |
| 77 | + | cpuinfoContent string | |
| 78 | + | expectedVendor string | |
| 79 | 79 | expectedMicrocode string | |
| 80 | - | wantErr bool | |
| 80 | + | wantErr bool | |
| 81 | 81 | }{ | |
| 82 | 82 | { | |
| 83 | - | name: "Intel CPU detected", | |
| 84 | - | cpuinfoContent: "processor\t: 0\nvendor_id\t: GenuineIntel\nflags\t: fpu\n", | |
| 85 | - | expectedVendor: "Intel", | |
| 83 | + | name: "Intel CPU detected", | |
| 84 | + | cpuinfoContent: "processor\t: 0\nvendor_id\t: GenuineIntel\nflags\t: fpu\n", | |
| 85 | + | expectedVendor: "Intel", | |
| 86 | 86 | expectedMicrocode: "intel-ucode", | |
| 87 | - | wantErr: false, | |
| 87 | + | wantErr: false, | |
| 88 | 88 | }, | |
| 89 | 89 | { | |
| 90 | - | name: "AMD CPU detected", | |
| 91 | - | cpuinfoContent: "processor\t: 0\nvendor_id\t: AuthenticAMD\nflags\t: fpu\n", | |
| 92 | - | expectedVendor: "AMD", | |
| 90 | + | name: "AMD CPU detected", | |
| 91 | + | cpuinfoContent: "processor\t: 0\nvendor_id\t: AuthenticAMD\nflags\t: fpu\n", | |
| 92 | + | expectedVendor: "AMD", | |
| 93 | 93 | expectedMicrocode: "amd-ucode", | |
| 94 | - | wantErr: false, | |
| 94 | + | wantErr: false, | |
| 95 | 95 | }, | |
| 96 | 96 | { | |
| 97 | - | name: "Unknown CPU vendor", | |
| 98 | - | cpuinfoContent: "processor\t: 0\nvendor_id\t: UnknownVendor\nflags\t: fpu\n", | |
| 99 | - | expectedVendor: "Unknown", | |
| 97 | + | name: "Unknown CPU vendor", | |
| 98 | + | cpuinfoContent: "processor\t: 0\nvendor_id\t: UnknownVendor\nflags\t: fpu\n", | |
| 99 | + | expectedVendor: "Unknown", | |
| 100 | 100 | expectedMicrocode: "", | |
| 101 | - | wantErr: false, | |
| 101 | + | wantErr: false, | |
| 102 | 102 | }, | |
| 103 | 103 | { | |
| 104 | - | name: "Empty cpuinfo", | |
| 105 | - | cpuinfoContent: "", | |
| 106 | - | expectedVendor: "Unknown", | |
| 104 | + | name: "Empty cpuinfo", | |
| 105 | + | cpuinfoContent: "", | |
| 106 | + | expectedVendor: "Unknown", | |
| 107 | 107 | expectedMicrocode: "", | |
| 108 | - | wantErr: false, | |
| 108 | + | wantErr: false, | |
| 109 | 109 | }, | |
| 110 | 110 | } | |
| 111 | 111 | ||
| @@ -237,21 +237,21 @@ func TestBaseInstallPhaseLoadBasePackages(t *testing.T) { | |||
| 237 | 237 | // TestBaseInstallPhaseGenerateFstab tests fstab generation | |
| 238 | 238 | func TestBaseInstallPhaseGenerateFstab(t *testing.T) { | |
| 239 | 239 | tests := []struct { | |
| 240 | - | name string | |
| 241 | - | genfstabResult system.CommandResult | |
| 242 | - | wantErr bool | |
| 243 | - | errContains string | |
| 240 | + | name string | |
| 241 | + | genfstabResult system.CommandResult | |
| 242 | + | wantErr bool | |
| 243 | + | errContains string | |
| 244 | 244 | }{ | |
| 245 | 245 | { | |
| 246 | - | name: "Fstab generation success", | |
| 247 | - | genfstabResult: system.CommandResult{ExitCode: 0}, | |
| 248 | - | wantErr: false, | |
| 246 | + | name: "Fstab generation success", | |
| 247 | + | genfstabResult: system.CommandResult{ExitCode: 0}, | |
| 248 | + | wantErr: false, | |
| 249 | 249 | }, | |
| 250 | 250 | { | |
| 251 | - | name: "Genfstab command failed", | |
| 252 | - | genfstabResult: system.CommandResult{ExitCode: 1, Error: fmt.Errorf("permission denied")}, | |
| 253 | - | wantErr: true, | |
| 254 | - | errContains: "genfstab failed", | |
| 251 | + | name: "Genfstab command failed", | |
| 252 | + | genfstabResult: system.CommandResult{ExitCode: 1, Error: fmt.Errorf("permission denied")}, | |
| 253 | + | wantErr: true, | |
| 254 | + | errContains: "genfstab failed", | |
| 255 | 255 | }, | |
| 256 | 256 | } | |
| 257 | 257 | ||
| @@ -295,31 +295,31 @@ func TestBaseInstallPhaseGenerateFstab(t *testing.T) { | |||
| 295 | 295 | // TestBaseInstallPhasePostCheck tests installation validation | |
| 296 | 296 | func TestBaseInstallPhasePostCheck(t *testing.T) { | |
| 297 | 297 | tests := []struct { | |
| 298 | - | name string | |
| 299 | - | usrDirExists bool | |
| 300 | - | fstabFileExists bool | |
| 301 | - | wantErr bool | |
| 302 | - | errContains string | |
| 298 | + | name string | |
| 299 | + | usrDirExists bool | |
| 300 | + | fstabFileExists bool | |
| 301 | + | wantErr bool | |
| 302 | + | errContains string | |
| 303 | 303 | }{ | |
| 304 | 304 | { | |
| 305 | - | name: "Both /mnt/usr and /mnt/etc/fstab exist", | |
| 306 | - | usrDirExists: true, | |
| 307 | - | fstabFileExists: true, | |
| 308 | - | wantErr: false, | |
| 305 | + | name: "Both /mnt/usr and /mnt/etc/fstab exist", | |
| 306 | + | usrDirExists: true, | |
| 307 | + | fstabFileExists: true, | |
| 308 | + | wantErr: false, | |
| 309 | 309 | }, | |
| 310 | 310 | { | |
| 311 | - | name: "/mnt/usr does not exist", | |
| 312 | - | usrDirExists: false, | |
| 313 | - | fstabFileExists: true, | |
| 314 | - | wantErr: true, | |
| 315 | - | errContains: "/mnt/usr does not exist", | |
| 311 | + | name: "/mnt/usr does not exist", | |
| 312 | + | usrDirExists: false, | |
| 313 | + | fstabFileExists: true, | |
| 314 | + | wantErr: true, | |
| 315 | + | errContains: "/mnt/usr does not exist", | |
| 316 | 316 | }, | |
| 317 | 317 | { | |
| 318 | - | name: "/mnt/etc/fstab does not exist", | |
| 319 | - | usrDirExists: true, | |
| 320 | - | fstabFileExists: false, | |
| 321 | - | wantErr: true, | |
| 322 | - | errContains: "fstab was not created", | |
| 318 | + | name: "/mnt/etc/fstab does not exist", | |
| 319 | + | usrDirExists: true, | |
| 320 | + | fstabFileExists: false, | |
| 321 | + | wantErr: true, | |
| 322 | + | errContains: "fstab was not created", | |
| 323 | 323 | }, | |
| 324 | 324 | } | |
| 325 | 325 | ||
| @@ -73,39 +73,39 @@ func TestBaseInstallPhasePreCheck(t *testing.T) { | |||||
| 73 | // TestBaseInstallPhaseDetectCPU tests CPU vendor detection | 73 | // TestBaseInstallPhaseDetectCPU tests CPU vendor detection | ||
| 74 | func TestBaseInstallPhaseDetectCPU(t *testing.T) { | 74 | func TestBaseInstallPhaseDetectCPU(t *testing.T) { | ||
| 75 | tests := []struct { | 75 | tests := []struct { | ||
| 76 | - | name string | 76 | + | name string |
| 77 | - | cpuinfoContent string | 77 | + | cpuinfoContent string |
| 78 | - | expectedVendor string | 78 | + | expectedVendor string |
| 79 | expectedMicrocode string | 79 | expectedMicrocode string | ||
| 80 | - | wantErr bool | 80 | + | wantErr bool |
| 81 | }{ | 81 | }{ | ||
| 82 | { | 82 | { | ||
| 83 | - | name: "Intel CPU detected", | 83 | + | name: "Intel CPU detected", |
| 84 | - | cpuinfoContent: "processor\t: 0\nvendor_id\t: GenuineIntel\nflags\t: fpu\n", | 84 | + | cpuinfoContent: "processor\t: 0\nvendor_id\t: GenuineIntel\nflags\t: fpu\n", |
| 85 | - | expectedVendor: "Intel", | 85 | + | expectedVendor: "Intel", |
| 86 | expectedMicrocode: "intel-ucode", | 86 | expectedMicrocode: "intel-ucode", | ||
| 87 | - | wantErr: false, | 87 | + | wantErr: false, |
| 88 | }, | 88 | }, | ||
| 89 | { | 89 | { | ||
| 90 | - | name: "AMD CPU detected", | 90 | + | name: "AMD CPU detected", |
| 91 | - | cpuinfoContent: "processor\t: 0\nvendor_id\t: AuthenticAMD\nflags\t: fpu\n", | 91 | + | cpuinfoContent: "processor\t: 0\nvendor_id\t: AuthenticAMD\nflags\t: fpu\n", |
| 92 | - | expectedVendor: "AMD", | 92 | + | expectedVendor: "AMD", |
| 93 | expectedMicrocode: "amd-ucode", | 93 | expectedMicrocode: "amd-ucode", | ||
| 94 | - | wantErr: false, | 94 | + | wantErr: false, |
| 95 | }, | 95 | }, | ||
| 96 | { | 96 | { | ||
| 97 | - | name: "Unknown CPU vendor", | 97 | + | name: "Unknown CPU vendor", |
| 98 | - | cpuinfoContent: "processor\t: 0\nvendor_id\t: UnknownVendor\nflags\t: fpu\n", | 98 | + | cpuinfoContent: "processor\t: 0\nvendor_id\t: UnknownVendor\nflags\t: fpu\n", |
| 99 | - | expectedVendor: "Unknown", | 99 | + | expectedVendor: "Unknown", |
| 100 | expectedMicrocode: "", | 100 | expectedMicrocode: "", | ||
| 101 | - | wantErr: false, | 101 | + | wantErr: false, |
| 102 | }, | 102 | }, | ||
| 103 | { | 103 | { | ||
| 104 | - | name: "Empty cpuinfo", | 104 | + | name: "Empty cpuinfo", |
| 105 | - | cpuinfoContent: "", | 105 | + | cpuinfoContent: "", |
| 106 | - | expectedVendor: "Unknown", | 106 | + | expectedVendor: "Unknown", |
| 107 | expectedMicrocode: "", | 107 | expectedMicrocode: "", | ||
| 108 | - | wantErr: false, | 108 | + | wantErr: false, |
| 109 | }, | 109 | }, | ||
| 110 | } | 110 | } | ||
| 111 | 111 | ||||
| @@ -237,21 +237,21 @@ func TestBaseInstallPhaseLoadBasePackages(t *testing.T) { | |||||
| 237 | // TestBaseInstallPhaseGenerateFstab tests fstab generation | 237 | // TestBaseInstallPhaseGenerateFstab tests fstab generation | ||
| 238 | func TestBaseInstallPhaseGenerateFstab(t *testing.T) { | 238 | func TestBaseInstallPhaseGenerateFstab(t *testing.T) { | ||
| 239 | tests := []struct { | 239 | tests := []struct { | ||
| 240 | - | name string | 240 | + | name string |
| 241 | - | genfstabResult system.CommandResult | 241 | + | genfstabResult system.CommandResult |
| 242 | - | wantErr bool | 242 | + | wantErr bool |
| 243 | - | errContains string | 243 | + | errContains string |
| 244 | }{ | 244 | }{ | ||
| 245 | { | 245 | { | ||
| 246 | - | name: "Fstab generation success", | 246 | + | name: "Fstab generation success", |
| 247 | - | genfstabResult: system.CommandResult{ExitCode: 0}, | 247 | + | genfstabResult: system.CommandResult{ExitCode: 0}, |
| 248 | - | wantErr: false, | 248 | + | wantErr: false, |
| 249 | }, | 249 | }, | ||
| 250 | { | 250 | { | ||
| 251 | - | name: "Genfstab command failed", | 251 | + | name: "Genfstab command failed", |
| 252 | - | genfstabResult: system.CommandResult{ExitCode: 1, Error: fmt.Errorf("permission denied")}, | 252 | + | genfstabResult: system.CommandResult{ExitCode: 1, Error: fmt.Errorf("permission denied")}, |
| 253 | - | wantErr: true, | 253 | + | wantErr: true, |
| 254 | - | errContains: "genfstab failed", | 254 | + | errContains: "genfstab failed", |
| 255 | }, | 255 | }, | ||
| 256 | } | 256 | } | ||
| 257 | 257 | ||||
| @@ -295,31 +295,31 @@ func TestBaseInstallPhaseGenerateFstab(t *testing.T) { | |||||
| 295 | // TestBaseInstallPhasePostCheck tests installation validation | 295 | // TestBaseInstallPhasePostCheck tests installation validation | ||
| 296 | func TestBaseInstallPhasePostCheck(t *testing.T) { | 296 | func TestBaseInstallPhasePostCheck(t *testing.T) { | ||
| 297 | tests := []struct { | 297 | tests := []struct { | ||
| 298 | - | name string | 298 | + | name string |
| 299 | - | usrDirExists bool | 299 | + | usrDirExists bool |
| 300 | - | fstabFileExists bool | 300 | + | fstabFileExists bool |
| 301 | - | wantErr bool | 301 | + | wantErr bool |
| 302 | - | errContains string | 302 | + | errContains string |
| 303 | }{ | 303 | }{ | ||
| 304 | { | 304 | { | ||
| 305 | - | name: "Both /mnt/usr and /mnt/etc/fstab exist", | 305 | + | name: "Both /mnt/usr and /mnt/etc/fstab exist", |
| 306 | - | usrDirExists: true, | 306 | + | usrDirExists: true, |
| 307 | - | fstabFileExists: true, | 307 | + | fstabFileExists: true, |
| 308 | - | wantErr: false, | 308 | + | wantErr: false, |
| 309 | }, | 309 | }, | ||
| 310 | { | 310 | { | ||
| 311 | - | name: "/mnt/usr does not exist", | 311 | + | name: "/mnt/usr does not exist", |
| 312 | - | usrDirExists: false, | 312 | + | usrDirExists: false, |
| 313 | - | fstabFileExists: true, | 313 | + | fstabFileExists: true, |
| 314 | - | wantErr: true, | 314 | + | wantErr: true, |
| 315 | - | errContains: "/mnt/usr does not exist", | 315 | + | errContains: "/mnt/usr does not exist", |
| 316 | }, | 316 | }, | ||
| 317 | { | 317 | { | ||
| 318 | - | name: "/mnt/etc/fstab does not exist", | 318 | + | name: "/mnt/etc/fstab does not exist", |
| 319 | - | usrDirExists: true, | 319 | + | usrDirExists: true, |
| 320 | - | fstabFileExists: false, | 320 | + | fstabFileExists: false, |
| 321 | - | wantErr: true, | 321 | + | wantErr: true, |
| 322 | - | errContains: "fstab was not created", | 322 | + | errContains: "fstab was not created", |
| 323 | }, | 323 | }, | ||
| 324 | } | 324 | } | ||
| 325 | 325 | ||||
M internal/phases/boot.go +9 -9
| @@ -15,9 +15,9 @@ import ( | |||
| 15 | 15 | // BootPhase handles bootloader installation | |
| 16 | 16 | type BootPhase struct { | |
| 17 | 17 | *BasePhase | |
| 18 | - | fs interfaces.FileSystem | |
| 19 | - | sysExec interfaces.SystemExecutor | |
| 20 | - | chrExec interfaces.ChrootExecutor | |
| 18 | + | fs interfaces.FileSystem | |
| 19 | + | sysExec interfaces.SystemExecutor | |
| 20 | + | chrExec interfaces.ChrootExecutor | |
| 21 | 21 | } | |
| 22 | 22 | ||
| 23 | 23 | // NewBootPhase creates a new boot phase | |
| @@ -119,7 +119,7 @@ func (p *BootPhase) configureMkinitcpio(progressChan chan<- ProgressUpdate) erro | |||
| 119 | 119 | ||
| 120 | 120 | // Regenerate initramfs | |
| 121 | 121 | p.SendOutput(progressChan, "Regenerating initramfs...") | |
| 122 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); err != nil { | |
| 122 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "mkinitcpio -P"); err != nil { | |
| 123 | 123 | return fmt.Errorf("failed to regenerate initramfs: %w", err) | |
| 124 | 124 | } | |
| 125 | 125 | ||
| @@ -134,7 +134,7 @@ func (p *BootPhase) installLimine(progressChan chan<- ProgressUpdate) error { | |||
| 134 | 134 | ||
| 135 | 135 | // Install Limine to disk (BIOS - optional, may fail on UEFI-only) | |
| 136 | 136 | biosCmd := fmt.Sprintf("limine bios-install %s", p.config.TargetDisk) | |
| 137 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, biosCmd); { | |
| 137 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, biosCmd); { | |
| 138 | 138 | case err != nil: | |
| 139 | 139 | p.SendOutput(progressChan, "[WARN] BIOS installation skipped (UEFI-only system)") | |
| 140 | 140 | default: | |
| @@ -224,8 +224,8 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error { | |||
| 224 | 224 | limineConfig = strings.ReplaceAll(limineConfig, "{{KERNEL}}", p.config.KernelChoice) | |
| 225 | 225 | limineConfig = strings.ReplaceAll(limineConfig, "{{KERNEL_PARAMS}}", kernelParams) | |
| 226 | 226 | ||
| 227 | - | // Write Limine configuration | |
| 228 | - | limineConfigPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 227 | + | // Write Limine configuration to /boot/limine.conf (standard Limine search path) | |
| 228 | + | limineConfigPath := config.PathMntBootLimineConf | |
| 229 | 229 | if err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); err != nil { | |
| 230 | 230 | return fmt.Errorf("failed to write Limine config: %w", err) | |
| 231 | 231 | } | |
| @@ -253,7 +253,7 @@ func (p *BootPhase) createUEFIEntry(progressChan chan<- ProgressUpdate) error { | |||
| 253 | 253 | config.UEFIBootLoader, | |
| 254 | 254 | ) | |
| 255 | 255 | ||
| 256 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, efiCmd); err != nil { | |
| 256 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, efiCmd); err != nil { | |
| 257 | 257 | return fmt.Errorf("failed to create UEFI boot entry: %w", err) | |
| 258 | 258 | } | |
| 259 | 259 | ||
| @@ -287,7 +287,7 @@ func (p *BootPhase) PostCheck() error { | |||
| 287 | 287 | } | |
| 288 | 288 | ||
| 289 | 289 | // Verify Limine config exists | |
| 290 | - | configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 290 | + | configPath := config.PathMntBootLimineConf | |
| 291 | 291 | if _, err := p.fs.Stat(configPath); p.fs.IsNotExist(err) { | |
| 292 | 292 | return fmt.Errorf("Limine config was not created") | |
| 293 | 293 | } | |
| @@ -15,9 +15,9 @@ import ( | |||||
| 15 | // BootPhase handles bootloader installation | 15 | // BootPhase handles bootloader installation | ||
| 16 | type BootPhase struct { | 16 | type BootPhase struct { | ||
| 17 | *BasePhase | 17 | *BasePhase | ||
| 18 | - | fs interfaces.FileSystem | 18 | + | fs interfaces.FileSystem |
| 19 | - | sysExec interfaces.SystemExecutor | 19 | + | sysExec interfaces.SystemExecutor |
| 20 | - | chrExec interfaces.ChrootExecutor | 20 | + | chrExec interfaces.ChrootExecutor |
| 21 | } | 21 | } | ||
| 22 | 22 | ||||
| 23 | // NewBootPhase creates a new boot phase | 23 | // NewBootPhase creates a new boot phase | ||
| @@ -119,7 +119,7 @@ func (p *BootPhase) configureMkinitcpio(progressChan chan<- ProgressUpdate) erro | |||||
| 119 | 119 | ||||
| 120 | // Regenerate initramfs | 120 | // Regenerate initramfs | ||
| 121 | p.SendOutput(progressChan, "Regenerating initramfs...") | 121 | p.SendOutput(progressChan, "Regenerating initramfs...") | ||
| 122 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); err != nil { | 122 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "mkinitcpio -P"); err != nil { |
| 123 | return fmt.Errorf("failed to regenerate initramfs: %w", err) | 123 | return fmt.Errorf("failed to regenerate initramfs: %w", err) | ||
| 124 | } | 124 | } | ||
| 125 | 125 | ||||
| @@ -134,7 +134,7 @@ func (p *BootPhase) installLimine(progressChan chan<- ProgressUpdate) error { | |||||
| 134 | 134 | ||||
| 135 | // Install Limine to disk (BIOS - optional, may fail on UEFI-only) | 135 | // Install Limine to disk (BIOS - optional, may fail on UEFI-only) | ||
| 136 | biosCmd := fmt.Sprintf("limine bios-install %s", p.config.TargetDisk) | 136 | biosCmd := fmt.Sprintf("limine bios-install %s", p.config.TargetDisk) | ||
| 137 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, biosCmd); { | 137 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, biosCmd); { |
| 138 | case err != nil: | 138 | case err != nil: | ||
| 139 | p.SendOutput(progressChan, "[WARN] BIOS installation skipped (UEFI-only system)") | 139 | p.SendOutput(progressChan, "[WARN] BIOS installation skipped (UEFI-only system)") | ||
| 140 | default: | 140 | default: | ||
| @@ -224,8 +224,8 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error { | |||||
| 224 | limineConfig = strings.ReplaceAll(limineConfig, "{{KERNEL}}", p.config.KernelChoice) | 224 | limineConfig = strings.ReplaceAll(limineConfig, "{{KERNEL}}", p.config.KernelChoice) | ||
| 225 | limineConfig = strings.ReplaceAll(limineConfig, "{{KERNEL_PARAMS}}", kernelParams) | 225 | limineConfig = strings.ReplaceAll(limineConfig, "{{KERNEL_PARAMS}}", kernelParams) | ||
| 226 | 226 | ||||
| 227 | - | // Write Limine configuration | 227 | + | // Write Limine configuration to /boot/limine.conf (standard Limine search path) |
| 228 | - | limineConfigPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 228 | + | limineConfigPath := config.PathMntBootLimineConf |
| 229 | if err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); err != nil { | 229 | if err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); err != nil { | ||
| 230 | return fmt.Errorf("failed to write Limine config: %w", err) | 230 | return fmt.Errorf("failed to write Limine config: %w", err) | ||
| 231 | } | 231 | } | ||
| @@ -253,7 +253,7 @@ func (p *BootPhase) createUEFIEntry(progressChan chan<- ProgressUpdate) error { | |||||
| 253 | config.UEFIBootLoader, | 253 | config.UEFIBootLoader, | ||
| 254 | ) | 254 | ) | ||
| 255 | 255 | ||||
| 256 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, efiCmd); err != nil { | 256 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, efiCmd); err != nil { |
| 257 | return fmt.Errorf("failed to create UEFI boot entry: %w", err) | 257 | return fmt.Errorf("failed to create UEFI boot entry: %w", err) | ||
| 258 | } | 258 | } | ||
| 259 | 259 | ||||
| @@ -287,7 +287,7 @@ func (p *BootPhase) PostCheck() error { | |||||
| 287 | } | 287 | } | ||
| 288 | 288 | ||||
| 289 | // Verify Limine config exists | 289 | // Verify Limine config exists | ||
| 290 | - | configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 290 | + | configPath := config.PathMntBootLimineConf |
| 291 | if _, err := p.fs.Stat(configPath); p.fs.IsNotExist(err) { | 291 | if _, err := p.fs.Stat(configPath); p.fs.IsNotExist(err) { | ||
| 292 | return fmt.Errorf("Limine config was not created") | 292 | return fmt.Errorf("Limine config was not created") | ||
| 293 | } | 293 | } | ||
M internal/phases/boot_test.go +17 -17
| @@ -15,10 +15,10 @@ import ( | |||
| 15 | 15 | // TestBootPhasePreCheck tests boot prerequisites | |
| 16 | 16 | func TestBootPhasePreCheck(t *testing.T) { | |
| 17 | 17 | tests := []struct { | |
| 18 | - | name string | |
| 19 | - | setupMocks func(*mocks.MockSystemExecutor) | |
| 20 | - | wantErr bool | |
| 21 | - | errContains string | |
| 18 | + | name string | |
| 19 | + | setupMocks func(*mocks.MockSystemExecutor) | |
| 20 | + | wantErr bool | |
| 21 | + | errContains string | |
| 22 | 22 | }{ | |
| 23 | 23 | { | |
| 24 | 24 | name: "Both /mnt and /mnt/boot mounted", | |
| @@ -86,9 +86,9 @@ func TestBootPhasePreCheck(t *testing.T) { | |||
| 86 | 86 | // TestBootPhaseExtractPartitionNumber tests partition number extraction | |
| 87 | 87 | func TestBootPhaseExtractPartitionNumber(t *testing.T) { | |
| 88 | 88 | tests := []struct { | |
| 89 | - | name string | |
| 90 | - | devicePath string | |
| 91 | - | expectedNum string | |
| 89 | + | name string | |
| 90 | + | devicePath string | |
| 91 | + | expectedNum string | |
| 92 | 92 | }{ | |
| 93 | 93 | { | |
| 94 | 94 | name: "SATA partition /dev/sda1", | |
| @@ -167,7 +167,7 @@ func TestBootPhasePostCheck(t *testing.T) { | |||
| 167 | 167 | name: "Both bootloader and config exist", | |
| 168 | 168 | setupMocks: func(mockFS *mocks.MockFileSystem) { | |
| 169 | 169 | bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader) | |
| 170 | - | configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 170 | + | configPath := config.PathMntBootLimineConf | |
| 171 | 171 | ||
| 172 | 172 | mockFS.EXPECT().Stat(bootloaderPath).Return(mockFileInfo{}, nil).Times(1) | |
| 173 | 173 | mockFS.EXPECT().IsNotExist(gomock.Any()).Return(false).Times(1) | |
| @@ -191,7 +191,7 @@ func TestBootPhasePostCheck(t *testing.T) { | |||
| 191 | 191 | name: "Config missing", | |
| 192 | 192 | setupMocks: func(mockFS *mocks.MockFileSystem) { | |
| 193 | 193 | bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader) | |
| 194 | - | configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 194 | + | configPath := config.PathMntBootLimineConf | |
| 195 | 195 | ||
| 196 | 196 | mockFS.EXPECT().Stat(bootloaderPath).Return(mockFileInfo{}, nil).Times(1) | |
| 197 | 197 | mockFS.EXPECT().IsNotExist(gomock.Any()).Return(false).Times(1) | |
| @@ -244,9 +244,9 @@ func TestBootPhasePostCheck(t *testing.T) { | |||
| 244 | 244 | // TestBootPhaseRollback tests boot phase rollback | |
| 245 | 245 | func TestBootPhaseRollback(t *testing.T) { | |
| 246 | 246 | tests := []struct { | |
| 247 | - | name string | |
| 248 | - | setupMocks func(*mocks.MockFileSystem) | |
| 249 | - | wantErr bool | |
| 247 | + | name string | |
| 248 | + | setupMocks func(*mocks.MockFileSystem) | |
| 249 | + | wantErr bool | |
| 250 | 250 | }{ | |
| 251 | 251 | { | |
| 252 | 252 | name: "Rollback success", | |
| @@ -423,9 +423,9 @@ func TestBootPhaseKernelParameterConstruction(t *testing.T) { | |||
| 423 | 423 | // TestBootPhaseInstallPathConstruction tests install path building | |
| 424 | 424 | func TestBootPhaseInstallPathConstruction(t *testing.T) { | |
| 425 | 425 | tests := []struct { | |
| 426 | - | name string | |
| 427 | - | filename string | |
| 428 | - | expected string | |
| 426 | + | name string | |
| 427 | + | filename string | |
| 428 | + | expected string | |
| 429 | 429 | }{ | |
| 430 | 430 | { | |
| 431 | 431 | name: "Limine config template", | |
| @@ -470,8 +470,8 @@ func TestBootPhaseInstallPathConstruction(t *testing.T) { | |||
| 470 | 470 | // TestBootPhaseFileSystemOperations tests file system interaction patterns | |
| 471 | 471 | func TestBootPhaseFileSystemOperations(t *testing.T) { | |
| 472 | 472 | tests := []struct { | |
| 473 | - | name string | |
| 474 | - | operation string // "read", "write", "mkdir" | |
| 473 | + | name string | |
| 474 | + | operation string // "read", "write", "mkdir" | |
| 475 | 475 | }{ | |
| 476 | 476 | { | |
| 477 | 477 | name: "Mkinitcpio config read", | |
| @@ -15,10 +15,10 @@ import ( | |||||
| 15 | // TestBootPhasePreCheck tests boot prerequisites | 15 | // TestBootPhasePreCheck tests boot prerequisites | ||
| 16 | func TestBootPhasePreCheck(t *testing.T) { | 16 | func TestBootPhasePreCheck(t *testing.T) { | ||
| 17 | tests := []struct { | 17 | tests := []struct { | ||
| 18 | - | name string | 18 | + | name string |
| 19 | - | setupMocks func(*mocks.MockSystemExecutor) | 19 | + | setupMocks func(*mocks.MockSystemExecutor) |
| 20 | - | wantErr bool | 20 | + | wantErr bool |
| 21 | - | errContains string | 21 | + | errContains string |
| 22 | }{ | 22 | }{ | ||
| 23 | { | 23 | { | ||
| 24 | name: "Both /mnt and /mnt/boot mounted", | 24 | name: "Both /mnt and /mnt/boot mounted", | ||
| @@ -86,9 +86,9 @@ func TestBootPhasePreCheck(t *testing.T) { | |||||
| 86 | // TestBootPhaseExtractPartitionNumber tests partition number extraction | 86 | // TestBootPhaseExtractPartitionNumber tests partition number extraction | ||
| 87 | func TestBootPhaseExtractPartitionNumber(t *testing.T) { | 87 | func TestBootPhaseExtractPartitionNumber(t *testing.T) { | ||
| 88 | tests := []struct { | 88 | tests := []struct { | ||
| 89 | - | name string | 89 | + | name string |
| 90 | - | devicePath string | 90 | + | devicePath string |
| 91 | - | expectedNum string | 91 | + | expectedNum string |
| 92 | }{ | 92 | }{ | ||
| 93 | { | 93 | { | ||
| 94 | name: "SATA partition /dev/sda1", | 94 | name: "SATA partition /dev/sda1", | ||
| @@ -167,7 +167,7 @@ func TestBootPhasePostCheck(t *testing.T) { | |||||
| 167 | name: "Both bootloader and config exist", | 167 | name: "Both bootloader and config exist", | ||
| 168 | setupMocks: func(mockFS *mocks.MockFileSystem) { | 168 | setupMocks: func(mockFS *mocks.MockFileSystem) { | ||
| 169 | bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader) | 169 | bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader) | ||
| 170 | - | configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 170 | + | configPath := config.PathMntBootLimineConf |
| 171 | 171 | ||||
| 172 | mockFS.EXPECT().Stat(bootloaderPath).Return(mockFileInfo{}, nil).Times(1) | 172 | mockFS.EXPECT().Stat(bootloaderPath).Return(mockFileInfo{}, nil).Times(1) | ||
| 173 | mockFS.EXPECT().IsNotExist(gomock.Any()).Return(false).Times(1) | 173 | mockFS.EXPECT().IsNotExist(gomock.Any()).Return(false).Times(1) | ||
| @@ -191,7 +191,7 @@ func TestBootPhasePostCheck(t *testing.T) { | |||||
| 191 | name: "Config missing", | 191 | name: "Config missing", | ||
| 192 | setupMocks: func(mockFS *mocks.MockFileSystem) { | 192 | setupMocks: func(mockFS *mocks.MockFileSystem) { | ||
| 193 | bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader) | 193 | bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader) | ||
| 194 | - | configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 194 | + | configPath := config.PathMntBootLimineConf |
| 195 | 195 | ||||
| 196 | mockFS.EXPECT().Stat(bootloaderPath).Return(mockFileInfo{}, nil).Times(1) | 196 | mockFS.EXPECT().Stat(bootloaderPath).Return(mockFileInfo{}, nil).Times(1) | ||
| 197 | mockFS.EXPECT().IsNotExist(gomock.Any()).Return(false).Times(1) | 197 | mockFS.EXPECT().IsNotExist(gomock.Any()).Return(false).Times(1) | ||
| @@ -244,9 +244,9 @@ func TestBootPhasePostCheck(t *testing.T) { | |||||
| 244 | // TestBootPhaseRollback tests boot phase rollback | 244 | // TestBootPhaseRollback tests boot phase rollback | ||
| 245 | func TestBootPhaseRollback(t *testing.T) { | 245 | func TestBootPhaseRollback(t *testing.T) { | ||
| 246 | tests := []struct { | 246 | tests := []struct { | ||
| 247 | - | name string | 247 | + | name string |
| 248 | - | setupMocks func(*mocks.MockFileSystem) | 248 | + | setupMocks func(*mocks.MockFileSystem) |
| 249 | - | wantErr bool | 249 | + | wantErr bool |
| 250 | }{ | 250 | }{ | ||
| 251 | { | 251 | { | ||
| 252 | name: "Rollback success", | 252 | name: "Rollback success", | ||
| @@ -423,9 +423,9 @@ func TestBootPhaseKernelParameterConstruction(t *testing.T) { | |||||
| 423 | // TestBootPhaseInstallPathConstruction tests install path building | 423 | // TestBootPhaseInstallPathConstruction tests install path building | ||
| 424 | func TestBootPhaseInstallPathConstruction(t *testing.T) { | 424 | func TestBootPhaseInstallPathConstruction(t *testing.T) { | ||
| 425 | tests := []struct { | 425 | tests := []struct { | ||
| 426 | - | name string | 426 | + | name string |
| 427 | - | filename string | 427 | + | filename string |
| 428 | - | expected string | 428 | + | expected string |
| 429 | }{ | 429 | }{ | ||
| 430 | { | 430 | { | ||
| 431 | name: "Limine config template", | 431 | name: "Limine config template", | ||
| @@ -470,8 +470,8 @@ func TestBootPhaseInstallPathConstruction(t *testing.T) { | |||||
| 470 | // TestBootPhaseFileSystemOperations tests file system interaction patterns | 470 | // TestBootPhaseFileSystemOperations tests file system interaction patterns | ||
| 471 | func TestBootPhaseFileSystemOperations(t *testing.T) { | 471 | func TestBootPhaseFileSystemOperations(t *testing.T) { | ||
| 472 | tests := []struct { | 472 | tests := []struct { | ||
| 473 | - | name string | 473 | + | name string |
| 474 | - | operation string // "read", "write", "mkdir" | 474 | + | operation string // "read", "write", "mkdir" |
| 475 | }{ | 475 | }{ | ||
| 476 | { | 476 | { | ||
| 477 | name: "Mkinitcpio config read", | 477 | name: "Mkinitcpio config read", | ||
M internal/phases/bootstrap_test.go +3 -3
| @@ -17,9 +17,9 @@ import ( | |||
| 17 | 17 | // TestBootstrapPhasePreCheck tests internet connectivity validation | |
| 18 | 18 | func TestBootstrapPhasePreCheck(t *testing.T) { | |
| 19 | 19 | tests := []struct { | |
| 20 | - | name string | |
| 21 | - | setupMocks func(*mocks.MockHTTPClient) | |
| 22 | - | wantErr bool | |
| 20 | + | name string | |
| 21 | + | setupMocks func(*mocks.MockHTTPClient) | |
| 22 | + | wantErr bool | |
| 23 | 23 | errContains string | |
| 24 | 24 | }{ | |
| 25 | 25 | { | |
| @@ -17,9 +17,9 @@ import ( | |||||
| 17 | // TestBootstrapPhasePreCheck tests internet connectivity validation | 17 | // TestBootstrapPhasePreCheck tests internet connectivity validation | ||
| 18 | func TestBootstrapPhasePreCheck(t *testing.T) { | 18 | func TestBootstrapPhasePreCheck(t *testing.T) { | ||
| 19 | tests := []struct { | 19 | tests := []struct { | ||
| 20 | - | name string | 20 | + | name string |
| 21 | - | setupMocks func(*mocks.MockHTTPClient) | 21 | + | setupMocks func(*mocks.MockHTTPClient) |
| 22 | - | wantErr bool | 22 | + | wantErr bool |
| 23 | errContains string | 23 | errContains string | ||
| 24 | }{ | 24 | }{ | ||
| 25 | { | 25 | { | ||
M internal/phases/partitioning_test.go +12 -12
| @@ -16,10 +16,10 @@ import ( | |||
| 16 | 16 | // TestPartitioningPhasePreCheck tests partitioning prerequisites | |
| 17 | 17 | func TestPartitioningPhasePreCheck(t *testing.T) { | |
| 18 | 18 | tests := []struct { | |
| 19 | - | name string | |
| 20 | - | targetDisk string | |
| 21 | - | wantErr bool | |
| 22 | - | errContains string | |
| 19 | + | name string | |
| 20 | + | targetDisk string | |
| 21 | + | wantErr bool | |
| 22 | + | errContains string | |
| 23 | 23 | }{ | |
| 24 | 24 | { | |
| 25 | 25 | name: "Valid target disk", | |
| @@ -78,10 +78,10 @@ func TestPartitioningPhasePreCheck(t *testing.T) { | |||
| 78 | 78 | // TestPartitioningPhasePartitionNaming tests partition naming logic | |
| 79 | 79 | func TestPartitioningPhasePartitionNaming(t *testing.T) { | |
| 80 | 80 | tests := []struct { | |
| 81 | - | name string | |
| 82 | - | targetDisk string | |
| 83 | - | expectedEFI string | |
| 84 | - | expectedRoot string | |
| 81 | + | name string | |
| 82 | + | targetDisk string | |
| 83 | + | expectedEFI string | |
| 84 | + | expectedRoot string | |
| 85 | 85 | }{ | |
| 86 | 86 | { | |
| 87 | 87 | name: "NVMe disk naming", | |
| @@ -262,10 +262,10 @@ func TestPartitioningPhaseEncryptionValidation(t *testing.T) { | |||
| 262 | 262 | // TestPartitioningPhasePostCheck tests mount point validation | |
| 263 | 263 | func TestPartitioningPhasePostCheck(t *testing.T) { | |
| 264 | 264 | tests := []struct { | |
| 265 | - | name string | |
| 266 | - | setupMocks func(*mocks.MockSystemExecutor) | |
| 267 | - | wantErr bool | |
| 268 | - | errContains string | |
| 265 | + | name string | |
| 266 | + | setupMocks func(*mocks.MockSystemExecutor) | |
| 267 | + | wantErr bool | |
| 268 | + | errContains string | |
| 269 | 269 | }{ | |
| 270 | 270 | { | |
| 271 | 271 | name: "/mnt is mounted - postcheck passes", | |
| @@ -16,10 +16,10 @@ import ( | |||||
| 16 | // TestPartitioningPhasePreCheck tests partitioning prerequisites | 16 | // TestPartitioningPhasePreCheck tests partitioning prerequisites | ||
| 17 | func TestPartitioningPhasePreCheck(t *testing.T) { | 17 | func TestPartitioningPhasePreCheck(t *testing.T) { | ||
| 18 | tests := []struct { | 18 | tests := []struct { | ||
| 19 | - | name string | 19 | + | name string |
| 20 | - | targetDisk string | 20 | + | targetDisk string |
| 21 | - | wantErr bool | 21 | + | wantErr bool |
| 22 | - | errContains string | 22 | + | errContains string |
| 23 | }{ | 23 | }{ | ||
| 24 | { | 24 | { | ||
| 25 | name: "Valid target disk", | 25 | name: "Valid target disk", | ||
| @@ -78,10 +78,10 @@ func TestPartitioningPhasePreCheck(t *testing.T) { | |||||
| 78 | // TestPartitioningPhasePartitionNaming tests partition naming logic | 78 | // TestPartitioningPhasePartitionNaming tests partition naming logic | ||
| 79 | func TestPartitioningPhasePartitionNaming(t *testing.T) { | 79 | func TestPartitioningPhasePartitionNaming(t *testing.T) { | ||
| 80 | tests := []struct { | 80 | tests := []struct { | ||
| 81 | - | name string | 81 | + | name string |
| 82 | - | targetDisk string | 82 | + | targetDisk string |
| 83 | - | expectedEFI string | 83 | + | expectedEFI string |
| 84 | - | expectedRoot string | 84 | + | expectedRoot string |
| 85 | }{ | 85 | }{ | ||
| 86 | { | 86 | { | ||
| 87 | name: "NVMe disk naming", | 87 | name: "NVMe disk naming", | ||
| @@ -262,10 +262,10 @@ func TestPartitioningPhaseEncryptionValidation(t *testing.T) { | |||||
| 262 | // TestPartitioningPhasePostCheck tests mount point validation | 262 | // TestPartitioningPhasePostCheck tests mount point validation | ||
| 263 | func TestPartitioningPhasePostCheck(t *testing.T) { | 263 | func TestPartitioningPhasePostCheck(t *testing.T) { | ||
| 264 | tests := []struct { | 264 | tests := []struct { | ||
| 265 | - | name string | 265 | + | name string |
| 266 | - | setupMocks func(*mocks.MockSystemExecutor) | 266 | + | setupMocks func(*mocks.MockSystemExecutor) |
| 267 | - | wantErr bool | 267 | + | wantErr bool |
| 268 | - | errContains string | 268 | + | errContains string |
| 269 | }{ | 269 | }{ | ||
| 270 | { | 270 | { | ||
| 271 | name: "/mnt is mounted - postcheck passes", | 271 | name: "/mnt is mounted - postcheck passes", | ||
M internal/phases/phase.go +8 -8
| @@ -44,14 +44,14 @@ type PhaseResult struct { | |||
| 44 | 44 | ||
| 45 | 45 | // ProgressUpdate represents a progress update from a phase | |
| 46 | 46 | type ProgressUpdate struct { | |
| 47 | - | PhaseName string | |
| 48 | - | Step string | |
| 49 | - | OutputLine string | |
| 50 | - | Current int | |
| 51 | - | Total int | |
| 52 | - | IsComplete bool | |
| 53 | - | IsError bool | |
| 54 | - | ErrorMsg string | |
| 47 | + | PhaseName string | |
| 48 | + | Step string | |
| 49 | + | OutputLine string | |
| 50 | + | Current int | |
| 51 | + | Total int | |
| 52 | + | IsComplete bool | |
| 53 | + | IsError bool | |
| 54 | + | ErrorMsg string | |
| 55 | 55 | } | |
| 56 | 56 | ||
| 57 | 57 | // Phase represents a single installation phase | |
| @@ -44,14 +44,14 @@ type PhaseResult struct { | |||||
| 44 | 44 | ||||
| 45 | // ProgressUpdate represents a progress update from a phase | 45 | // ProgressUpdate represents a progress update from a phase | ||
| 46 | type ProgressUpdate struct { | 46 | type ProgressUpdate struct { | ||
| 47 | - | PhaseName string | 47 | + | PhaseName string |
| 48 | - | Step string | 48 | + | Step string |
| 49 | - | OutputLine string | 49 | + | OutputLine string |
| 50 | - | Current int | 50 | + | Current int |
| 51 | - | Total int | 51 | + | Total int |
| 52 | - | IsComplete bool | 52 | + | IsComplete bool |
| 53 | - | IsError bool | 53 | + | IsError bool |
| 54 | - | ErrorMsg string | 54 | + | ErrorMsg string |
| 55 | } | 55 | } | ||
| 56 | 56 | ||||
| 57 | // Phase represents a single installation phase | 57 | // Phase represents a single installation phase | ||
M internal/phases/postinstall.go +8 -8
| @@ -178,7 +178,7 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e | |||
| 178 | 178 | p.SendOutput(progressChan, "[OK] Logo downloaded") | |
| 179 | 179 | ||
| 180 | 180 | // Update Limine config | |
| 181 | - | limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 181 | + | limineConf := config.PathMntBootLimineConf | |
| 182 | 182 | content, err := p.fs.ReadFile(limineConf) | |
| 183 | 183 | switch { | |
| 184 | 184 | case err != nil: | |
| @@ -264,7 +264,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate) | |||
| 264 | 264 | ||
| 265 | 265 | // Set as default theme | |
| 266 | 266 | setThemeCmd := fmt.Sprintf("plymouth-set-default-theme %s", config.PlymouthThemeName) | |
| 267 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, setThemeCmd); { | |
| 267 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, setThemeCmd); { | |
| 268 | 268 | case err != nil: | |
| 269 | 269 | return fmt.Errorf("failed to set Plymouth theme: %w", err) | |
| 270 | 270 | } | |
| @@ -273,7 +273,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate) | |||
| 273 | 273 | ||
| 274 | 274 | // Regenerate initramfs | |
| 275 | 275 | p.SendOutput(progressChan, "Regenerating initramfs with Plymouth...") | |
| 276 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); { | |
| 276 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "mkinitcpio -P"); { | |
| 277 | 277 | case err != nil: | |
| 278 | 278 | return fmt.Errorf("failed to regenerate initramfs: %w", err) | |
| 279 | 279 | } | |
| @@ -287,7 +287,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate) | |||
| 287 | 287 | p.SendOutput(progressChan, "Installing limine-snapper-sync...") | |
| 288 | 288 | ||
| 289 | 289 | // Install limine-snapper-sync | |
| 290 | - | switch err := p.chrExec.ChrootPacman(p.logger.LogPath(),config.PathMnt, "-S", "--needed", "limine-snapper-sync"); { | |
| 290 | + | switch err := p.chrExec.ChrootPacman(p.logger.LogPath(), config.PathMnt, "-S", "--needed", "limine-snapper-sync"); { | |
| 291 | 291 | case err != nil: | |
| 292 | 292 | return fmt.Errorf("failed to install limine-snapper-sync: %w", err) | |
| 293 | 293 | } | |
| @@ -295,7 +295,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate) | |||
| 295 | 295 | p.SendOutput(progressChan, "[OK] Package installed") | |
| 296 | 296 | ||
| 297 | 297 | // Get kernel cmdline from existing Limine config | |
| 298 | - | limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 298 | + | limineConf := config.PathMntBootLimineConf | |
| 299 | 299 | content, err := p.fs.ReadFile(limineConf) | |
| 300 | 300 | switch { | |
| 301 | 301 | case err != nil: | |
| @@ -511,7 +511,7 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er | |||
| 511 | 511 | } | |
| 512 | 512 | ||
| 513 | 513 | for _, gitCmd := range gitCommands { | |
| 514 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, gitCmd); { | |
| 514 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, gitCmd); { | |
| 515 | 515 | case err != nil: | |
| 516 | 516 | // Non-fatal | |
| 517 | 517 | p.SendOutput(progressChan, "[WARN] Failed to configure git delta") | |
| @@ -563,7 +563,7 @@ func (p *PostInstallPhase) setShellOwnership(userHome, username string) error { | |||
| 563 | 563 | relativeHome := strings.TrimPrefix(userHome, config.PathMnt) | |
| 564 | 564 | chownCmd := fmt.Sprintf("chown -R %s:%s %s/.local %s/.bashrc", | |
| 565 | 565 | username, username, relativeHome, relativeHome) | |
| 566 | - | return p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, chownCmd) | |
| 566 | + | return p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, chownCmd) | |
| 567 | 567 | } | |
| 568 | 568 | ||
| 569 | 569 | // applyThemes applies bleu-theme to CLI tools | |
| @@ -664,7 +664,7 @@ func (p *PostInstallPhase) verifyInstallation(progressChan chan<- ProgressUpdate | |||
| 664 | 664 | } | |
| 665 | 665 | ||
| 666 | 666 | // Verify Limine config | |
| 667 | - | limineConfPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | |
| 667 | + | limineConfPath := config.PathMntBootLimineConf | |
| 668 | 668 | switch content, err := p.fs.ReadFile(limineConfPath); { | |
| 669 | 669 | case err != nil: | |
| 670 | 670 | p.SendOutput(progressChan, "[ERROR] Limine config missing") | |
| @@ -178,7 +178,7 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e | |||||
| 178 | p.SendOutput(progressChan, "[OK] Logo downloaded") | 178 | p.SendOutput(progressChan, "[OK] Logo downloaded") | ||
| 179 | 179 | ||||
| 180 | // Update Limine config | 180 | // Update Limine config | ||
| 181 | - | limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 181 | + | limineConf := config.PathMntBootLimineConf |
| 182 | content, err := p.fs.ReadFile(limineConf) | 182 | content, err := p.fs.ReadFile(limineConf) | ||
| 183 | switch { | 183 | switch { | ||
| 184 | case err != nil: | 184 | case err != nil: | ||
| @@ -264,7 +264,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate) | |||||
| 264 | 264 | ||||
| 265 | // Set as default theme | 265 | // Set as default theme | ||
| 266 | setThemeCmd := fmt.Sprintf("plymouth-set-default-theme %s", config.PlymouthThemeName) | 266 | setThemeCmd := fmt.Sprintf("plymouth-set-default-theme %s", config.PlymouthThemeName) | ||
| 267 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, setThemeCmd); { | 267 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, setThemeCmd); { |
| 268 | case err != nil: | 268 | case err != nil: | ||
| 269 | return fmt.Errorf("failed to set Plymouth theme: %w", err) | 269 | return fmt.Errorf("failed to set Plymouth theme: %w", err) | ||
| 270 | } | 270 | } | ||
| @@ -273,7 +273,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate) | |||||
| 273 | 273 | ||||
| 274 | // Regenerate initramfs | 274 | // Regenerate initramfs | ||
| 275 | p.SendOutput(progressChan, "Regenerating initramfs with Plymouth...") | 275 | p.SendOutput(progressChan, "Regenerating initramfs with Plymouth...") | ||
| 276 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); { | 276 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "mkinitcpio -P"); { |
| 277 | case err != nil: | 277 | case err != nil: | ||
| 278 | return fmt.Errorf("failed to regenerate initramfs: %w", err) | 278 | return fmt.Errorf("failed to regenerate initramfs: %w", err) | ||
| 279 | } | 279 | } | ||
| @@ -287,7 +287,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate) | |||||
| 287 | p.SendOutput(progressChan, "Installing limine-snapper-sync...") | 287 | p.SendOutput(progressChan, "Installing limine-snapper-sync...") | ||
| 288 | 288 | ||||
| 289 | // Install limine-snapper-sync | 289 | // Install limine-snapper-sync | ||
| 290 | - | switch err := p.chrExec.ChrootPacman(p.logger.LogPath(),config.PathMnt, "-S", "--needed", "limine-snapper-sync"); { | 290 | + | switch err := p.chrExec.ChrootPacman(p.logger.LogPath(), config.PathMnt, "-S", "--needed", "limine-snapper-sync"); { |
| 291 | case err != nil: | 291 | case err != nil: | ||
| 292 | return fmt.Errorf("failed to install limine-snapper-sync: %w", err) | 292 | return fmt.Errorf("failed to install limine-snapper-sync: %w", err) | ||
| 293 | } | 293 | } | ||
| @@ -295,7 +295,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate) | |||||
| 295 | p.SendOutput(progressChan, "[OK] Package installed") | 295 | p.SendOutput(progressChan, "[OK] Package installed") | ||
| 296 | 296 | ||||
| 297 | // Get kernel cmdline from existing Limine config | 297 | // Get kernel cmdline from existing Limine config | ||
| 298 | - | limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 298 | + | limineConf := config.PathMntBootLimineConf |
| 299 | content, err := p.fs.ReadFile(limineConf) | 299 | content, err := p.fs.ReadFile(limineConf) | ||
| 300 | switch { | 300 | switch { | ||
| 301 | case err != nil: | 301 | case err != nil: | ||
| @@ -511,7 +511,7 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er | |||||
| 511 | } | 511 | } | ||
| 512 | 512 | ||||
| 513 | for _, gitCmd := range gitCommands { | 513 | for _, gitCmd := range gitCommands { | ||
| 514 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, gitCmd); { | 514 | + | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, gitCmd); { |
| 515 | case err != nil: | 515 | case err != nil: | ||
| 516 | // Non-fatal | 516 | // Non-fatal | ||
| 517 | p.SendOutput(progressChan, "[WARN] Failed to configure git delta") | 517 | p.SendOutput(progressChan, "[WARN] Failed to configure git delta") | ||
| @@ -563,7 +563,7 @@ func (p *PostInstallPhase) setShellOwnership(userHome, username string) error { | |||||
| 563 | relativeHome := strings.TrimPrefix(userHome, config.PathMnt) | 563 | relativeHome := strings.TrimPrefix(userHome, config.PathMnt) | ||
| 564 | chownCmd := fmt.Sprintf("chown -R %s:%s %s/.local %s/.bashrc", | 564 | chownCmd := fmt.Sprintf("chown -R %s:%s %s/.local %s/.bashrc", | ||
| 565 | username, username, relativeHome, relativeHome) | 565 | username, username, relativeHome, relativeHome) | ||
| 566 | - | return p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, chownCmd) | 566 | + | return p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, chownCmd) |
| 567 | } | 567 | } | ||
| 568 | 568 | ||||
| 569 | // applyThemes applies bleu-theme to CLI tools | 569 | // applyThemes applies bleu-theme to CLI tools | ||
| @@ -664,7 +664,7 @@ func (p *PostInstallPhase) verifyInstallation(progressChan chan<- ProgressUpdate | |||||
| 664 | } | 664 | } | ||
| 665 | 665 | ||||
| 666 | // Verify Limine config | 666 | // Verify Limine config | ||
| 667 | - | limineConfPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig) | 667 | + | limineConfPath := config.PathMntBootLimineConf |
| 668 | switch content, err := p.fs.ReadFile(limineConfPath); { | 668 | switch content, err := p.fs.ReadFile(limineConfPath); { | ||
| 669 | case err != nil: | 669 | case err != nil: | ||
| 670 | p.SendOutput(progressChan, "[ERROR] Limine config missing") | 670 | p.SendOutput(progressChan, "[ERROR] Limine config missing") | ||
M internal/phases/postinstall_test.go +8 -8
| @@ -15,10 +15,10 @@ import ( | |||
| 15 | 15 | // TestPostInstallPhasePreCheck tests post-install prerequisites | |
| 16 | 16 | func TestPostInstallPhasePreCheck(t *testing.T) { | |
| 17 | 17 | tests := []struct { | |
| 18 | - | name string | |
| 19 | - | setupMocks func(*mocks.MockFileSystem, *mocks.MockSystemExecutor) | |
| 20 | - | wantErr bool | |
| 21 | - | errContains string | |
| 18 | + | name string | |
| 19 | + | setupMocks func(*mocks.MockFileSystem, *mocks.MockSystemExecutor) | |
| 20 | + | wantErr bool | |
| 21 | + | errContains string | |
| 22 | 22 | }{ | |
| 23 | 23 | { | |
| 24 | 24 | name: "/mnt mounted and boot directory exists", | |
| @@ -270,8 +270,8 @@ func TestPostInstallPhaseExecute(t *testing.T) { | |||
| 270 | 270 | // TestPostInstallPhaseEncryptionHandling tests encryption-aware operations | |
| 271 | 271 | func TestPostInstallPhaseEncryptionHandling(t *testing.T) { | |
| 272 | 272 | tests := []struct { | |
| 273 | - | name string | |
| 274 | - | encryptionType string | |
| 273 | + | name string | |
| 274 | + | encryptionType string | |
| 275 | 275 | expectedClosing bool | |
| 276 | 276 | }{ | |
| 277 | 277 | { | |
| @@ -331,8 +331,8 @@ func TestPostInstallPhaseEncryptionHandling(t *testing.T) { | |||
| 331 | 331 | // TestPostInstallPhaseFileSystemOperations tests file system interaction patterns | |
| 332 | 332 | func TestPostInstallPhaseFileSystemOperations(t *testing.T) { | |
| 333 | 333 | tests := []struct { | |
| 334 | - | name string | |
| 335 | - | operation string // "read", "write", "mkdir", "create" | |
| 334 | + | name string | |
| 335 | + | operation string // "read", "write", "mkdir", "create" | |
| 336 | 336 | }{ | |
| 337 | 337 | { | |
| 338 | 338 | name: "Read pacman.conf", | |
| @@ -15,10 +15,10 @@ import ( | |||||
| 15 | // TestPostInstallPhasePreCheck tests post-install prerequisites | 15 | // TestPostInstallPhasePreCheck tests post-install prerequisites | ||
| 16 | func TestPostInstallPhasePreCheck(t *testing.T) { | 16 | func TestPostInstallPhasePreCheck(t *testing.T) { | ||
| 17 | tests := []struct { | 17 | tests := []struct { | ||
| 18 | - | name string | 18 | + | name string |
| 19 | - | setupMocks func(*mocks.MockFileSystem, *mocks.MockSystemExecutor) | 19 | + | setupMocks func(*mocks.MockFileSystem, *mocks.MockSystemExecutor) |
| 20 | - | wantErr bool | 20 | + | wantErr bool |
| 21 | - | errContains string | 21 | + | errContains string |
| 22 | }{ | 22 | }{ | ||
| 23 | { | 23 | { | ||
| 24 | name: "/mnt mounted and boot directory exists", | 24 | name: "/mnt mounted and boot directory exists", | ||
| @@ -270,8 +270,8 @@ func TestPostInstallPhaseExecute(t *testing.T) { | |||||
| 270 | // TestPostInstallPhaseEncryptionHandling tests encryption-aware operations | 270 | // TestPostInstallPhaseEncryptionHandling tests encryption-aware operations | ||
| 271 | func TestPostInstallPhaseEncryptionHandling(t *testing.T) { | 271 | func TestPostInstallPhaseEncryptionHandling(t *testing.T) { | ||
| 272 | tests := []struct { | 272 | tests := []struct { | ||
| 273 | - | name string | 273 | + | name string |
| 274 | - | encryptionType string | 274 | + | encryptionType string |
| 275 | expectedClosing bool | 275 | expectedClosing bool | ||
| 276 | }{ | 276 | }{ | ||
| 277 | { | 277 | { | ||
| @@ -331,8 +331,8 @@ func TestPostInstallPhaseEncryptionHandling(t *testing.T) { | |||||
| 331 | // TestPostInstallPhaseFileSystemOperations tests file system interaction patterns | 331 | // TestPostInstallPhaseFileSystemOperations tests file system interaction patterns | ||
| 332 | func TestPostInstallPhaseFileSystemOperations(t *testing.T) { | 332 | func TestPostInstallPhaseFileSystemOperations(t *testing.T) { | ||
| 333 | tests := []struct { | 333 | tests := []struct { | ||
| 334 | - | name string | 334 | + | name string |
| 335 | - | operation string // "read", "write", "mkdir", "create" | 335 | + | operation string // "read", "write", "mkdir", "create" |
| 336 | }{ | 336 | }{ | ||
| 337 | { | 337 | { | ||
| 338 | name: "Read pacman.conf", | 338 | name: "Read pacman.conf", | ||
M internal/phases/preflight_test.go +4 -4
| @@ -14,10 +14,10 @@ import ( | |||
| 14 | 14 | // TestPreflightPhasePreCheck tests the PreCheck validation | |
| 15 | 15 | func TestPreflightPhasePreCheck(t *testing.T) { | |
| 16 | 16 | tests := []struct { | |
| 17 | - | name string | |
| 18 | - | setupMocks func(*mocks.MockFileSystem, *mocks.MockCommandExecutor) | |
| 19 | - | wantErr bool | |
| 20 | - | errContains string | |
| 17 | + | name string | |
| 18 | + | setupMocks func(*mocks.MockFileSystem, *mocks.MockCommandExecutor) | |
| 19 | + | wantErr bool | |
| 20 | + | errContains string | |
| 21 | 21 | }{ | |
| 22 | 22 | { | |
| 23 | 23 | name: "Arch Linux detection - file not found", | |
| @@ -14,10 +14,10 @@ import ( | |||||
| 14 | // TestPreflightPhasePreCheck tests the PreCheck validation | 14 | // TestPreflightPhasePreCheck tests the PreCheck validation | ||
| 15 | func TestPreflightPhasePreCheck(t *testing.T) { | 15 | func TestPreflightPhasePreCheck(t *testing.T) { | ||
| 16 | tests := []struct { | 16 | tests := []struct { | ||
| 17 | - | name string | 17 | + | name string |
| 18 | - | setupMocks func(*mocks.MockFileSystem, *mocks.MockCommandExecutor) | 18 | + | setupMocks func(*mocks.MockFileSystem, *mocks.MockCommandExecutor) |
| 19 | - | wantErr bool | 19 | + | wantErr bool |
| 20 | - | errContains string | 20 | + | errContains string |
| 21 | }{ | 21 | }{ | ||
| 22 | { | 22 | { | ||
| 23 | name: "Arch Linux detection - file not found", | 23 | name: "Arch Linux detection - file not found", | ||
M internal/phases/repos.go +5 -5
| @@ -46,11 +46,11 @@ func IsValidAURHelper(helper string) bool { | |||
| 46 | 46 | // ReposPhase handles repository configuration | |
| 47 | 47 | type ReposPhase struct { | |
| 48 | 48 | *BasePhase | |
| 49 | - | fs interfaces.FileSystem | |
| 50 | - | sysExec interfaces.SystemExecutor | |
| 51 | - | chrExec interfaces.ChrootExecutor | |
| 52 | - | chaoticConfig map[string]string | |
| 53 | - | chaoticAUREnabled bool | |
| 49 | + | fs interfaces.FileSystem | |
| 50 | + | sysExec interfaces.SystemExecutor | |
| 51 | + | chrExec interfaces.ChrootExecutor | |
| 52 | + | chaoticConfig map[string]string | |
| 53 | + | chaoticAUREnabled bool | |
| 54 | 54 | } | |
| 55 | 55 | ||
| 56 | 56 | // NewReposPhase creates a new repos phase | |
| @@ -46,11 +46,11 @@ func IsValidAURHelper(helper string) bool { | |||||
| 46 | // ReposPhase handles repository configuration | 46 | // ReposPhase handles repository configuration | ||
| 47 | type ReposPhase struct { | 47 | type ReposPhase struct { | ||
| 48 | *BasePhase | 48 | *BasePhase | ||
| 49 | - | fs interfaces.FileSystem | 49 | + | fs interfaces.FileSystem |
| 50 | - | sysExec interfaces.SystemExecutor | 50 | + | sysExec interfaces.SystemExecutor |
| 51 | - | chrExec interfaces.ChrootExecutor | 51 | + | chrExec interfaces.ChrootExecutor |
| 52 | - | chaoticConfig map[string]string | 52 | + | chaoticConfig map[string]string |
| 53 | - | chaoticAUREnabled bool | 53 | + | chaoticAUREnabled bool |
| 54 | } | 54 | } | ||
| 55 | 55 | ||||
| 56 | // NewReposPhase creates a new repos phase | 56 | // NewReposPhase creates a new repos phase | ||
M internal/phases/repos_test.go +6 -6
| @@ -127,8 +127,8 @@ func TestMultilibEdgeCases(t *testing.T) { | |||
| 127 | 127 | checkFunc func(string) bool | |
| 128 | 128 | }{ | |
| 129 | 129 | { | |
| 130 | - | name: "Empty file", | |
| 131 | - | input: "", | |
| 130 | + | name: "Empty file", | |
| 131 | + | input: "", | |
| 132 | 132 | expectError: false, | |
| 133 | 133 | checkFunc: func(s string) bool { | |
| 134 | 134 | return s == "" | |
| @@ -652,8 +652,8 @@ func TestPackageFiltering(t *testing.T) { | |||
| 652 | 652 | wantError: false, | |
| 653 | 653 | }, | |
| 654 | 654 | { | |
| 655 | - | name: "only debug package (should filter all)", | |
| 656 | - | output: `/tmp/yay/yay-debug-12.5.2-2-x86_64.pkg.tar.zst`, | |
| 655 | + | name: "only debug package (should filter all)", | |
| 656 | + | output: `/tmp/yay/yay-debug-12.5.2-2-x86_64.pkg.tar.zst`, | |
| 657 | 657 | wantPackage: "", | |
| 658 | 658 | wantError: true, | |
| 659 | 659 | }, | |
| @@ -664,8 +664,8 @@ func TestPackageFiltering(t *testing.T) { | |||
| 664 | 664 | wantError: true, | |
| 665 | 665 | }, | |
| 666 | 666 | { | |
| 667 | - | name: "single main package without debug", | |
| 668 | - | output: `/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst`, | |
| 667 | + | name: "single main package without debug", | |
| 668 | + | output: `/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst`, | |
| 669 | 669 | wantPackage: "/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst", | |
| 670 | 670 | wantError: false, | |
| 671 | 671 | }, | |
| @@ -127,8 +127,8 @@ func TestMultilibEdgeCases(t *testing.T) { | |||||
| 127 | checkFunc func(string) bool | 127 | checkFunc func(string) bool | ||
| 128 | }{ | 128 | }{ | ||
| 129 | { | 129 | { | ||
| 130 | - | name: "Empty file", | 130 | + | name: "Empty file", |
| 131 | - | input: "", | 131 | + | input: "", |
| 132 | expectError: false, | 132 | expectError: false, | ||
| 133 | checkFunc: func(s string) bool { | 133 | checkFunc: func(s string) bool { | ||
| 134 | return s == "" | 134 | return s == "" | ||
| @@ -652,8 +652,8 @@ func TestPackageFiltering(t *testing.T) { | |||||
| 652 | wantError: false, | 652 | wantError: false, | ||
| 653 | }, | 653 | }, | ||
| 654 | { | 654 | { | ||
| 655 | - | name: "only debug package (should filter all)", | 655 | + | name: "only debug package (should filter all)", |
| 656 | - | output: `/tmp/yay/yay-debug-12.5.2-2-x86_64.pkg.tar.zst`, | 656 | + | output: `/tmp/yay/yay-debug-12.5.2-2-x86_64.pkg.tar.zst`, |
| 657 | wantPackage: "", | 657 | wantPackage: "", | ||
| 658 | wantError: true, | 658 | wantError: true, | ||
| 659 | }, | 659 | }, | ||
| @@ -664,8 +664,8 @@ func TestPackageFiltering(t *testing.T) { | |||||
| 664 | wantError: true, | 664 | wantError: true, | ||
| 665 | }, | 665 | }, | ||
| 666 | { | 666 | { | ||
| 667 | - | name: "single main package without debug", | 667 | + | name: "single main package without debug", |
| 668 | - | output: `/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst`, | 668 | + | output: `/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst`, |
| 669 | wantPackage: "/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst", | 669 | wantPackage: "/tmp/yay/yay-12.5.2-2-x86_64.pkg.tar.zst", | ||
| 670 | wantError: false, | 670 | wantError: false, | ||
| 671 | }, | 671 | }, | ||
M internal/phases/systemconfig.go +5 -5
| @@ -97,12 +97,12 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error | |||
| 97 | 97 | // Set timezone | |
| 98 | 98 | timezonePath := filepath.Join(config.PathUsrShareZoneinfo, p.config.Timezone) | |
| 99 | 99 | tzCmd := fmt.Sprintf("ln -sf %s %s", timezonePath, config.PathEtcLocaltime) | |
| 100 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, tzCmd); err != nil { | |
| 100 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, tzCmd); err != nil { | |
| 101 | 101 | return fmt.Errorf("failed to set timezone: %w", err) | |
| 102 | 102 | } | |
| 103 | 103 | ||
| 104 | 104 | // Set hardware clock | |
| 105 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "hwclock --systohc"); err != nil { | |
| 105 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "hwclock --systohc"); err != nil { | |
| 106 | 106 | return fmt.Errorf("failed to set hardware clock: %w", err) | |
| 107 | 107 | } | |
| 108 | 108 | ||
| @@ -114,7 +114,7 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error | |||
| 114 | 114 | return fmt.Errorf("failed to write locale.gen: %w", err) | |
| 115 | 115 | } | |
| 116 | 116 | ||
| 117 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "locale-gen"); err != nil { | |
| 117 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "locale-gen"); err != nil { | |
| 118 | 118 | return fmt.Errorf("failed to generate locale: %w", err) | |
| 119 | 119 | } | |
| 120 | 120 | ||
| @@ -159,7 +159,7 @@ func (p *ConfigPhase) configureNetwork(progressChan chan<- ProgressUpdate) error | |||
| 159 | 159 | p.SendOutput(progressChan, "Configuring network...") | |
| 160 | 160 | ||
| 161 | 161 | // Enable NetworkManager service | |
| 162 | - | if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(),config.PathMnt, "enable", config.ServiceNetworkManager); err != nil { | |
| 162 | + | if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", config.ServiceNetworkManager); err != nil { | |
| 163 | 163 | return fmt.Errorf("failed to enable NetworkManager: %w", err) | |
| 164 | 164 | } | |
| 165 | 165 | ||
| @@ -174,7 +174,7 @@ func (p *ConfigPhase) createUser(progressChan chan<- ProgressUpdate) error { | |||
| 174 | 174 | ||
| 175 | 175 | // Create user with home directory | |
| 176 | 176 | userAddCmd := fmt.Sprintf("useradd -m -G %s -s %s %s", config.GroupWheel, config.ShellBash, p.config.Username) | |
| 177 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, userAddCmd); err != nil { | |
| 177 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, userAddCmd); err != nil { | |
| 178 | 178 | return fmt.Errorf("failed to create user: %w", err) | |
| 179 | 179 | } | |
| 180 | 180 | ||
| @@ -97,12 +97,12 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error | |||||
| 97 | // Set timezone | 97 | // Set timezone | ||
| 98 | timezonePath := filepath.Join(config.PathUsrShareZoneinfo, p.config.Timezone) | 98 | timezonePath := filepath.Join(config.PathUsrShareZoneinfo, p.config.Timezone) | ||
| 99 | tzCmd := fmt.Sprintf("ln -sf %s %s", timezonePath, config.PathEtcLocaltime) | 99 | tzCmd := fmt.Sprintf("ln -sf %s %s", timezonePath, config.PathEtcLocaltime) | ||
| 100 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, tzCmd); err != nil { | 100 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, tzCmd); err != nil { |
| 101 | return fmt.Errorf("failed to set timezone: %w", err) | 101 | return fmt.Errorf("failed to set timezone: %w", err) | ||
| 102 | } | 102 | } | ||
| 103 | 103 | ||||
| 104 | // Set hardware clock | 104 | // Set hardware clock | ||
| 105 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "hwclock --systohc"); err != nil { | 105 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "hwclock --systohc"); err != nil { |
| 106 | return fmt.Errorf("failed to set hardware clock: %w", err) | 106 | return fmt.Errorf("failed to set hardware clock: %w", err) | ||
| 107 | } | 107 | } | ||
| 108 | 108 | ||||
| @@ -114,7 +114,7 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error | |||||
| 114 | return fmt.Errorf("failed to write locale.gen: %w", err) | 114 | return fmt.Errorf("failed to write locale.gen: %w", err) | ||
| 115 | } | 115 | } | ||
| 116 | 116 | ||||
| 117 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "locale-gen"); err != nil { | 117 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "locale-gen"); err != nil { |
| 118 | return fmt.Errorf("failed to generate locale: %w", err) | 118 | return fmt.Errorf("failed to generate locale: %w", err) | ||
| 119 | } | 119 | } | ||
| 120 | 120 | ||||
| @@ -159,7 +159,7 @@ func (p *ConfigPhase) configureNetwork(progressChan chan<- ProgressUpdate) error | |||||
| 159 | p.SendOutput(progressChan, "Configuring network...") | 159 | p.SendOutput(progressChan, "Configuring network...") | ||
| 160 | 160 | ||||
| 161 | // Enable NetworkManager service | 161 | // Enable NetworkManager service | ||
| 162 | - | if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(),config.PathMnt, "enable", config.ServiceNetworkManager); err != nil { | 162 | + | if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", config.ServiceNetworkManager); err != nil { |
| 163 | return fmt.Errorf("failed to enable NetworkManager: %w", err) | 163 | return fmt.Errorf("failed to enable NetworkManager: %w", err) | ||
| 164 | } | 164 | } | ||
| 165 | 165 | ||||
| @@ -174,7 +174,7 @@ func (p *ConfigPhase) createUser(progressChan chan<- ProgressUpdate) error { | |||||
| 174 | 174 | ||||
| 175 | // Create user with home directory | 175 | // Create user with home directory | ||
| 176 | userAddCmd := fmt.Sprintf("useradd -m -G %s -s %s %s", config.GroupWheel, config.ShellBash, p.config.Username) | 176 | userAddCmd := fmt.Sprintf("useradd -m -G %s -s %s %s", config.GroupWheel, config.ShellBash, p.config.Username) | ||
| 177 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, userAddCmd); err != nil { | 177 | + | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, userAddCmd); err != nil { |
| 178 | return fmt.Errorf("failed to create user: %w", err) | 178 | return fmt.Errorf("failed to create user: %w", err) | ||
| 179 | } | 179 | } | ||
| 180 | 180 | ||||
M internal/phases/systemconfig_test.go +4 -4
| @@ -129,10 +129,10 @@ func TestConfigPhasePreCheck(t *testing.T) { | |||
| 129 | 129 | // TestConfigPhasePostCheck tests configuration validation | |
| 130 | 130 | func TestConfigPhasePostCheck(t *testing.T) { | |
| 131 | 131 | tests := []struct { | |
| 132 | - | name string | |
| 133 | - | setupMocks func(*mocks.MockFileSystem) | |
| 134 | - | wantErr bool | |
| 135 | - | errContains string | |
| 132 | + | name string | |
| 133 | + | setupMocks func(*mocks.MockFileSystem) | |
| 134 | + | wantErr bool | |
| 135 | + | errContains string | |
| 136 | 136 | }{ | |
| 137 | 137 | { | |
| 138 | 138 | name: "All configuration files exist - postcheck passes", | |
| @@ -129,10 +129,10 @@ func TestConfigPhasePreCheck(t *testing.T) { | |||||
| 129 | // TestConfigPhasePostCheck tests configuration validation | 129 | // TestConfigPhasePostCheck tests configuration validation | ||
| 130 | func TestConfigPhasePostCheck(t *testing.T) { | 130 | func TestConfigPhasePostCheck(t *testing.T) { | ||
| 131 | tests := []struct { | 131 | tests := []struct { | ||
| 132 | - | name string | 132 | + | name string |
| 133 | - | setupMocks func(*mocks.MockFileSystem) | 133 | + | setupMocks func(*mocks.MockFileSystem) |
| 134 | - | wantErr bool | 134 | + | wantErr bool |
| 135 | - | errContains string | 135 | + | errContains string |
| 136 | }{ | 136 | }{ | ||
| 137 | { | 137 | { | ||
| 138 | name: "All configuration files exist - postcheck passes", | 138 | name: "All configuration files exist - postcheck passes", | ||
M internal/postboot/setup.go +0 -2
| @@ -113,7 +113,6 @@ func (s *Setup) Configure() (SetupResult, error) { | |||
| 113 | 113 | } | |
| 114 | 114 | } | |
| 115 | 115 | ||
| 116 | - | ||
| 117 | 116 | // Download service template | |
| 118 | 117 | serviceURL := fmt.Sprintf("%s/%s", s.config.RawURL, config.PostBootServiceTemplate) | |
| 119 | 118 | resp, err = s.http.Get(serviceURL) | |
| @@ -140,7 +139,6 @@ func (s *Setup) Configure() (SetupResult, error) { | |||
| 140 | 139 | return result, fmt.Errorf("failed to write service file: %w", err) | |
| 141 | 140 | } | |
| 142 | 141 | ||
| 143 | - | ||
| 144 | 142 | if err := s.chrExec.ChrootSystemctl(s.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); err != nil { | |
| 145 | 143 | return result, fmt.Errorf("failed to enable service: %w", err) | |
| 146 | 144 | } | |
| @@ -113,7 +113,6 @@ func (s *Setup) Configure() (SetupResult, error) { | |||||
| 113 | } | 113 | } | ||
| 114 | } | 114 | } | ||
| 115 | 115 | ||||
| 116 | - | ||||
| 117 | // Download service template | 116 | // Download service template | ||
| 118 | serviceURL := fmt.Sprintf("%s/%s", s.config.RawURL, config.PostBootServiceTemplate) | 117 | serviceURL := fmt.Sprintf("%s/%s", s.config.RawURL, config.PostBootServiceTemplate) | ||
| 119 | resp, err = s.http.Get(serviceURL) | 118 | resp, err = s.http.Get(serviceURL) | ||
| @@ -140,7 +139,6 @@ func (s *Setup) Configure() (SetupResult, error) { | |||||
| 140 | return result, fmt.Errorf("failed to write service file: %w", err) | 139 | return result, fmt.Errorf("failed to write service file: %w", err) | ||
| 141 | } | 140 | } | ||
| 142 | 141 | ||||
| 143 | - | ||||
| 144 | if err := s.chrExec.ChrootSystemctl(s.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); err != nil { | 142 | if err := s.chrExec.ChrootSystemctl(s.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); err != nil { | ||
| 145 | return result, fmt.Errorf("failed to enable service: %w", err) | 143 | return result, fmt.Errorf("failed to enable service: %w", err) | ||
| 146 | } | 144 | } | ||
M internal/shell/configurator.go +0 -1
| @@ -165,4 +165,3 @@ func (c *Configurator) setShellOwnership(userHome, username string) error { | |||
| 165 | 165 | username, username, relativeHome, relativeHome) | |
| 166 | 166 | return c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, chownCmd) | |
| 167 | 167 | } | |
| 168 | - | ||
| @@ -165,4 +165,3 @@ func (c *Configurator) setShellOwnership(userHome, username string) error { | |||||
| 165 | username, username, relativeHome, relativeHome) | 165 | username, username, relativeHome, relativeHome) | ||
| 166 | return c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, chownCmd) | 166 | return c.chrExec.ChrootExec(c.logger.LogPath(), config.PathMnt, chownCmd) | ||
| 167 | } | 167 | } | ||
| 168 | - | ||||
M internal/system/chroot.go +12 -12
| @@ -199,18 +199,18 @@ func Genfstab(logPath, mountPoint, fstabPath string) error { | |||
| 199 | 199 | ||
| 200 | 200 | // DefaultChrootSession represents a persistent chroot session | |
| 201 | 201 | type DefaultChrootSession struct { | |
| 202 | - | cmd *exec.Cmd | |
| 203 | - | stdin *os.File | |
| 204 | - | stdoutPipe *os.File | |
| 205 | - | stderrPipe *os.File | |
| 206 | - | logFile *os.File | |
| 207 | - | logPath string | |
| 208 | - | mountPoint string | |
| 209 | - | ctx context.Context | |
| 210 | - | cancel context.CancelFunc | |
| 211 | - | outputChan chan string | |
| 212 | - | errorChan chan error | |
| 213 | - | closed bool | |
| 202 | + | cmd *exec.Cmd | |
| 203 | + | stdin *os.File | |
| 204 | + | stdoutPipe *os.File | |
| 205 | + | stderrPipe *os.File | |
| 206 | + | logFile *os.File | |
| 207 | + | logPath string | |
| 208 | + | mountPoint string | |
| 209 | + | ctx context.Context | |
| 210 | + | cancel context.CancelFunc | |
| 211 | + | outputChan chan string | |
| 212 | + | errorChan chan error | |
| 213 | + | closed bool | |
| 214 | 214 | } | |
| 215 | 215 | ||
| 216 | 216 | // BeginSession starts a persistent chroot session | |
| @@ -199,18 +199,18 @@ func Genfstab(logPath, mountPoint, fstabPath string) error { | |||||
| 199 | 199 | ||||
| 200 | // DefaultChrootSession represents a persistent chroot session | 200 | // DefaultChrootSession represents a persistent chroot session | ||
| 201 | type DefaultChrootSession struct { | 201 | type DefaultChrootSession struct { | ||
| 202 | - | cmd *exec.Cmd | 202 | + | cmd *exec.Cmd |
| 203 | - | stdin *os.File | 203 | + | stdin *os.File |
| 204 | - | stdoutPipe *os.File | 204 | + | stdoutPipe *os.File |
| 205 | - | stderrPipe *os.File | 205 | + | stderrPipe *os.File |
| 206 | - | logFile *os.File | 206 | + | logFile *os.File |
| 207 | - | logPath string | 207 | + | logPath string |
| 208 | - | mountPoint string | 208 | + | mountPoint string |
| 209 | - | ctx context.Context | 209 | + | ctx context.Context |
| 210 | - | cancel context.CancelFunc | 210 | + | cancel context.CancelFunc |
| 211 | - | outputChan chan string | 211 | + | outputChan chan string |
| 212 | - | errorChan chan error | 212 | + | errorChan chan error |
| 213 | - | closed bool | 213 | + | closed bool |
| 214 | } | 214 | } | ||
| 215 | 215 | ||||
| 216 | // BeginSession starts a persistent chroot session | 216 | // BeginSession starts a persistent chroot session | ||
M internal/system/cpu.go +5 -5
| @@ -34,11 +34,11 @@ type AMDZenGen struct { | |||
| 34 | 34 | ||
| 35 | 35 | // CPUInfo holds detected CPU information | |
| 36 | 36 | type CPUInfo struct { | |
| 37 | - | Vendor CPUVendor | |
| 38 | - | ModelName string // Full CPU model name | |
| 39 | - | Microcode string | |
| 40 | - | AMDZenGen *AMDZenGen // AMD Zen generation (nil for non-AMD) | |
| 41 | - | AMDPStateModes []AMDPStateMode | |
| 37 | + | Vendor CPUVendor | |
| 38 | + | ModelName string // Full CPU model name | |
| 39 | + | Microcode string | |
| 40 | + | AMDZenGen *AMDZenGen // AMD Zen generation (nil for non-AMD) | |
| 41 | + | AMDPStateModes []AMDPStateMode | |
| 42 | 42 | RecommendedPStateMode AMDPStateMode // Recommended mode for this CPU | |
| 43 | 43 | } | |
| 44 | 44 | ||
| @@ -34,11 +34,11 @@ type AMDZenGen struct { | |||||
| 34 | 34 | ||||
| 35 | // CPUInfo holds detected CPU information | 35 | // CPUInfo holds detected CPU information | ||
| 36 | type CPUInfo struct { | 36 | type CPUInfo struct { | ||
| 37 | - | Vendor CPUVendor | 37 | + | Vendor CPUVendor |
| 38 | - | ModelName string // Full CPU model name | 38 | + | ModelName string // Full CPU model name |
| 39 | - | Microcode string | 39 | + | Microcode string |
| 40 | - | AMDZenGen *AMDZenGen // AMD Zen generation (nil for non-AMD) | 40 | + | AMDZenGen *AMDZenGen // AMD Zen generation (nil for non-AMD) |
| 41 | - | AMDPStateModes []AMDPStateMode | 41 | + | AMDPStateModes []AMDPStateMode |
| 42 | RecommendedPStateMode AMDPStateMode // Recommended mode for this CPU | 42 | RecommendedPStateMode AMDPStateMode // Recommended mode for this CPU | ||
| 43 | } | 43 | } | ||
| 44 | 44 | ||||
M internal/system/mirrorlist_test.go +12 -12
| @@ -95,13 +95,13 @@ Server = https://tabs.com/$repo/$arch `, | |||
| 95 | 95 | ||
| 96 | 96 | func TestBuildPackageURLs(t *testing.T) { | |
| 97 | 97 | tests := []struct { | |
| 98 | - | name string | |
| 99 | - | mirrors []MirrorlistEntry | |
| 100 | - | packageName string | |
| 101 | - | preferEnabled bool | |
| 102 | - | wantCount int | |
| 103 | - | wantURLContains []string | |
| 104 | - | shouldStartWith string | |
| 98 | + | name string | |
| 99 | + | mirrors []MirrorlistEntry | |
| 100 | + | packageName string | |
| 101 | + | preferEnabled bool | |
| 102 | + | wantCount int | |
| 103 | + | wantURLContains []string | |
| 104 | + | shouldStartWith string | |
| 105 | 105 | }{ | |
| 106 | 106 | { | |
| 107 | 107 | name: "Basic URL building with enabled mirrors preferred", | |
| @@ -126,9 +126,9 @@ func TestBuildPackageURLs(t *testing.T) { | |||
| 126 | 126 | {URL: "https://enabled1.com/$repo/$arch", Enabled: true}, | |
| 127 | 127 | {URL: "https://enabled2.com/$repo/$arch", Enabled: true}, | |
| 128 | 128 | }, | |
| 129 | - | packageName: "pkg.tar.zst", | |
| 130 | - | preferEnabled: true, | |
| 131 | - | wantCount: 3, | |
| 129 | + | packageName: "pkg.tar.zst", | |
| 130 | + | preferEnabled: true, | |
| 131 | + | wantCount: 3, | |
| 132 | 132 | shouldStartWith: "https://enabled1.com/chaotic-aur/x86_64/pkg.tar.zst", | |
| 133 | 133 | }, | |
| 134 | 134 | { | |
| @@ -142,8 +142,8 @@ func TestBuildPackageURLs(t *testing.T) { | |||
| 142 | 142 | wantCount: 2, | |
| 143 | 143 | }, | |
| 144 | 144 | { | |
| 145 | - | name: "Empty mirrors list", | |
| 146 | - | mirrors: []MirrorlistEntry{}, | |
| 145 | + | name: "Empty mirrors list", | |
| 146 | + | mirrors: []MirrorlistEntry{}, | |
| 147 | 147 | packageName: "test.pkg.tar.zst", | |
| 148 | 148 | preferEnabled: true, | |
| 149 | 149 | wantCount: 0, | |
| @@ -95,13 +95,13 @@ Server = https://tabs.com/$repo/$arch `, | |||||
| 95 | 95 | ||||
| 96 | func TestBuildPackageURLs(t *testing.T) { | 96 | func TestBuildPackageURLs(t *testing.T) { | ||
| 97 | tests := []struct { | 97 | tests := []struct { | ||
| 98 | - | name string | 98 | + | name string |
| 99 | - | mirrors []MirrorlistEntry | 99 | + | mirrors []MirrorlistEntry |
| 100 | - | packageName string | 100 | + | packageName string |
| 101 | - | preferEnabled bool | 101 | + | preferEnabled bool |
| 102 | - | wantCount int | 102 | + | wantCount int |
| 103 | - | wantURLContains []string | 103 | + | wantURLContains []string |
| 104 | - | shouldStartWith string | 104 | + | shouldStartWith string |
| 105 | }{ | 105 | }{ | ||
| 106 | { | 106 | { | ||
| 107 | name: "Basic URL building with enabled mirrors preferred", | 107 | name: "Basic URL building with enabled mirrors preferred", | ||
| @@ -126,9 +126,9 @@ func TestBuildPackageURLs(t *testing.T) { | |||||
| 126 | {URL: "https://enabled1.com/$repo/$arch", Enabled: true}, | 126 | {URL: "https://enabled1.com/$repo/$arch", Enabled: true}, | ||
| 127 | {URL: "https://enabled2.com/$repo/$arch", Enabled: true}, | 127 | {URL: "https://enabled2.com/$repo/$arch", Enabled: true}, | ||
| 128 | }, | 128 | }, | ||
| 129 | - | packageName: "pkg.tar.zst", | 129 | + | packageName: "pkg.tar.zst", |
| 130 | - | preferEnabled: true, | 130 | + | preferEnabled: true, |
| 131 | - | wantCount: 3, | 131 | + | wantCount: 3, |
| 132 | shouldStartWith: "https://enabled1.com/chaotic-aur/x86_64/pkg.tar.zst", | 132 | shouldStartWith: "https://enabled1.com/chaotic-aur/x86_64/pkg.tar.zst", | ||
| 133 | }, | 133 | }, | ||
| 134 | { | 134 | { | ||
| @@ -142,8 +142,8 @@ func TestBuildPackageURLs(t *testing.T) { | |||||
| 142 | wantCount: 2, | 142 | wantCount: 2, | ||
| 143 | }, | 143 | }, | ||
| 144 | { | 144 | { | ||
| 145 | - | name: "Empty mirrors list", | 145 | + | name: "Empty mirrors list", |
| 146 | - | mirrors: []MirrorlistEntry{}, | 146 | + | mirrors: []MirrorlistEntry{}, |
| 147 | packageName: "test.pkg.tar.zst", | 147 | packageName: "test.pkg.tar.zst", | ||
| 148 | preferEnabled: true, | 148 | preferEnabled: true, | ||
| 149 | wantCount: 0, | 149 | wantCount: 0, | ||
M internal/ui/components/forms.go +1 -1
| @@ -1,9 +1,9 @@ | |||
| 1 | 1 | package components | |
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | + | "github.com/bnema/archup/internal/ui/styles" | |
| 4 | 5 | "github.com/charmbracelet/huh" | |
| 5 | 6 | "github.com/charmbracelet/lipgloss" | |
| 6 | - | "github.com/bnema/archup/internal/ui/styles" | |
| 7 | 7 | ) | |
| 8 | 8 | ||
| 9 | 9 | // FormBuilder provides reusable form components | |
| @@ -1,9 +1,9 @@ | |||||
| 1 | package components | 1 | package components | ||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | + | "github.com/bnema/archup/internal/ui/styles" | |||
| 4 | "github.com/charmbracelet/huh" | 5 | "github.com/charmbracelet/huh" | ||
| 5 | "github.com/charmbracelet/lipgloss" | 6 | "github.com/charmbracelet/lipgloss" | ||
| 6 | - | "github.com/bnema/archup/internal/ui/styles" | |||
| 7 | ) | 7 | ) | ||
| 8 | 8 | ||||
| 9 | // FormBuilder provides reusable form components | 9 | // FormBuilder provides reusable form components | ||
M internal/ui/components/output.go +1 -1
| @@ -3,9 +3,9 @@ package components | |||
| 3 | 3 | import ( | |
| 4 | 4 | "strings" | |
| 5 | 5 | ||
| 6 | + | "github.com/bnema/archup/internal/ui/styles" | |
| 6 | 7 | "github.com/charmbracelet/bubbles/viewport" | |
| 7 | 8 | tea "github.com/charmbracelet/bubbletea" | |
| 8 | - | "github.com/bnema/archup/internal/ui/styles" | |
| 9 | 9 | ) | |
| 10 | 10 | ||
| 11 | 11 | // OutputViewer displays scrolling command output (last N lines) | |
| @@ -3,9 +3,9 @@ package components | |||||
| 3 | import ( | 3 | import ( | ||
| 4 | "strings" | 4 | "strings" | ||
| 5 | 5 | ||||
| 6 | + | "github.com/bnema/archup/internal/ui/styles" | |||
| 6 | "github.com/charmbracelet/bubbles/viewport" | 7 | "github.com/charmbracelet/bubbles/viewport" | ||
| 7 | tea "github.com/charmbracelet/bubbletea" | 8 | tea "github.com/charmbracelet/bubbletea" | ||
| 8 | - | "github.com/bnema/archup/internal/ui/styles" | |||
| 9 | ) | 9 | ) | ||
| 10 | 10 | ||||
| 11 | // OutputViewer displays scrolling command output (last N lines) | 11 | // OutputViewer displays scrolling command output (last N lines) | ||
M internal/ui/model.go +8 -8
| @@ -342,15 +342,15 @@ func (m *Model) handleFormComplete() tea.Cmd { | |||
| 342 | 342 | } | |
| 343 | 343 | ||
| 344 | 344 | // Getter methods for views package | |
| 345 | - | func (m *Model) Width() int { return m.width } | |
| 346 | - | func (m *Model) Version() string { return m.version } | |
| 347 | - | func (m *Model) Config() *config.Config { return m.config } | |
| 348 | - | func (m *Model) CurrentForm() *huh.Form { return m.currentForm } | |
| 349 | - | func (m *Model) Spinner() spinner.Model { return m.spinner } | |
| 345 | + | func (m *Model) Width() int { return m.width } | |
| 346 | + | func (m *Model) Version() string { return m.version } | |
| 347 | + | func (m *Model) Config() *config.Config { return m.config } | |
| 348 | + | func (m *Model) CurrentForm() *huh.Form { return m.currentForm } | |
| 349 | + | func (m *Model) Spinner() spinner.Model { return m.spinner } | |
| 350 | 350 | func (m *Model) Output() *components.OutputViewer { return m.output } | |
| 351 | - | func (m *Model) RenderPhaseHeader() string { return m.renderPhaseHeader() } | |
| 352 | - | func (m *Model) NetworkCheckDone() bool { return m.networkCheckDone } | |
| 353 | - | func (m *Model) NetworkErr() error { return m.networkErr } | |
| 351 | + | func (m *Model) RenderPhaseHeader() string { return m.renderPhaseHeader() } | |
| 352 | + | func (m *Model) NetworkCheckDone() bool { return m.networkCheckDone } | |
| 353 | + | func (m *Model) NetworkErr() error { return m.networkErr } | |
| 354 | 354 | ||
| 355 | 355 | // executeNextPhase executes the next pending phase | |
| 356 | 356 | func (m *Model) executeNextPhase() tea.Cmd { | |
| @@ -342,15 +342,15 @@ func (m *Model) handleFormComplete() tea.Cmd { | |||||
| 342 | } | 342 | } | ||
| 343 | 343 | ||||
| 344 | // Getter methods for views package | 344 | // Getter methods for views package | ||
| 345 | - | func (m *Model) Width() int { return m.width } | 345 | + | func (m *Model) Width() int { return m.width } |
| 346 | - | func (m *Model) Version() string { return m.version } | 346 | + | func (m *Model) Version() string { return m.version } |
| 347 | - | func (m *Model) Config() *config.Config { return m.config } | 347 | + | func (m *Model) Config() *config.Config { return m.config } |
| 348 | - | func (m *Model) CurrentForm() *huh.Form { return m.currentForm } | 348 | + | func (m *Model) CurrentForm() *huh.Form { return m.currentForm } |
| 349 | - | func (m *Model) Spinner() spinner.Model { return m.spinner } | 349 | + | func (m *Model) Spinner() spinner.Model { return m.spinner } |
| 350 | func (m *Model) Output() *components.OutputViewer { return m.output } | 350 | func (m *Model) Output() *components.OutputViewer { return m.output } | ||
| 351 | - | func (m *Model) RenderPhaseHeader() string { return m.renderPhaseHeader() } | 351 | + | func (m *Model) RenderPhaseHeader() string { return m.renderPhaseHeader() } |
| 352 | - | func (m *Model) NetworkCheckDone() bool { return m.networkCheckDone } | 352 | + | func (m *Model) NetworkCheckDone() bool { return m.networkCheckDone } |
| 353 | - | func (m *Model) NetworkErr() error { return m.networkErr } | 353 | + | func (m *Model) NetworkErr() error { return m.networkErr } |
| 354 | 354 | ||||
| 355 | // executeNextPhase executes the next pending phase | 355 | // executeNextPhase executes the next pending phase | ||
| 356 | func (m *Model) executeNextPhase() tea.Cmd { | 356 | func (m *Model) executeNextPhase() tea.Cmd { | ||
M internal/ui/sections.go +12 -12
| @@ -27,27 +27,27 @@ const ( | |||
| 27 | 27 | WarnDiskErase = "WARNING: This will delete all data on the selected disk!" | |
| 28 | 28 | ||
| 29 | 29 | // Encryption | |
| 30 | - | SectionDiskEncryption = "Disk Encryption" | |
| 31 | - | DescEncryption = "LUKS encryption protects your data with Argon2id (2000ms iteration)" | |
| 32 | - | DescEncryptionPassword = "Leave empty to use the same password as your user account" | |
| 33 | - | DescEncryptionSamePass = "Use the same password for disk encryption as your user account?" | |
| 30 | + | SectionDiskEncryption = "Disk Encryption" | |
| 31 | + | DescEncryption = "LUKS encryption protects your data with Argon2id (2000ms iteration)" | |
| 32 | + | DescEncryptionPassword = "Leave empty to use the same password as your user account" | |
| 33 | + | DescEncryptionSamePass = "Use the same password for disk encryption as your user account?" | |
| 34 | 34 | ||
| 35 | 35 | // Kernel | |
| 36 | - | SectionKernel = "Kernel Selection" | |
| 37 | - | DescKernelLinux = "Stable mainline kernel (recommended)" | |
| 38 | - | DescKernelLTS = "Long-term support (maximum stability)" | |
| 39 | - | DescKernelZen = "Performance-optimized for general use" | |
| 36 | + | SectionKernel = "Kernel Selection" | |
| 37 | + | DescKernelLinux = "Stable mainline kernel (recommended)" | |
| 38 | + | DescKernelLTS = "Long-term support (maximum stability)" | |
| 39 | + | DescKernelZen = "Performance-optimized for general use" | |
| 40 | 40 | DescKernelHardened = "Security-focused kernel" | |
| 41 | - | DescKernelCachyOS = "Gaming-optimized (requires CachyOS repo)" | |
| 41 | + | DescKernelCachyOS = "Gaming-optimized (requires CachyOS repo)" | |
| 42 | 42 | ||
| 43 | 43 | // AMD P-State | |
| 44 | 44 | SectionAMDTuning = "AMD CPU Tuning" | |
| 45 | 45 | DescAMDPState = "Select AMD P-State driver mode for CPU frequency scaling" | |
| 46 | 46 | ||
| 47 | 47 | // Repository options | |
| 48 | - | DescMultilib = "Required for 32-bit applications and Wine" | |
| 49 | - | DescChaoticAUR = "Community repository with pre-built AUR packages" | |
| 50 | - | DescAURHelper = "Tool for installing packages from Arch User Repository" | |
| 48 | + | DescMultilib = "Required for 32-bit applications and Wine" | |
| 49 | + | DescChaoticAUR = "Community repository with pre-built AUR packages" | |
| 50 | + | DescAURHelper = "Tool for installing packages from Arch User Repository" | |
| 51 | 51 | DescAURHelperParu = "Rust-based AUR helper" | |
| 52 | 52 | DescAURHelperYay = "Go-based AUR helper" | |
| 53 | 53 | ) | |
| @@ -27,27 +27,27 @@ const ( | |||||
| 27 | WarnDiskErase = "WARNING: This will delete all data on the selected disk!" | 27 | WarnDiskErase = "WARNING: This will delete all data on the selected disk!" | ||
| 28 | 28 | ||||
| 29 | // Encryption | 29 | // Encryption | ||
| 30 | - | SectionDiskEncryption = "Disk Encryption" | 30 | + | SectionDiskEncryption = "Disk Encryption" |
| 31 | - | DescEncryption = "LUKS encryption protects your data with Argon2id (2000ms iteration)" | 31 | + | DescEncryption = "LUKS encryption protects your data with Argon2id (2000ms iteration)" |
| 32 | - | DescEncryptionPassword = "Leave empty to use the same password as your user account" | 32 | + | DescEncryptionPassword = "Leave empty to use the same password as your user account" |
| 33 | - | DescEncryptionSamePass = "Use the same password for disk encryption as your user account?" | 33 | + | DescEncryptionSamePass = "Use the same password for disk encryption as your user account?" |
| 34 | 34 | ||||
| 35 | // Kernel | 35 | // Kernel | ||
| 36 | - | SectionKernel = "Kernel Selection" | 36 | + | SectionKernel = "Kernel Selection" |
| 37 | - | DescKernelLinux = "Stable mainline kernel (recommended)" | 37 | + | DescKernelLinux = "Stable mainline kernel (recommended)" |
| 38 | - | DescKernelLTS = "Long-term support (maximum stability)" | 38 | + | DescKernelLTS = "Long-term support (maximum stability)" |
| 39 | - | DescKernelZen = "Performance-optimized for general use" | 39 | + | DescKernelZen = "Performance-optimized for general use" |
| 40 | DescKernelHardened = "Security-focused kernel" | 40 | DescKernelHardened = "Security-focused kernel" | ||
| 41 | - | DescKernelCachyOS = "Gaming-optimized (requires CachyOS repo)" | 41 | + | DescKernelCachyOS = "Gaming-optimized (requires CachyOS repo)" |
| 42 | 42 | ||||
| 43 | // AMD P-State | 43 | // AMD P-State | ||
| 44 | SectionAMDTuning = "AMD CPU Tuning" | 44 | SectionAMDTuning = "AMD CPU Tuning" | ||
| 45 | DescAMDPState = "Select AMD P-State driver mode for CPU frequency scaling" | 45 | DescAMDPState = "Select AMD P-State driver mode for CPU frequency scaling" | ||
| 46 | 46 | ||||
| 47 | // Repository options | 47 | // Repository options | ||
| 48 | - | DescMultilib = "Required for 32-bit applications and Wine" | 48 | + | DescMultilib = "Required for 32-bit applications and Wine" |
| 49 | - | DescChaoticAUR = "Community repository with pre-built AUR packages" | 49 | + | DescChaoticAUR = "Community repository with pre-built AUR packages" |
| 50 | - | DescAURHelper = "Tool for installing packages from Arch User Repository" | 50 | + | DescAURHelper = "Tool for installing packages from Arch User Repository" |
| 51 | DescAURHelperParu = "Rust-based AUR helper" | 51 | DescAURHelperParu = "Rust-based AUR helper" | ||
| 52 | DescAURHelperYay = "Go-based AUR helper" | 52 | DescAURHelperYay = "Go-based AUR helper" | ||
| 53 | ) | 53 | ) | ||
M internal/ui/styles/containers.go +5 -5
| @@ -18,12 +18,12 @@ const ( | |||
| 18 | 18 | var ( | |
| 19 | 19 | // CenteredContainerStyle - Used for welcome, complete, error screens | |
| 20 | 20 | CenteredContainerStyle = lipgloss.NewStyle(). | |
| 21 | - | MaxWidth(MaxContentWidth). | |
| 22 | - | Padding(0, 2). | |
| 23 | - | AlignHorizontal(lipgloss.Center) | |
| 21 | + | MaxWidth(MaxContentWidth). | |
| 22 | + | Padding(0, 2). | |
| 23 | + | AlignHorizontal(lipgloss.Center) | |
| 24 | 24 | ||
| 25 | 25 | // FormContainerStyle - Used for all forms (content left-aligned) | |
| 26 | 26 | FormContainerStyle = lipgloss.NewStyle(). | |
| 27 | - | Padding(0, 2). | |
| 28 | - | AlignHorizontal(lipgloss.Left) | |
| 27 | + | Padding(0, 2). | |
| 28 | + | AlignHorizontal(lipgloss.Left) | |
| 29 | 29 | ) | |
| @@ -18,12 +18,12 @@ const ( | |||||
| 18 | var ( | 18 | var ( | ||
| 19 | // CenteredContainerStyle - Used for welcome, complete, error screens | 19 | // CenteredContainerStyle - Used for welcome, complete, error screens | ||
| 20 | CenteredContainerStyle = lipgloss.NewStyle(). | 20 | CenteredContainerStyle = lipgloss.NewStyle(). | ||
| 21 | - | MaxWidth(MaxContentWidth). | 21 | + | MaxWidth(MaxContentWidth). |
| 22 | - | Padding(0, 2). | 22 | + | Padding(0, 2). |
| 23 | - | AlignHorizontal(lipgloss.Center) | 23 | + | AlignHorizontal(lipgloss.Center) |
| 24 | 24 | ||||
| 25 | // FormContainerStyle - Used for all forms (content left-aligned) | 25 | // FormContainerStyle - Used for all forms (content left-aligned) | ||
| 26 | FormContainerStyle = lipgloss.NewStyle(). | 26 | FormContainerStyle = lipgloss.NewStyle(). | ||
| 27 | - | Padding(0, 2). | 27 | + | Padding(0, 2). |
| 28 | - | AlignHorizontal(lipgloss.Left) | 28 | + | AlignHorizontal(lipgloss.Left) |
| 29 | ) | 29 | ) | ||
M internal/ui/styles/theme.go +28 -28
| @@ -14,8 +14,8 @@ var ( | |||
| 14 | 14 | // Background Colors | |
| 15 | 15 | ColorDeepNavy = lipgloss.CompleteColor{ | |
| 16 | 16 | TrueColor: "#050a14", | |
| 17 | - | ANSI256: "16", // Pure black | |
| 18 | - | ANSI: "0", // Black | |
| 17 | + | ANSI256: "16", // Pure black | |
| 18 | + | ANSI: "0", // Black | |
| 19 | 19 | } | |
| 20 | 20 | ||
| 21 | 21 | ColorDarkBlue = lipgloss.CompleteColor{ | |
| @@ -38,8 +38,8 @@ var ( | |||
| 38 | 38 | ||
| 39 | 39 | ColorOceanBlue = lipgloss.CompleteColor{ | |
| 40 | 40 | TrueColor: "#2d4a6b", | |
| 41 | - | ANSI256: "24", // Deep blue | |
| 42 | - | ANSI: "4", // Blue | |
| 41 | + | ANSI256: "24", // Deep blue | |
| 42 | + | ANSI: "4", // Blue | |
| 43 | 43 | } | |
| 44 | 44 | ||
| 45 | 45 | // Text Colors | |
| @@ -64,14 +64,14 @@ var ( | |||
| 64 | 64 | // Accent Colors | |
| 65 | 65 | ColorBrightCyan = lipgloss.CompleteColor{ | |
| 66 | 66 | TrueColor: "#00d4ff", | |
| 67 | - | ANSI256: "45", // Bright cyan | |
| 68 | - | ANSI: "14", // Bright cyan | |
| 67 | + | ANSI256: "45", // Bright cyan | |
| 68 | + | ANSI: "14", // Bright cyan | |
| 69 | 69 | } | |
| 70 | 70 | ||
| 71 | 71 | ColorPureBlue = lipgloss.CompleteColor{ | |
| 72 | 72 | TrueColor: "#5588cc", | |
| 73 | - | ANSI256: "69", // Steel blue | |
| 74 | - | ANSI: "12", // Bright blue | |
| 73 | + | ANSI256: "69", // Steel blue | |
| 74 | + | ANSI: "12", // Bright blue | |
| 75 | 75 | } | |
| 76 | 76 | ||
| 77 | 77 | ColorLightSkyBlue = lipgloss.CompleteColor{ | |
| @@ -82,8 +82,8 @@ var ( | |||
| 82 | 82 | ||
| 83 | 83 | ColorSkyBlue = lipgloss.CompleteColor{ | |
| 84 | 84 | TrueColor: "#4a7ba7", | |
| 85 | - | ANSI256: "67", // Steel blue | |
| 86 | - | ANSI: "4", // Blue | |
| 85 | + | ANSI256: "67", // Steel blue | |
| 86 | + | ANSI: "4", // Blue | |
| 87 | 87 | } | |
| 88 | 88 | ||
| 89 | 89 | // Status Colors | |
| @@ -273,52 +273,52 @@ func HuhTheme() *huh.Theme { | |||
| 273 | 273 | // 0=black, 4=blue, 6=cyan, 7=white, 8=grey, 10=bright green, 12=bright blue, 14=bright cyan, 15=bright white | |
| 274 | 274 | ||
| 275 | 275 | // Form and Group styles | |
| 276 | - | theme.Group.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | |
| 277 | - | theme.Group.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue | |
| 276 | + | theme.Group.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | |
| 277 | + | theme.Group.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue | |
| 278 | 278 | ||
| 279 | 279 | // Focused field styles | |
| 280 | - | theme.Focused.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | |
| 281 | - | theme.Focused.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue | |
| 280 | + | theme.Focused.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | |
| 281 | + | theme.Focused.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue | |
| 282 | 282 | theme.Focused.SelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).SetString("> ") | |
| 283 | - | theme.Focused.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White | |
| 283 | + | theme.Focused.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White | |
| 284 | 284 | theme.Focused.MultiSelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).SetString("> ") | |
| 285 | - | theme.Focused.SelectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan | |
| 285 | + | theme.Focused.SelectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan | |
| 286 | 286 | theme.Focused.SelectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("10")).SetString("[OK] ") // Bright green | |
| 287 | - | theme.Focused.UnselectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White | |
| 288 | - | theme.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("○ ") // Grey | |
| 287 | + | theme.Focused.UnselectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White | |
| 288 | + | theme.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("○ ") // Grey | |
| 289 | 289 | ||
| 290 | 290 | // Button styles with explicit background colors for TTY compatibility | |
| 291 | 291 | // Active/focused button (currently selected - e.g., "Yes" when on Yes) | |
| 292 | 292 | theme.Focused.FocusedButton = lipgloss.NewStyle(). | |
| 293 | - | Foreground(lipgloss.Color("15")). // Bright white text | |
| 294 | - | Background(lipgloss.Color("4")). // Blue background | |
| 293 | + | Foreground(lipgloss.Color("15")). // Bright white text | |
| 294 | + | Background(lipgloss.Color("4")). // Blue background | |
| 295 | 295 | Padding(0, 2). | |
| 296 | 296 | Bold(true) | |
| 297 | 297 | ||
| 298 | 298 | // Inactive/blurred button (not selected - e.g., "No" when on Yes) | |
| 299 | 299 | theme.Focused.BlurredButton = lipgloss.NewStyle(). | |
| 300 | - | Foreground(lipgloss.Color("7")). // White text | |
| 301 | - | Background(lipgloss.Color("0")). // Black background | |
| 300 | + | Foreground(lipgloss.Color("7")). // White text | |
| 301 | + | Background(lipgloss.Color("0")). // Black background | |
| 302 | 302 | Padding(0, 2) | |
| 303 | 303 | ||
| 304 | 304 | // Blurred field styles (when entire field loses focus) | |
| 305 | - | theme.Blurred.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 306 | - | theme.Blurred.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 305 | + | theme.Blurred.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 306 | + | theme.Blurred.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 307 | 307 | theme.Blurred.SelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("> ") | |
| 308 | - | theme.Blurred.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 308 | + | theme.Blurred.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 309 | 309 | ||
| 310 | 310 | // Override buttons in Blurred state too (inherited from Focused in Base16) | |
| 311 | 311 | theme.Blurred.FocusedButton = theme.Focused.FocusedButton | |
| 312 | 312 | theme.Blurred.BlurredButton = theme.Focused.BlurredButton | |
| 313 | 313 | ||
| 314 | 314 | // Text input styles | |
| 315 | - | theme.Focused.TextInput.Cursor = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan | |
| 316 | - | theme.Focused.TextInput.Placeholder = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 315 | + | theme.Focused.TextInput.Cursor = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan | |
| 316 | + | theme.Focused.TextInput.Placeholder = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | |
| 317 | 317 | theme.Focused.TextInput.Prompt = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | |
| 318 | 318 | ||
| 319 | 319 | // Error styles | |
| 320 | 320 | theme.Focused.ErrorIndicator = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).SetString("[KO] ") // Bright red | |
| 321 | - | theme.Focused.ErrorMessage = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true) // Bright red | |
| 321 | + | theme.Focused.ErrorMessage = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true) // Bright red | |
| 322 | 322 | ||
| 323 | 323 | return theme | |
| 324 | 324 | } | |
| @@ -14,8 +14,8 @@ var ( | |||||
| 14 | // Background Colors | 14 | // Background Colors | ||
| 15 | ColorDeepNavy = lipgloss.CompleteColor{ | 15 | ColorDeepNavy = lipgloss.CompleteColor{ | ||
| 16 | TrueColor: "#050a14", | 16 | TrueColor: "#050a14", | ||
| 17 | - | ANSI256: "16", // Pure black | 17 | + | ANSI256: "16", // Pure black |
| 18 | - | ANSI: "0", // Black | 18 | + | ANSI: "0", // Black |
| 19 | } | 19 | } | ||
| 20 | 20 | ||||
| 21 | ColorDarkBlue = lipgloss.CompleteColor{ | 21 | ColorDarkBlue = lipgloss.CompleteColor{ | ||
| @@ -38,8 +38,8 @@ var ( | |||||
| 38 | 38 | ||||
| 39 | ColorOceanBlue = lipgloss.CompleteColor{ | 39 | ColorOceanBlue = lipgloss.CompleteColor{ | ||
| 40 | TrueColor: "#2d4a6b", | 40 | TrueColor: "#2d4a6b", | ||
| 41 | - | ANSI256: "24", // Deep blue | 41 | + | ANSI256: "24", // Deep blue |
| 42 | - | ANSI: "4", // Blue | 42 | + | ANSI: "4", // Blue |
| 43 | } | 43 | } | ||
| 44 | 44 | ||||
| 45 | // Text Colors | 45 | // Text Colors | ||
| @@ -64,14 +64,14 @@ var ( | |||||
| 64 | // Accent Colors | 64 | // Accent Colors | ||
| 65 | ColorBrightCyan = lipgloss.CompleteColor{ | 65 | ColorBrightCyan = lipgloss.CompleteColor{ | ||
| 66 | TrueColor: "#00d4ff", | 66 | TrueColor: "#00d4ff", | ||
| 67 | - | ANSI256: "45", // Bright cyan | 67 | + | ANSI256: "45", // Bright cyan |
| 68 | - | ANSI: "14", // Bright cyan | 68 | + | ANSI: "14", // Bright cyan |
| 69 | } | 69 | } | ||
| 70 | 70 | ||||
| 71 | ColorPureBlue = lipgloss.CompleteColor{ | 71 | ColorPureBlue = lipgloss.CompleteColor{ | ||
| 72 | TrueColor: "#5588cc", | 72 | TrueColor: "#5588cc", | ||
| 73 | - | ANSI256: "69", // Steel blue | 73 | + | ANSI256: "69", // Steel blue |
| 74 | - | ANSI: "12", // Bright blue | 74 | + | ANSI: "12", // Bright blue |
| 75 | } | 75 | } | ||
| 76 | 76 | ||||
| 77 | ColorLightSkyBlue = lipgloss.CompleteColor{ | 77 | ColorLightSkyBlue = lipgloss.CompleteColor{ | ||
| @@ -82,8 +82,8 @@ var ( | |||||
| 82 | 82 | ||||
| 83 | ColorSkyBlue = lipgloss.CompleteColor{ | 83 | ColorSkyBlue = lipgloss.CompleteColor{ | ||
| 84 | TrueColor: "#4a7ba7", | 84 | TrueColor: "#4a7ba7", | ||
| 85 | - | ANSI256: "67", // Steel blue | 85 | + | ANSI256: "67", // Steel blue |
| 86 | - | ANSI: "4", // Blue | 86 | + | ANSI: "4", // Blue |
| 87 | } | 87 | } | ||
| 88 | 88 | ||||
| 89 | // Status Colors | 89 | // Status Colors | ||
| @@ -273,52 +273,52 @@ func HuhTheme() *huh.Theme { | |||||
| 273 | // 0=black, 4=blue, 6=cyan, 7=white, 8=grey, 10=bright green, 12=bright blue, 14=bright cyan, 15=bright white | 273 | // 0=black, 4=blue, 6=cyan, 7=white, 8=grey, 10=bright green, 12=bright blue, 14=bright cyan, 15=bright white | ||
| 274 | 274 | ||||
| 275 | // Form and Group styles | 275 | // Form and Group styles | ||
| 276 | - | theme.Group.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | 276 | + | theme.Group.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan |
| 277 | - | theme.Group.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue | 277 | + | theme.Group.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue |
| 278 | 278 | ||||
| 279 | // Focused field styles | 279 | // Focused field styles | ||
| 280 | - | theme.Focused.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | 280 | + | theme.Focused.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan |
| 281 | - | theme.Focused.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue | 281 | + | theme.Focused.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("12")) // Bright blue |
| 282 | theme.Focused.SelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).SetString("> ") | 282 | theme.Focused.SelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).SetString("> ") | ||
| 283 | - | theme.Focused.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White | 283 | + | theme.Focused.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White |
| 284 | theme.Focused.MultiSelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).SetString("> ") | 284 | theme.Focused.MultiSelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).SetString("> ") | ||
| 285 | - | theme.Focused.SelectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan | 285 | + | theme.Focused.SelectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan |
| 286 | theme.Focused.SelectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("10")).SetString("[OK] ") // Bright green | 286 | theme.Focused.SelectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("10")).SetString("[OK] ") // Bright green | ||
| 287 | - | theme.Focused.UnselectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White | 287 | + | theme.Focused.UnselectedOption = lipgloss.NewStyle().Foreground(lipgloss.Color("7")) // White |
| 288 | - | theme.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("○ ") // Grey | 288 | + | theme.Focused.UnselectedPrefix = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("○ ") // Grey |
| 289 | 289 | ||||
| 290 | // Button styles with explicit background colors for TTY compatibility | 290 | // Button styles with explicit background colors for TTY compatibility | ||
| 291 | // Active/focused button (currently selected - e.g., "Yes" when on Yes) | 291 | // Active/focused button (currently selected - e.g., "Yes" when on Yes) | ||
| 292 | theme.Focused.FocusedButton = lipgloss.NewStyle(). | 292 | theme.Focused.FocusedButton = lipgloss.NewStyle(). | ||
| 293 | - | Foreground(lipgloss.Color("15")). // Bright white text | 293 | + | Foreground(lipgloss.Color("15")). // Bright white text |
| 294 | - | Background(lipgloss.Color("4")). // Blue background | 294 | + | Background(lipgloss.Color("4")). // Blue background |
| 295 | Padding(0, 2). | 295 | Padding(0, 2). | ||
| 296 | Bold(true) | 296 | Bold(true) | ||
| 297 | 297 | ||||
| 298 | // Inactive/blurred button (not selected - e.g., "No" when on Yes) | 298 | // Inactive/blurred button (not selected - e.g., "No" when on Yes) | ||
| 299 | theme.Focused.BlurredButton = lipgloss.NewStyle(). | 299 | theme.Focused.BlurredButton = lipgloss.NewStyle(). | ||
| 300 | - | Foreground(lipgloss.Color("7")). // White text | 300 | + | Foreground(lipgloss.Color("7")). // White text |
| 301 | - | Background(lipgloss.Color("0")). // Black background | 301 | + | Background(lipgloss.Color("0")). // Black background |
| 302 | Padding(0, 2) | 302 | Padding(0, 2) | ||
| 303 | 303 | ||||
| 304 | // Blurred field styles (when entire field loses focus) | 304 | // Blurred field styles (when entire field loses focus) | ||
| 305 | - | theme.Blurred.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | 305 | + | theme.Blurred.Title = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey |
| 306 | - | theme.Blurred.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | 306 | + | theme.Blurred.Description = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey |
| 307 | theme.Blurred.SelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("> ") | 307 | theme.Blurred.SelectSelector = lipgloss.NewStyle().Foreground(lipgloss.Color("8")).SetString("> ") | ||
| 308 | - | theme.Blurred.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | 308 | + | theme.Blurred.Option = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey |
| 309 | 309 | ||||
| 310 | // Override buttons in Blurred state too (inherited from Focused in Base16) | 310 | // Override buttons in Blurred state too (inherited from Focused in Base16) | ||
| 311 | theme.Blurred.FocusedButton = theme.Focused.FocusedButton | 311 | theme.Blurred.FocusedButton = theme.Focused.FocusedButton | ||
| 312 | theme.Blurred.BlurredButton = theme.Focused.BlurredButton | 312 | theme.Blurred.BlurredButton = theme.Focused.BlurredButton | ||
| 313 | 313 | ||||
| 314 | // Text input styles | 314 | // Text input styles | ||
| 315 | - | theme.Focused.TextInput.Cursor = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan | 315 | + | theme.Focused.TextInput.Cursor = lipgloss.NewStyle().Foreground(lipgloss.Color("14")) // Bright cyan |
| 316 | - | theme.Focused.TextInput.Placeholder = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey | 316 | + | theme.Focused.TextInput.Placeholder = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // Grey |
| 317 | theme.Focused.TextInput.Prompt = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | 317 | theme.Focused.TextInput.Prompt = lipgloss.NewStyle().Foreground(lipgloss.Color("14")).Bold(true) // Bright cyan | ||
| 318 | 318 | ||||
| 319 | // Error styles | 319 | // Error styles | ||
| 320 | theme.Focused.ErrorIndicator = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).SetString("[KO] ") // Bright red | 320 | theme.Focused.ErrorIndicator = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).SetString("[KO] ") // Bright red | ||
| 321 | - | theme.Focused.ErrorMessage = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true) // Bright red | 321 | + | theme.Focused.ErrorMessage = lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true) // Bright red |
| 322 | 322 | ||||
| 323 | return theme | 323 | return theme | ||
| 324 | } | 324 | } | ||
M internal/verify/shell.go +5 -5
| @@ -11,11 +11,11 @@ import ( | |||
| 11 | 11 | ||
| 12 | 12 | // ShellConfig holds verification results for shell configuration | |
| 13 | 13 | type ShellConfig struct { | |
| 14 | - | BashrcExists bool | |
| 15 | - | ShellFilesOK bool | |
| 16 | - | BashrcSyntaxOK bool | |
| 17 | - | Warnings []string | |
| 18 | - | Errors []string | |
| 14 | + | BashrcExists bool | |
| 15 | + | ShellFilesOK bool | |
| 16 | + | BashrcSyntaxOK bool | |
| 17 | + | Warnings []string | |
| 18 | + | Errors []string | |
| 19 | 19 | } | |
| 20 | 20 | ||
| 21 | 21 | // ValidateShellConfigs performs comprehensive shell configuration verification | |
| @@ -11,11 +11,11 @@ import ( | |||||
| 11 | 11 | ||||
| 12 | // ShellConfig holds verification results for shell configuration | 12 | // ShellConfig holds verification results for shell configuration | ||
| 13 | type ShellConfig struct { | 13 | type ShellConfig struct { | ||
| 14 | - | BashrcExists bool | 14 | + | BashrcExists bool |
| 15 | - | ShellFilesOK bool | 15 | + | ShellFilesOK bool |
| 16 | - | BashrcSyntaxOK bool | 16 | + | BashrcSyntaxOK bool |
| 17 | - | Warnings []string | 17 | + | Warnings []string |
| 18 | - | Errors []string | 18 | + | Errors []string |
| 19 | } | 19 | } | ||
| 20 | 20 | ||||
| 21 | // ValidateShellConfigs performs comprehensive shell configuration verification | 21 | // ValidateShellConfigs performs comprehensive shell configuration verification | ||