detached cc22049

refactor(code-style): convert 218 single-case switches to if statements

Replaced all problematic single-case switch statements with equivalent if statements
for better Go idiom compliance. Automated conversion handled 216 cases, with 2 edge
cases converted manually. This improves code readability and follows Go best practices
which discourage unnecessary switch statements.

Files modified:
- internal/phases/{base,boot,bootstrap,partitioning,postinstall,preflight,repos,systemconfig}.go
- internal/system/cpu.go
- internal/ui/{installer_forms,model}.go

Build verification: ✓ Complete
Type: refactor | Scope: code-style | Breaking: No
commit
cc220498172159dce39943ae69ae0346f48a4113
author
bnema · · 2025-10-29 06:38 UTC
parent
66db09f
signature
unsigned
11 files · +218 -436
M internal/phases/base.go +30 -60
@@ -31,8 +31,7 @@ func NewBaseInstallPhase(cfg *config.Config, log *logger.Logger, fs interfaces.F
3131 func (p *BaseInstallPhase) PreCheck() error {
3232 // Verify /mnt is mounted
3333 result := p.sysExec.RunSimple("mountpoint", "-q", "/mnt")
34- switch {
35- case result.ExitCode != 0:
34+ if result.ExitCode != 0 {
3635 return fmt.Errorf("/mnt is not mounted")
3736 }
3837
@@ -44,8 +43,7 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
4443 p.SendProgress(progressChan, "Starting base installation...", 1, 5)
4544
4645 // Step 1: Configure ISO pacman
47- switch err := p.configurePacman(progressChan); {
48- case err != nil:
46+ if err := p.configurePacman(progressChan); err != nil {
4947 p.SendError(progressChan, err)
5048 return PhaseResult{Success: false, Error: err}
5149 }
@@ -53,18 +51,15 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
5351 p.SendProgress(progressChan, "Detecting CPU and microcode...", 2, 5)
5452
5553 // Step 2: Detect CPU and select microcode
56- switch err := p.detectCPU(progressChan); {
57- case err != nil:
54+ if err := p.detectCPU(progressChan); err != nil {
5855 p.SendError(progressChan, err)
5956 return PhaseResult{Success: false, Error: err}
6057 }
6158
6259 // Step 2.5: Configure CachyOS repository on ISO if needed
63- switch {
64- case p.config.KernelChoice == config.KernelLinuxCachyOS:
60+ if p.config.KernelChoice == config.KernelLinuxCachyOS {
6561 p.SendProgress(progressChan, "Configuring CachyOS repository...", 2, 5)
66- switch err := p.configureCachyOSRepo(progressChan); {
67- case err != nil:
62+ if err := p.configureCachyOSRepo(progressChan); err != nil {
6863 p.SendError(progressChan, err)
6964 return PhaseResult{Success: false, Error: err}
7065 }
@@ -73,8 +68,7 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
7368 p.SendProgress(progressChan, "Installing base system...", 3, 5)
7469
7570 // Step 3: Run pacstrap
76- switch err := p.runPacstrap(progressChan); {
77- case err != nil:
71+ if err := p.runPacstrap(progressChan); err != nil {
7872 p.SendError(progressChan, err)
7973 return PhaseResult{Success: false, Error: err}
8074 }
@@ -82,8 +76,7 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
8276 p.SendProgress(progressChan, "Generating fstab...", 4, 5)
8377
8478 // Step 4: Generate fstab
85- switch err := p.generateFstab(progressChan); {
86- case err != nil:
79+ if err := p.generateFstab(progressChan); err != nil {
8780 p.SendError(progressChan, err)
8881 return PhaseResult{Success: false, Error: err}
8982 }
@@ -103,8 +96,7 @@ func (p *BaseInstallPhase) configurePacman(progressChan chan<- ProgressUpdate) e
10396 "s/^#ParallelDownloads = 5$/ParallelDownloads = 10/",
10497 "/etc/pacman.conf")
10598
106- switch {
107- case result.ExitCode != 0:
99+ if result.ExitCode != 0 {
108100 return fmt.Errorf("pacman configuration failed: %w", result.Error)
109101 }
110102
@@ -119,14 +111,12 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
119111 // Import CachyOS GPG key
120112 p.SendOutput(progressChan, "Importing CachyOS GPG key...")
121113 result := p.logger.ExecCommand("pacman-key", "--recv-keys", "F3B607488DB35A47", "--keyserver", "keyserver.ubuntu.com")
122- switch {
123- case result.ExitCode != 0:
114+ if result.ExitCode != 0 {
124115 return fmt.Errorf("failed to receive CachyOS GPG key: %w", result.Error)
125116 }
126117
127118 result = p.logger.ExecCommand("pacman-key", "--lsign-key", "F3B607488DB35A47")
128- switch {
129- case result.ExitCode != 0:
119+ if result.ExitCode != 0 {
130120 return fmt.Errorf("failed to sign CachyOS GPG key: %w", result.Error)
131121 }
132122
@@ -134,8 +124,7 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
134124
135125 // Check if CachyOS repo already configured
136126 content, err := p.fs.ReadFile("/etc/pacman.conf")
137- switch {
138- case err != nil:
127+ if err != nil {
139128 return fmt.Errorf("failed to read pacman.conf: %w", err)
140129 }
141130
@@ -162,8 +151,7 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
162151
163152 contentStr = strings.Join(newLines, "\n")
164153
165- switch err := p.fs.WriteFile("/etc/pacman.conf", []byte(contentStr), 0644); {
166- case err != nil:
154+ if err := p.fs.WriteFile("/etc/pacman.conf", []byte(contentStr), 0644); err != nil {
167155 return fmt.Errorf("failed to write pacman.conf: %w", err)
168156 }
169157 }
@@ -172,16 +160,14 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
172160 p.SendOutput(progressChan, "Creating CachyOS mirrorlist...")
173161 mirrorlist := "## CachyOS mirrorlist\nServer = https://mirror.cachyos.org/repo/$arch/$repo\n"
174162
175- switch err := p.fs.WriteFile("/etc/pacman.d/cachyos-mirrorlist", []byte(mirrorlist), 0644); {
176- case err != nil:
163+ if err := p.fs.WriteFile("/etc/pacman.d/cachyos-mirrorlist", []byte(mirrorlist), 0644); err != nil {
177164 return fmt.Errorf("failed to create cachyos-mirrorlist: %w", err)
178165 }
179166
180167 // Sync databases
181168 p.SendOutput(progressChan, "Syncing package databases...")
182169 result = p.logger.ExecCommand("pacman", "-Sy")
183- switch {
184- case result.ExitCode != 0:
170+ if result.ExitCode != 0 {
185171 return fmt.Errorf("failed to sync databases: %w", result.Error)
186172 }
187173
@@ -193,8 +179,7 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
193179 func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate) error {
194180 // Read ISO's pacman.conf to check if CachyOS is configured
195181 content, err := p.fs.ReadFile("/etc/pacman.conf")
196- switch {
197- case err != nil:
182+ if err != nil {
198183 return fmt.Errorf("failed to read ISO pacman.conf: %w", err)
199184 }
200185
@@ -202,8 +187,7 @@ func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate)
202187
203188 // Read installed system's pacman.conf
204189 mntContent, err := p.fs.ReadFile("/mnt/etc/pacman.conf")
205- switch {
206- case err != nil:
190+ if err != nil {
207191 return fmt.Errorf("failed to read /mnt/etc/pacman.conf: %w", err)
208192 }
209193
@@ -228,8 +212,7 @@ func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate)
228212
229213 mntContentStr = strings.Join(newLines, "\n")
230214
231- switch err := p.fs.WriteFile("/mnt/etc/pacman.conf", []byte(mntContentStr), 0644); {
232- case err != nil:
215+ if err := p.fs.WriteFile("/mnt/etc/pacman.conf", []byte(mntContentStr), 0644); err != nil {
233216 return fmt.Errorf("failed to write /mnt/etc/pacman.conf: %w", err)
234217 }
235218
@@ -238,14 +221,12 @@ func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate)
238221
239222 // Copy mirrorlist from ISO to installed system
240223 result := p.logger.ExecCommand("mkdir", "-p", "/mnt/etc/pacman.d")
241- switch {
242- case result.ExitCode != 0:
224+ if result.ExitCode != 0 {
243225 return fmt.Errorf("failed to create /mnt/etc/pacman.d: %w", result.Error)
244226 }
245227
246228 result = p.logger.ExecCommand("cp", "/etc/pacman.d/cachyos-mirrorlist", "/mnt/etc/pacman.d/cachyos-mirrorlist")
247- switch {
248- case result.ExitCode != 0:
229+ if result.ExitCode != 0 {
249230 return fmt.Errorf("failed to copy cachyos-mirrorlist: %w", result.Error)
250231 }
251232
@@ -259,8 +240,7 @@ func (p *BaseInstallPhase) detectCPU(progressChan chan<- ProgressUpdate) error {
259240
260241 // Read /proc/cpuinfo to detect vendor
261242 file, err := p.fs.Open("/proc/cpuinfo")
262- switch {
263- case err != nil:
243+ if err != nil {
264244 return fmt.Errorf("failed to read /proc/cpuinfo: %w", err)
265245 }
266246 defer file.Close()
@@ -298,8 +278,7 @@ func (p *BaseInstallPhase) detectCPU(progressChan chan<- ProgressUpdate) error {
298278 p.config.Microcode = microcode
299279 p.config.CPUVendor = cpuType
300280
301- switch {
302- case microcode != "":
281+ if microcode != "" {
303282 p.SendOutput(progressChan, fmt.Sprintf("[OK] Detected %s CPU", cpuType))
304283 p.SendOutput(progressChan, fmt.Sprintf(" Microcode: %s", microcode))
305284 }
@@ -311,8 +290,7 @@ func (p *BaseInstallPhase) detectCPU(progressChan chan<- ProgressUpdate) error {
311290 func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error {
312291 // Load base packages from embedded list
313292 packages, err := p.loadBasePackages()
314- switch {
315- case err != nil:
293+ if err != nil {
316294 return fmt.Errorf("failed to load package list: %w", err)
317295 }
318296
@@ -328,8 +306,7 @@ func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error
328306 }
329307
330308 // Add microcode
331- switch {
332- case p.config.Microcode != "":
309+ if p.config.Microcode != "" {
333310 packages = append(packages, p.config.Microcode)
334311 p.SendOutput(progressChan, fmt.Sprintf("Adding microcode: %s", p.config.Microcode))
335312 }
@@ -355,16 +332,14 @@ func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error
355332 args := append([]string{"/mnt"}, packages...)
356333 result := p.logger.ExecCommand("pacstrap", args...)
357334
358- switch {
359- case result.ExitCode != 0:
335+ if result.ExitCode != 0 {
360336 return fmt.Errorf("pacstrap failed: %w", result.Error)
361337 }
362338
363339 p.SendOutput(progressChan, fmt.Sprintf("[OK] Installed %d packages", len(packages)))
364340
365341 // Copy CachyOS configuration to installed system if needed
366- switch {
367- case p.config.KernelChoice == config.KernelLinuxCachyOS:
342+ if p.config.KernelChoice == config.KernelLinuxCachyOS {
368343 p.SendOutput(progressChan, "Configuring CachyOS repository in installed system...")
369344 if err := p.copyCachyOSConfig(progressChan); err != nil {
370345 return fmt.Errorf("failed to configure CachyOS in installed system: %w", err)
@@ -381,8 +356,7 @@ func (p *BaseInstallPhase) loadBasePackages() ([]string, error) {
381356 packageFile := config.DefaultInstallDir + "/" + config.BasePackagesFile
382357
383358 file, err := p.fs.Open(packageFile)
384- switch {
385- case err != nil:
359+ if err != nil {
386360 return nil, fmt.Errorf("failed to open %s: %w", packageFile, err)
387361 }
388362 defer file.Close()
@@ -404,8 +378,7 @@ func (p *BaseInstallPhase) loadBasePackages() ([]string, error) {
404378 packages = append(packages, line)
405379 }
406380
407- switch err := scanner.Err(); {
408- case err != nil:
381+ if err := scanner.Err(); err != nil {
409382 return nil, fmt.Errorf("error reading package file: %w", err)
410383 }
411384
@@ -417,8 +390,7 @@ func (p *BaseInstallPhase) generateFstab(progressChan chan<- ProgressUpdate) err
417390 p.SendOutput(progressChan, "Generating fstab with UUIDs...")
418391
419392 result := p.sysExec.RunSimple("sh", "-c", "genfstab -U /mnt >> /mnt/etc/fstab")
420- switch {
421- case result.ExitCode != 0:
393+ if result.ExitCode != 0 {
422394 return fmt.Errorf("genfstab failed: %w", result.Error)
423395 }
424396
@@ -430,15 +402,13 @@ func (p *BaseInstallPhase) generateFstab(progressChan chan<- ProgressUpdate) err
430402 func (p *BaseInstallPhase) PostCheck() error {
431403 // Check if base system exists
432404 result := p.sysExec.RunSimple("test", "-d", "/mnt/usr")
433- switch {
434- case result.ExitCode != 0:
405+ if result.ExitCode != 0 {
435406 return fmt.Errorf("/mnt/usr does not exist")
436407 }
437408
438409 // Check if fstab exists
439410 result = p.sysExec.RunSimple("test", "-f", "/mnt/etc/fstab")
440- switch {
441- case result.ExitCode != 0:
411+ if result.ExitCode != 0 {
442412 return fmt.Errorf("/mnt/etc/fstab was not created")
443413 }
444414
@@ -31,8 +31,7 @@ func NewBaseInstallPhase(cfg *config.Config, log *logger.Logger, fs interfaces.F
31 func (p *BaseInstallPhase) PreCheck() error {31 func (p *BaseInstallPhase) PreCheck() error {
32 // Verify /mnt is mounted32 // Verify /mnt is mounted
33 result := p.sysExec.RunSimple("mountpoint", "-q", "/mnt")33 result := p.sysExec.RunSimple("mountpoint", "-q", "/mnt")
34- switch {34+ if result.ExitCode != 0 {
35- case result.ExitCode != 0:
36 return fmt.Errorf("/mnt is not mounted")35 return fmt.Errorf("/mnt is not mounted")
37 }36 }
38 37
@@ -44,8 +43,7 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
44 p.SendProgress(progressChan, "Starting base installation...", 1, 5)43 p.SendProgress(progressChan, "Starting base installation...", 1, 5)
45 44
46 // Step 1: Configure ISO pacman45 // Step 1: Configure ISO pacman
47- switch err := p.configurePacman(progressChan); {46+ if err := p.configurePacman(progressChan); err != nil {
48- case err != nil:
49 p.SendError(progressChan, err)47 p.SendError(progressChan, err)
50 return PhaseResult{Success: false, Error: err}48 return PhaseResult{Success: false, Error: err}
51 }49 }
@@ -53,18 +51,15 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
53 p.SendProgress(progressChan, "Detecting CPU and microcode...", 2, 5)51 p.SendProgress(progressChan, "Detecting CPU and microcode...", 2, 5)
54 52
55 // Step 2: Detect CPU and select microcode53 // Step 2: Detect CPU and select microcode
56- switch err := p.detectCPU(progressChan); {54+ if err := p.detectCPU(progressChan); err != nil {
57- case err != nil:
58 p.SendError(progressChan, err)55 p.SendError(progressChan, err)
59 return PhaseResult{Success: false, Error: err}56 return PhaseResult{Success: false, Error: err}
60 }57 }
61 58
62 // Step 2.5: Configure CachyOS repository on ISO if needed59 // Step 2.5: Configure CachyOS repository on ISO if needed
63- switch {60+ if p.config.KernelChoice == config.KernelLinuxCachyOS {
64- case p.config.KernelChoice == config.KernelLinuxCachyOS:
65 p.SendProgress(progressChan, "Configuring CachyOS repository...", 2, 5)61 p.SendProgress(progressChan, "Configuring CachyOS repository...", 2, 5)
66- switch err := p.configureCachyOSRepo(progressChan); {62+ if err := p.configureCachyOSRepo(progressChan); err != nil {
67- case err != nil:
68 p.SendError(progressChan, err)63 p.SendError(progressChan, err)
69 return PhaseResult{Success: false, Error: err}64 return PhaseResult{Success: false, Error: err}
70 }65 }
@@ -73,8 +68,7 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
73 p.SendProgress(progressChan, "Installing base system...", 3, 5)68 p.SendProgress(progressChan, "Installing base system...", 3, 5)
74 69
75 // Step 3: Run pacstrap70 // Step 3: Run pacstrap
76- switch err := p.runPacstrap(progressChan); {71+ if err := p.runPacstrap(progressChan); err != nil {
77- case err != nil:
78 p.SendError(progressChan, err)72 p.SendError(progressChan, err)
79 return PhaseResult{Success: false, Error: err}73 return PhaseResult{Success: false, Error: err}
80 }74 }
@@ -82,8 +76,7 @@ func (p *BaseInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
82 p.SendProgress(progressChan, "Generating fstab...", 4, 5)76 p.SendProgress(progressChan, "Generating fstab...", 4, 5)
83 77
84 // Step 4: Generate fstab78 // Step 4: Generate fstab
85- switch err := p.generateFstab(progressChan); {79+ if err := p.generateFstab(progressChan); err != nil {
86- case err != nil:
87 p.SendError(progressChan, err)80 p.SendError(progressChan, err)
88 return PhaseResult{Success: false, Error: err}81 return PhaseResult{Success: false, Error: err}
89 }82 }
@@ -103,8 +96,7 @@ func (p *BaseInstallPhase) configurePacman(progressChan chan<- ProgressUpdate) e
103 "s/^#ParallelDownloads = 5$/ParallelDownloads = 10/",96 "s/^#ParallelDownloads = 5$/ParallelDownloads = 10/",
104 "/etc/pacman.conf")97 "/etc/pacman.conf")
105 98
106- switch {99+ if result.ExitCode != 0 {
107- case result.ExitCode != 0:
108 return fmt.Errorf("pacman configuration failed: %w", result.Error)100 return fmt.Errorf("pacman configuration failed: %w", result.Error)
109 }101 }
110 102
@@ -119,14 +111,12 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
119 // Import CachyOS GPG key111 // Import CachyOS GPG key
120 p.SendOutput(progressChan, "Importing CachyOS GPG key...")112 p.SendOutput(progressChan, "Importing CachyOS GPG key...")
121 result := p.logger.ExecCommand("pacman-key", "--recv-keys", "F3B607488DB35A47", "--keyserver", "keyserver.ubuntu.com")113 result := p.logger.ExecCommand("pacman-key", "--recv-keys", "F3B607488DB35A47", "--keyserver", "keyserver.ubuntu.com")
122- switch {114+ if result.ExitCode != 0 {
123- case result.ExitCode != 0:
124 return fmt.Errorf("failed to receive CachyOS GPG key: %w", result.Error)115 return fmt.Errorf("failed to receive CachyOS GPG key: %w", result.Error)
125 }116 }
126 117
127 result = p.logger.ExecCommand("pacman-key", "--lsign-key", "F3B607488DB35A47")118 result = p.logger.ExecCommand("pacman-key", "--lsign-key", "F3B607488DB35A47")
128- switch {119+ if result.ExitCode != 0 {
129- case result.ExitCode != 0:
130 return fmt.Errorf("failed to sign CachyOS GPG key: %w", result.Error)120 return fmt.Errorf("failed to sign CachyOS GPG key: %w", result.Error)
131 }121 }
132 122
@@ -134,8 +124,7 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
134 124
135 // Check if CachyOS repo already configured125 // Check if CachyOS repo already configured
136 content, err := p.fs.ReadFile("/etc/pacman.conf")126 content, err := p.fs.ReadFile("/etc/pacman.conf")
137- switch {127+ if err != nil {
138- case err != nil:
139 return fmt.Errorf("failed to read pacman.conf: %w", err)128 return fmt.Errorf("failed to read pacman.conf: %w", err)
140 }129 }
141 130
@@ -162,8 +151,7 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
162 151
163 contentStr = strings.Join(newLines, "\n")152 contentStr = strings.Join(newLines, "\n")
164 153
165- switch err := p.fs.WriteFile("/etc/pacman.conf", []byte(contentStr), 0644); {154+ if err := p.fs.WriteFile("/etc/pacman.conf", []byte(contentStr), 0644); err != nil {
166- case err != nil:
167 return fmt.Errorf("failed to write pacman.conf: %w", err)155 return fmt.Errorf("failed to write pacman.conf: %w", err)
168 }156 }
169 }157 }
@@ -172,16 +160,14 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
172 p.SendOutput(progressChan, "Creating CachyOS mirrorlist...")160 p.SendOutput(progressChan, "Creating CachyOS mirrorlist...")
173 mirrorlist := "## CachyOS mirrorlist\nServer = https://mirror.cachyos.org/repo/$arch/$repo\n"161 mirrorlist := "## CachyOS mirrorlist\nServer = https://mirror.cachyos.org/repo/$arch/$repo\n"
174 162
175- switch err := p.fs.WriteFile("/etc/pacman.d/cachyos-mirrorlist", []byte(mirrorlist), 0644); {163+ if err := p.fs.WriteFile("/etc/pacman.d/cachyos-mirrorlist", []byte(mirrorlist), 0644); err != nil {
176- case err != nil:
177 return fmt.Errorf("failed to create cachyos-mirrorlist: %w", err)164 return fmt.Errorf("failed to create cachyos-mirrorlist: %w", err)
178 }165 }
179 166
180 // Sync databases167 // Sync databases
181 p.SendOutput(progressChan, "Syncing package databases...")168 p.SendOutput(progressChan, "Syncing package databases...")
182 result = p.logger.ExecCommand("pacman", "-Sy")169 result = p.logger.ExecCommand("pacman", "-Sy")
183- switch {170+ if result.ExitCode != 0 {
184- case result.ExitCode != 0:
185 return fmt.Errorf("failed to sync databases: %w", result.Error)171 return fmt.Errorf("failed to sync databases: %w", result.Error)
186 }172 }
187 173
@@ -193,8 +179,7 @@ func (p *BaseInstallPhase) configureCachyOSRepo(progressChan chan<- ProgressUpda
193 func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate) error {179 func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate) error {
194 // Read ISO's pacman.conf to check if CachyOS is configured180 // Read ISO's pacman.conf to check if CachyOS is configured
195 content, err := p.fs.ReadFile("/etc/pacman.conf")181 content, err := p.fs.ReadFile("/etc/pacman.conf")
196- switch {182+ if err != nil {
197- case err != nil:
198 return fmt.Errorf("failed to read ISO pacman.conf: %w", err)183 return fmt.Errorf("failed to read ISO pacman.conf: %w", err)
199 }184 }
200 185
@@ -202,8 +187,7 @@ func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate)
202 187
203 // Read installed system's pacman.conf188 // Read installed system's pacman.conf
204 mntContent, err := p.fs.ReadFile("/mnt/etc/pacman.conf")189 mntContent, err := p.fs.ReadFile("/mnt/etc/pacman.conf")
205- switch {190+ if err != nil {
206- case err != nil:
207 return fmt.Errorf("failed to read /mnt/etc/pacman.conf: %w", err)191 return fmt.Errorf("failed to read /mnt/etc/pacman.conf: %w", err)
208 }192 }
209 193
@@ -228,8 +212,7 @@ func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate)
228 212
229 mntContentStr = strings.Join(newLines, "\n")213 mntContentStr = strings.Join(newLines, "\n")
230 214
231- switch err := p.fs.WriteFile("/mnt/etc/pacman.conf", []byte(mntContentStr), 0644); {215+ if err := p.fs.WriteFile("/mnt/etc/pacman.conf", []byte(mntContentStr), 0644); err != nil {
232- case err != nil:
233 return fmt.Errorf("failed to write /mnt/etc/pacman.conf: %w", err)216 return fmt.Errorf("failed to write /mnt/etc/pacman.conf: %w", err)
234 }217 }
235 218
@@ -238,14 +221,12 @@ func (p *BaseInstallPhase) copyCachyOSConfig(progressChan chan<- ProgressUpdate)
238 221
239 // Copy mirrorlist from ISO to installed system222 // Copy mirrorlist from ISO to installed system
240 result := p.logger.ExecCommand("mkdir", "-p", "/mnt/etc/pacman.d")223 result := p.logger.ExecCommand("mkdir", "-p", "/mnt/etc/pacman.d")
241- switch {224+ if result.ExitCode != 0 {
242- case result.ExitCode != 0:
243 return fmt.Errorf("failed to create /mnt/etc/pacman.d: %w", result.Error)225 return fmt.Errorf("failed to create /mnt/etc/pacman.d: %w", result.Error)
244 }226 }
245 227
246 result = p.logger.ExecCommand("cp", "/etc/pacman.d/cachyos-mirrorlist", "/mnt/etc/pacman.d/cachyos-mirrorlist")228 result = p.logger.ExecCommand("cp", "/etc/pacman.d/cachyos-mirrorlist", "/mnt/etc/pacman.d/cachyos-mirrorlist")
247- switch {229+ if result.ExitCode != 0 {
248- case result.ExitCode != 0:
249 return fmt.Errorf("failed to copy cachyos-mirrorlist: %w", result.Error)230 return fmt.Errorf("failed to copy cachyos-mirrorlist: %w", result.Error)
250 }231 }
251 232
@@ -259,8 +240,7 @@ func (p *BaseInstallPhase) detectCPU(progressChan chan<- ProgressUpdate) error {
259 240
260 // Read /proc/cpuinfo to detect vendor241 // Read /proc/cpuinfo to detect vendor
261 file, err := p.fs.Open("/proc/cpuinfo")242 file, err := p.fs.Open("/proc/cpuinfo")
262- switch {243+ if err != nil {
263- case err != nil:
264 return fmt.Errorf("failed to read /proc/cpuinfo: %w", err)244 return fmt.Errorf("failed to read /proc/cpuinfo: %w", err)
265 }245 }
266 defer file.Close()246 defer file.Close()
@@ -298,8 +278,7 @@ func (p *BaseInstallPhase) detectCPU(progressChan chan<- ProgressUpdate) error {
298 p.config.Microcode = microcode278 p.config.Microcode = microcode
299 p.config.CPUVendor = cpuType279 p.config.CPUVendor = cpuType
300 280
301- switch {281+ if microcode != "" {
302- case microcode != "":
303 p.SendOutput(progressChan, fmt.Sprintf("[OK] Detected %s CPU", cpuType))282 p.SendOutput(progressChan, fmt.Sprintf("[OK] Detected %s CPU", cpuType))
304 p.SendOutput(progressChan, fmt.Sprintf(" Microcode: %s", microcode))283 p.SendOutput(progressChan, fmt.Sprintf(" Microcode: %s", microcode))
305 }284 }
@@ -311,8 +290,7 @@ func (p *BaseInstallPhase) detectCPU(progressChan chan<- ProgressUpdate) error {
311 func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error {290 func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error {
312 // Load base packages from embedded list291 // Load base packages from embedded list
313 packages, err := p.loadBasePackages()292 packages, err := p.loadBasePackages()
314- switch {293+ if err != nil {
315- case err != nil:
316 return fmt.Errorf("failed to load package list: %w", err)294 return fmt.Errorf("failed to load package list: %w", err)
317 }295 }
318 296
@@ -328,8 +306,7 @@ func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error
328 }306 }
329 307
330 // Add microcode308 // Add microcode
331- switch {309+ if p.config.Microcode != "" {
332- case p.config.Microcode != "":
333 packages = append(packages, p.config.Microcode)310 packages = append(packages, p.config.Microcode)
334 p.SendOutput(progressChan, fmt.Sprintf("Adding microcode: %s", p.config.Microcode))311 p.SendOutput(progressChan, fmt.Sprintf("Adding microcode: %s", p.config.Microcode))
335 }312 }
@@ -355,16 +332,14 @@ func (p *BaseInstallPhase) runPacstrap(progressChan chan<- ProgressUpdate) error
355 args := append([]string{"/mnt"}, packages...)332 args := append([]string{"/mnt"}, packages...)
356 result := p.logger.ExecCommand("pacstrap", args...)333 result := p.logger.ExecCommand("pacstrap", args...)
357 334
358- switch {335+ if result.ExitCode != 0 {
359- case result.ExitCode != 0:
360 return fmt.Errorf("pacstrap failed: %w", result.Error)336 return fmt.Errorf("pacstrap failed: %w", result.Error)
361 }337 }
362 338
363 p.SendOutput(progressChan, fmt.Sprintf("[OK] Installed %d packages", len(packages)))339 p.SendOutput(progressChan, fmt.Sprintf("[OK] Installed %d packages", len(packages)))
364 340
365 // Copy CachyOS configuration to installed system if needed341 // Copy CachyOS configuration to installed system if needed
366- switch {342+ if p.config.KernelChoice == config.KernelLinuxCachyOS {
367- case p.config.KernelChoice == config.KernelLinuxCachyOS:
368 p.SendOutput(progressChan, "Configuring CachyOS repository in installed system...")343 p.SendOutput(progressChan, "Configuring CachyOS repository in installed system...")
369 if err := p.copyCachyOSConfig(progressChan); err != nil {344 if err := p.copyCachyOSConfig(progressChan); err != nil {
370 return fmt.Errorf("failed to configure CachyOS in installed system: %w", err)345 return fmt.Errorf("failed to configure CachyOS in installed system: %w", err)
@@ -381,8 +356,7 @@ func (p *BaseInstallPhase) loadBasePackages() ([]string, error) {
381 packageFile := config.DefaultInstallDir + "/" + config.BasePackagesFile356 packageFile := config.DefaultInstallDir + "/" + config.BasePackagesFile
382 357
383 file, err := p.fs.Open(packageFile)358 file, err := p.fs.Open(packageFile)
384- switch {359+ if err != nil {
385- case err != nil:
386 return nil, fmt.Errorf("failed to open %s: %w", packageFile, err)360 return nil, fmt.Errorf("failed to open %s: %w", packageFile, err)
387 }361 }
388 defer file.Close()362 defer file.Close()
@@ -404,8 +378,7 @@ func (p *BaseInstallPhase) loadBasePackages() ([]string, error) {
404 packages = append(packages, line)378 packages = append(packages, line)
405 }379 }
406 380
407- switch err := scanner.Err(); {381+ if err := scanner.Err(); err != nil {
408- case err != nil:
409 return nil, fmt.Errorf("error reading package file: %w", err)382 return nil, fmt.Errorf("error reading package file: %w", err)
410 }383 }
411 384
@@ -417,8 +390,7 @@ func (p *BaseInstallPhase) generateFstab(progressChan chan<- ProgressUpdate) err
417 p.SendOutput(progressChan, "Generating fstab with UUIDs...")390 p.SendOutput(progressChan, "Generating fstab with UUIDs...")
418 391
419 result := p.sysExec.RunSimple("sh", "-c", "genfstab -U /mnt >> /mnt/etc/fstab")392 result := p.sysExec.RunSimple("sh", "-c", "genfstab -U /mnt >> /mnt/etc/fstab")
420- switch {393+ if result.ExitCode != 0 {
421- case result.ExitCode != 0:
422 return fmt.Errorf("genfstab failed: %w", result.Error)394 return fmt.Errorf("genfstab failed: %w", result.Error)
423 }395 }
424 396
@@ -430,15 +402,13 @@ func (p *BaseInstallPhase) generateFstab(progressChan chan<- ProgressUpdate) err
430 func (p *BaseInstallPhase) PostCheck() error {402 func (p *BaseInstallPhase) PostCheck() error {
431 // Check if base system exists403 // Check if base system exists
432 result := p.sysExec.RunSimple("test", "-d", "/mnt/usr")404 result := p.sysExec.RunSimple("test", "-d", "/mnt/usr")
433- switch {405+ if result.ExitCode != 0 {
434- case result.ExitCode != 0:
435 return fmt.Errorf("/mnt/usr does not exist")406 return fmt.Errorf("/mnt/usr does not exist")
436 }407 }
437 408
438 // Check if fstab exists409 // Check if fstab exists
439 result = p.sysExec.RunSimple("test", "-f", "/mnt/etc/fstab")410 result = p.sysExec.RunSimple("test", "-f", "/mnt/etc/fstab")
440- switch {411+ if result.ExitCode != 0 {
441- case result.ExitCode != 0:
442 return fmt.Errorf("/mnt/etc/fstab was not created")412 return fmt.Errorf("/mnt/etc/fstab was not created")
443 }413 }
444 414
M internal/phases/boot.go +20 -40
@@ -34,15 +34,13 @@ func NewBootPhase(cfg *config.Config, log *logger.Logger, fs interfaces.FileSyst
3434 func (p *BootPhase) PreCheck() error {
3535 // Verify /mnt is mounted
3636 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
37- switch {
38- case result.ExitCode != 0:
37+ if result.ExitCode != 0 {
3938 return fmt.Errorf("%s is not mounted", config.PathMnt)
4039 }
4140
4241 // Verify boot partition is mounted
4342 result = p.sysExec.RunSimple("mountpoint", "-q", config.PathMntBoot)
44- switch {
45- case result.ExitCode != 0:
43+ if result.ExitCode != 0 {
4644 return fmt.Errorf("%s is not mounted", config.PathMntBoot)
4745 }
4846
@@ -54,8 +52,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
5452 p.SendProgress(progressChan, "Starting bootloader installation...", 1, 4)
5553
5654 // Step 1: Configure initramfs
57- switch err := p.configureMkinitcpio(progressChan); {
58- case err != nil:
55+ if err := p.configureMkinitcpio(progressChan); err != nil {
5956 p.SendError(progressChan, err)
6057 return PhaseResult{Success: false, Error: err}
6158 }
@@ -63,8 +60,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
6360 p.SendProgress(progressChan, "Installing Limine bootloader...", 2, 4)
6461
6562 // Step 2: Install Limine
66- switch err := p.installLimine(progressChan); {
67- case err != nil:
63+ if err := p.installLimine(progressChan); err != nil {
6864 p.SendError(progressChan, err)
6965 return PhaseResult{Success: false, Error: err}
7066 }
@@ -72,8 +68,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
7268 p.SendProgress(progressChan, "Configuring Limine...", 3, 4)
7369
7470 // Step 3: Configure Limine
75- switch err := p.configureLimine(progressChan); {
76- case err != nil:
71+ if err := p.configureLimine(progressChan); err != nil {
7772 p.SendError(progressChan, err)
7873 return PhaseResult{Success: false, Error: err}
7974 }
@@ -81,8 +76,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
8176 p.SendProgress(progressChan, "Creating UEFI boot entry...", 4, 4)
8277
8378 // Step 4: Create UEFI boot entry
84- switch err := p.createUEFIEntry(progressChan); {
85- case err != nil:
79+ if err := p.createUEFIEntry(progressChan); err != nil {
8680 p.SendError(progressChan, err)
8781 return PhaseResult{Success: false, Error: err}
8882 }
@@ -99,8 +93,7 @@ func (p *BootPhase) configureMkinitcpio(progressChan chan<- ProgressUpdate) erro
9993
10094 // Read current mkinitcpio.conf
10195 content, err := p.fs.ReadFile(config.PathMntEtcMkinitcpio)
102- switch {
103- case err != nil:
96+ if err != nil {
10497 return fmt.Errorf("failed to read mkinitcpio.conf: %w", err)
10598 }
10699
@@ -120,15 +113,13 @@ func (p *BootPhase) configureMkinitcpio(progressChan chan<- ProgressUpdate) erro
120113 newContent := hooksRegex.ReplaceAllString(string(content), hooks)
121114
122115 // Write updated config
123- switch err := p.fs.WriteFile(config.PathMntEtcMkinitcpio, []byte(newContent), 0644); {
124- case err != nil:
116+ if err := p.fs.WriteFile(config.PathMntEtcMkinitcpio, []byte(newContent), 0644); err != nil {
125117 return fmt.Errorf("failed to write mkinitcpio.conf: %w", err)
126118 }
127119
128120 // Regenerate initramfs
129121 p.SendOutput(progressChan, "Regenerating initramfs...")
130- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); {
131- case err != nil:
122+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); err != nil {
132123 return fmt.Errorf("failed to regenerate initramfs: %w", err)
133124 }
134125
@@ -151,8 +142,7 @@ func (p *BootPhase) installLimine(progressChan chan<- ProgressUpdate) error {
151142 }
152143
153144 // Create Limine directory
154- switch err := p.fs.MkdirAll(config.PathMntBootEFILimine, 0755); {
155- case err != nil:
145+ if err := p.fs.MkdirAll(config.PathMntBootEFILimine, 0755); err != nil {
156146 return fmt.Errorf("failed to create Limine directory: %w", err)
157147 }
158148
@@ -162,8 +152,7 @@ func (p *BootPhase) installLimine(progressChan chan<- ProgressUpdate) error {
162152
163153 cpCmd := fmt.Sprintf("cp %s %s", srcBootloader, dstBootloader)
164154 result := p.logger.ExecCommand("sh", "-c", cpCmd)
165- switch {
166- case result.ExitCode != 0:
155+ if result.ExitCode != 0 {
167156 return fmt.Errorf("failed to copy Limine bootloader: %w", result.Error)
168157 }
169158
@@ -179,8 +168,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
179168 // Get root partition UUID
180169 rootPartition := p.config.RootPartition
181170 result := p.sysExec.RunSimple("blkid", "-s", "UUID", "-o", "value", rootPartition)
182- switch {
183- case result.ExitCode != 0:
171+ if result.ExitCode != 0 {
184172 return fmt.Errorf("failed to get root partition UUID: %w", result.Error)
185173 }
186174
@@ -199,8 +187,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
199187 }
200188
201189 // Add AMD-specific kernel parameters if configured
202- switch {
203- case p.config.AMDPState != "":
190+ if p.config.AMDPState != "" {
204191 // Detect CPU to get Zen generation for proper kernel params
205192 cpuInfo, err := p.sysExec.DetectCPUInfo()
206193 var amdParams string
@@ -224,8 +211,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
224211 // Read Limine config template
225212 templatePath := p.getInstallPath(config.LimineConfigTemplate)
226213 templateContent, err := p.fs.ReadFile(templatePath)
227- switch {
228- case err != nil:
214+ if err != nil {
229215 return fmt.Errorf("failed to read Limine template: %w", err)
230216 }
231217
@@ -240,8 +226,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
240226
241227 // Write Limine configuration
242228 limineConfigPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
243- switch err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); {
244- case err != nil:
229+ if err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); err != nil {
245230 return fmt.Errorf("failed to write Limine config: %w", err)
246231 }
247232
@@ -256,8 +241,7 @@ func (p *BootPhase) createUEFIEntry(progressChan chan<- ProgressUpdate) error {
256241
257242 // Extract EFI partition number
258243 efiPartNum := p.extractPartitionNumber(p.config.EFIPartition)
259- switch {
260- case efiPartNum == "":
244+ if efiPartNum == "" {
261245 return fmt.Errorf("failed to extract EFI partition number from %s", p.config.EFIPartition)
262246 }
263247
@@ -269,8 +253,7 @@ func (p *BootPhase) createUEFIEntry(progressChan chan<- ProgressUpdate) error {
269253 config.UEFIBootLoader,
270254 )
271255
272- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, efiCmd); {
273- case err != nil:
256+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, efiCmd); err != nil {
274257 return fmt.Errorf("failed to create UEFI boot entry: %w", err)
275258 }
276259
@@ -299,15 +282,13 @@ func (p *BootPhase) extractPartitionNumber(partPath string) string {
299282 func (p *BootPhase) PostCheck() error {
300283 // Verify Limine bootloader exists
301284 bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader)
302- switch _, err := p.fs.Stat(bootloaderPath); {
303- case p.fs.IsNotExist(err):
285+ if _, err := p.fs.Stat(bootloaderPath); p.fs.IsNotExist(err) {
304286 return fmt.Errorf("Limine bootloader was not installed")
305287 }
306288
307289 // Verify Limine config exists
308290 configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
309- switch _, err := p.fs.Stat(configPath); {
310- case p.fs.IsNotExist(err):
291+ if _, err := p.fs.Stat(configPath); p.fs.IsNotExist(err) {
311292 return fmt.Errorf("Limine config was not created")
312293 }
313294
@@ -317,8 +298,7 @@ func (p *BootPhase) PostCheck() error {
317298 // Rollback for boot phase
318299 func (p *BootPhase) Rollback() error {
319300 // Remove Limine files if they exist
320- switch err := p.fs.RemoveAll(config.PathMntBootEFILimine); {
321- case err != nil:
301+ if err := p.fs.RemoveAll(config.PathMntBootEFILimine); err != nil {
322302 p.SendOutput(nil, fmt.Sprintf("[WARN] Failed to remove Limine directory: %v", err))
323303 }
324304
@@ -34,15 +34,13 @@ func NewBootPhase(cfg *config.Config, log *logger.Logger, fs interfaces.FileSyst
34 func (p *BootPhase) PreCheck() error {34 func (p *BootPhase) PreCheck() error {
35 // Verify /mnt is mounted35 // Verify /mnt is mounted
36 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)36 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
37- switch {37+ if result.ExitCode != 0 {
38- case result.ExitCode != 0:
39 return fmt.Errorf("%s is not mounted", config.PathMnt)38 return fmt.Errorf("%s is not mounted", config.PathMnt)
40 }39 }
41 40
42 // Verify boot partition is mounted41 // Verify boot partition is mounted
43 result = p.sysExec.RunSimple("mountpoint", "-q", config.PathMntBoot)42 result = p.sysExec.RunSimple("mountpoint", "-q", config.PathMntBoot)
44- switch {43+ if result.ExitCode != 0 {
45- case result.ExitCode != 0:
46 return fmt.Errorf("%s is not mounted", config.PathMntBoot)44 return fmt.Errorf("%s is not mounted", config.PathMntBoot)
47 }45 }
48 46
@@ -54,8 +52,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
54 p.SendProgress(progressChan, "Starting bootloader installation...", 1, 4)52 p.SendProgress(progressChan, "Starting bootloader installation...", 1, 4)
55 53
56 // Step 1: Configure initramfs54 // Step 1: Configure initramfs
57- switch err := p.configureMkinitcpio(progressChan); {55+ if err := p.configureMkinitcpio(progressChan); err != nil {
58- case err != nil:
59 p.SendError(progressChan, err)56 p.SendError(progressChan, err)
60 return PhaseResult{Success: false, Error: err}57 return PhaseResult{Success: false, Error: err}
61 }58 }
@@ -63,8 +60,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
63 p.SendProgress(progressChan, "Installing Limine bootloader...", 2, 4)60 p.SendProgress(progressChan, "Installing Limine bootloader...", 2, 4)
64 61
65 // Step 2: Install Limine62 // Step 2: Install Limine
66- switch err := p.installLimine(progressChan); {63+ if err := p.installLimine(progressChan); err != nil {
67- case err != nil:
68 p.SendError(progressChan, err)64 p.SendError(progressChan, err)
69 return PhaseResult{Success: false, Error: err}65 return PhaseResult{Success: false, Error: err}
70 }66 }
@@ -72,8 +68,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
72 p.SendProgress(progressChan, "Configuring Limine...", 3, 4)68 p.SendProgress(progressChan, "Configuring Limine...", 3, 4)
73 69
74 // Step 3: Configure Limine70 // Step 3: Configure Limine
75- switch err := p.configureLimine(progressChan); {71+ if err := p.configureLimine(progressChan); err != nil {
76- case err != nil:
77 p.SendError(progressChan, err)72 p.SendError(progressChan, err)
78 return PhaseResult{Success: false, Error: err}73 return PhaseResult{Success: false, Error: err}
79 }74 }
@@ -81,8 +76,7 @@ func (p *BootPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
81 p.SendProgress(progressChan, "Creating UEFI boot entry...", 4, 4)76 p.SendProgress(progressChan, "Creating UEFI boot entry...", 4, 4)
82 77
83 // Step 4: Create UEFI boot entry78 // Step 4: Create UEFI boot entry
84- switch err := p.createUEFIEntry(progressChan); {79+ if err := p.createUEFIEntry(progressChan); err != nil {
85- case err != nil:
86 p.SendError(progressChan, err)80 p.SendError(progressChan, err)
87 return PhaseResult{Success: false, Error: err}81 return PhaseResult{Success: false, Error: err}
88 }82 }
@@ -99,8 +93,7 @@ func (p *BootPhase) configureMkinitcpio(progressChan chan<- ProgressUpdate) erro
99 93
100 // Read current mkinitcpio.conf94 // Read current mkinitcpio.conf
101 content, err := p.fs.ReadFile(config.PathMntEtcMkinitcpio)95 content, err := p.fs.ReadFile(config.PathMntEtcMkinitcpio)
102- switch {96+ if err != nil {
103- case err != nil:
104 return fmt.Errorf("failed to read mkinitcpio.conf: %w", err)97 return fmt.Errorf("failed to read mkinitcpio.conf: %w", err)
105 }98 }
106 99
@@ -120,15 +113,13 @@ func (p *BootPhase) configureMkinitcpio(progressChan chan<- ProgressUpdate) erro
120 newContent := hooksRegex.ReplaceAllString(string(content), hooks)113 newContent := hooksRegex.ReplaceAllString(string(content), hooks)
121 114
122 // Write updated config115 // Write updated config
123- switch err := p.fs.WriteFile(config.PathMntEtcMkinitcpio, []byte(newContent), 0644); {116+ if err := p.fs.WriteFile(config.PathMntEtcMkinitcpio, []byte(newContent), 0644); err != nil {
124- case err != nil:
125 return fmt.Errorf("failed to write mkinitcpio.conf: %w", err)117 return fmt.Errorf("failed to write mkinitcpio.conf: %w", err)
126 }118 }
127 119
128 // Regenerate initramfs120 // Regenerate initramfs
129 p.SendOutput(progressChan, "Regenerating initramfs...")121 p.SendOutput(progressChan, "Regenerating initramfs...")
130- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); {122+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); err != nil {
131- case err != nil:
132 return fmt.Errorf("failed to regenerate initramfs: %w", err)123 return fmt.Errorf("failed to regenerate initramfs: %w", err)
133 }124 }
134 125
@@ -151,8 +142,7 @@ func (p *BootPhase) installLimine(progressChan chan<- ProgressUpdate) error {
151 }142 }
152 143
153 // Create Limine directory144 // Create Limine directory
154- switch err := p.fs.MkdirAll(config.PathMntBootEFILimine, 0755); {145+ if err := p.fs.MkdirAll(config.PathMntBootEFILimine, 0755); err != nil {
155- case err != nil:
156 return fmt.Errorf("failed to create Limine directory: %w", err)146 return fmt.Errorf("failed to create Limine directory: %w", err)
157 }147 }
158 148
@@ -162,8 +152,7 @@ func (p *BootPhase) installLimine(progressChan chan<- ProgressUpdate) error {
162 152
163 cpCmd := fmt.Sprintf("cp %s %s", srcBootloader, dstBootloader)153 cpCmd := fmt.Sprintf("cp %s %s", srcBootloader, dstBootloader)
164 result := p.logger.ExecCommand("sh", "-c", cpCmd)154 result := p.logger.ExecCommand("sh", "-c", cpCmd)
165- switch {155+ if result.ExitCode != 0 {
166- case result.ExitCode != 0:
167 return fmt.Errorf("failed to copy Limine bootloader: %w", result.Error)156 return fmt.Errorf("failed to copy Limine bootloader: %w", result.Error)
168 }157 }
169 158
@@ -179,8 +168,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
179 // Get root partition UUID168 // Get root partition UUID
180 rootPartition := p.config.RootPartition169 rootPartition := p.config.RootPartition
181 result := p.sysExec.RunSimple("blkid", "-s", "UUID", "-o", "value", rootPartition)170 result := p.sysExec.RunSimple("blkid", "-s", "UUID", "-o", "value", rootPartition)
182- switch {171+ if result.ExitCode != 0 {
183- case result.ExitCode != 0:
184 return fmt.Errorf("failed to get root partition UUID: %w", result.Error)172 return fmt.Errorf("failed to get root partition UUID: %w", result.Error)
185 }173 }
186 174
@@ -199,8 +187,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
199 }187 }
200 188
201 // Add AMD-specific kernel parameters if configured189 // Add AMD-specific kernel parameters if configured
202- switch {190+ if p.config.AMDPState != "" {
203- case p.config.AMDPState != "":
204 // Detect CPU to get Zen generation for proper kernel params191 // Detect CPU to get Zen generation for proper kernel params
205 cpuInfo, err := p.sysExec.DetectCPUInfo()192 cpuInfo, err := p.sysExec.DetectCPUInfo()
206 var amdParams string193 var amdParams string
@@ -224,8 +211,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
224 // Read Limine config template211 // Read Limine config template
225 templatePath := p.getInstallPath(config.LimineConfigTemplate)212 templatePath := p.getInstallPath(config.LimineConfigTemplate)
226 templateContent, err := p.fs.ReadFile(templatePath)213 templateContent, err := p.fs.ReadFile(templatePath)
227- switch {214+ if err != nil {
228- case err != nil:
229 return fmt.Errorf("failed to read Limine template: %w", err)215 return fmt.Errorf("failed to read Limine template: %w", err)
230 }216 }
231 217
@@ -240,8 +226,7 @@ func (p *BootPhase) configureLimine(progressChan chan<- ProgressUpdate) error {
240 226
241 // Write Limine configuration227 // Write Limine configuration
242 limineConfigPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)228 limineConfigPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
243- switch err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); {229+ if err := p.fs.WriteFile(limineConfigPath, []byte(limineConfig), 0644); err != nil {
244- case err != nil:
245 return fmt.Errorf("failed to write Limine config: %w", err)230 return fmt.Errorf("failed to write Limine config: %w", err)
246 }231 }
247 232
@@ -256,8 +241,7 @@ func (p *BootPhase) createUEFIEntry(progressChan chan<- ProgressUpdate) error {
256 241
257 // Extract EFI partition number242 // Extract EFI partition number
258 efiPartNum := p.extractPartitionNumber(p.config.EFIPartition)243 efiPartNum := p.extractPartitionNumber(p.config.EFIPartition)
259- switch {244+ if efiPartNum == "" {
260- case efiPartNum == "":
261 return fmt.Errorf("failed to extract EFI partition number from %s", p.config.EFIPartition)245 return fmt.Errorf("failed to extract EFI partition number from %s", p.config.EFIPartition)
262 }246 }
263 247
@@ -269,8 +253,7 @@ func (p *BootPhase) createUEFIEntry(progressChan chan<- ProgressUpdate) error {
269 config.UEFIBootLoader,253 config.UEFIBootLoader,
270 )254 )
271 255
272- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, efiCmd); {256+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, efiCmd); err != nil {
273- case err != nil:
274 return fmt.Errorf("failed to create UEFI boot entry: %w", err)257 return fmt.Errorf("failed to create UEFI boot entry: %w", err)
275 }258 }
276 259
@@ -299,15 +282,13 @@ func (p *BootPhase) extractPartitionNumber(partPath string) string {
299 func (p *BootPhase) PostCheck() error {282 func (p *BootPhase) PostCheck() error {
300 // Verify Limine bootloader exists283 // Verify Limine bootloader exists
301 bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader)284 bootloaderPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineBootloader)
302- switch _, err := p.fs.Stat(bootloaderPath); {285+ if _, err := p.fs.Stat(bootloaderPath); p.fs.IsNotExist(err) {
303- case p.fs.IsNotExist(err):
304 return fmt.Errorf("Limine bootloader was not installed")286 return fmt.Errorf("Limine bootloader was not installed")
305 }287 }
306 288
307 // Verify Limine config exists289 // Verify Limine config exists
308 configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)290 configPath := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
309- switch _, err := p.fs.Stat(configPath); {291+ if _, err := p.fs.Stat(configPath); p.fs.IsNotExist(err) {
310- case p.fs.IsNotExist(err):
311 return fmt.Errorf("Limine config was not created")292 return fmt.Errorf("Limine config was not created")
312 }293 }
313 294
@@ -317,8 +298,7 @@ func (p *BootPhase) PostCheck() error {
317 // Rollback for boot phase298 // Rollback for boot phase
318 func (p *BootPhase) Rollback() error {299 func (p *BootPhase) Rollback() error {
319 // Remove Limine files if they exist300 // Remove Limine files if they exist
320- switch err := p.fs.RemoveAll(config.PathMntBootEFILimine); {301+ if err := p.fs.RemoveAll(config.PathMntBootEFILimine); err != nil {
321- case err != nil:
322 p.SendOutput(nil, fmt.Sprintf("[WARN] Failed to remove Limine directory: %v", err))302 p.SendOutput(nil, fmt.Sprintf("[WARN] Failed to remove Limine directory: %v", err))
323 }303 }
324 304
M internal/phases/bootstrap.go +9 -18
@@ -31,8 +31,7 @@ func NewBootstrapPhase(cfg *config.Config, log *logger.Logger, httpClient interf
3131 func (p *BootstrapPhase) PreCheck() error {
3232 // Check internet connectivity
3333 resp, err := p.httpClient.Get("https://raw.githubusercontent.com")
34- switch {
35- case err != nil:
34+ if err != nil {
3635 return fmt.Errorf("no internet connectivity: %w", err)
3736 }
3837 defer resp.Body.Close()
@@ -45,8 +44,7 @@ func (p *BootstrapPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
4544 p.SendOutput(progressChan, "Starting bootstrap phase...")
4645
4746 // Create install directory
48- switch err := p.fs.MkdirAll(config.DefaultInstallDir, 0755); {
49- case err != nil:
47+ if err := p.fs.MkdirAll(config.DefaultInstallDir, 0755); err != nil {
5048 p.SendError(progressChan, err)
5149 return PhaseResult{Success: false, Error: err}
5250 }
@@ -112,8 +110,7 @@ func (p *BootstrapPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
112110 fileName := filepath.Base(file.destPath)
113111 p.SendProgress(progressChan, fmt.Sprintf("Downloading %s...", fileName), i+1, totalFiles)
114112
115- switch err := p.downloadFile(file.url, file.destPath); {
116- case err != nil:
113+ if err := p.downloadFile(file.url, file.destPath); err != nil {
117114 errMsg := fmt.Errorf("failed to download %s: %w", fileName, err)
118115 p.SendError(progressChan, errMsg)
119116 return PhaseResult{Success: false, Error: errMsg}
@@ -130,35 +127,30 @@ func (p *BootstrapPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
130127 func (p *BootstrapPhase) downloadFile(url, destPath string) error {
131128 // Create destination directory if needed
132129 destDir := filepath.Dir(destPath)
133- switch err := p.fs.MkdirAll(destDir, 0755); {
134- case err != nil:
130+ if err := p.fs.MkdirAll(destDir, 0755); err != nil {
135131 return fmt.Errorf("failed to create directory: %w", err)
136132 }
137133
138134 // Download file
139135 resp, err := p.httpClient.Get(url)
140- switch {
141- case err != nil:
136+ if err != nil {
142137 return fmt.Errorf("HTTP request failed: %w", err)
143138 }
144139 defer resp.Body.Close()
145140
146- switch {
147- case resp.StatusCode != http.StatusOK:
141+ if resp.StatusCode != http.StatusOK {
148142 return fmt.Errorf("HTTP %d: %s", resp.StatusCode, resp.Status)
149143 }
150144
151145 // Create destination file
152146 destFile, err := p.fs.Create(destPath)
153- switch {
154- case err != nil:
147+ if err != nil {
155148 return fmt.Errorf("failed to create file: %w", err)
156149 }
157150 defer destFile.Close()
158151
159152 // Copy content
160- switch _, err := io.Copy(destFile, resp.Body); {
161- case err != nil:
153+ if _, err := io.Copy(destFile, resp.Body); err != nil {
162154 return fmt.Errorf("failed to write file: %w", err)
163155 }
164156
@@ -168,8 +160,7 @@ func (p *BootstrapPhase) downloadFile(url, destPath string) error {
168160 // Rollback removes downloaded files
169161 func (p *BootstrapPhase) Rollback() error {
170162 // Remove install directory
171- switch err := p.fs.RemoveAll(config.DefaultInstallDir); {
172- case err != nil:
163+ if err := p.fs.RemoveAll(config.DefaultInstallDir); err != nil {
173164 return fmt.Errorf("failed to remove install directory: %w", err)
174165 }
175166
@@ -31,8 +31,7 @@ func NewBootstrapPhase(cfg *config.Config, log *logger.Logger, httpClient interf
31 func (p *BootstrapPhase) PreCheck() error {31 func (p *BootstrapPhase) PreCheck() error {
32 // Check internet connectivity32 // Check internet connectivity
33 resp, err := p.httpClient.Get("https://raw.githubusercontent.com")33 resp, err := p.httpClient.Get("https://raw.githubusercontent.com")
34- switch {34+ if err != nil {
35- case err != nil:
36 return fmt.Errorf("no internet connectivity: %w", err)35 return fmt.Errorf("no internet connectivity: %w", err)
37 }36 }
38 defer resp.Body.Close()37 defer resp.Body.Close()
@@ -45,8 +44,7 @@ func (p *BootstrapPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
45 p.SendOutput(progressChan, "Starting bootstrap phase...")44 p.SendOutput(progressChan, "Starting bootstrap phase...")
46 45
47 // Create install directory46 // Create install directory
48- switch err := p.fs.MkdirAll(config.DefaultInstallDir, 0755); {47+ if err := p.fs.MkdirAll(config.DefaultInstallDir, 0755); err != nil {
49- case err != nil:
50 p.SendError(progressChan, err)48 p.SendError(progressChan, err)
51 return PhaseResult{Success: false, Error: err}49 return PhaseResult{Success: false, Error: err}
52 }50 }
@@ -112,8 +110,7 @@ func (p *BootstrapPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
112 fileName := filepath.Base(file.destPath)110 fileName := filepath.Base(file.destPath)
113 p.SendProgress(progressChan, fmt.Sprintf("Downloading %s...", fileName), i+1, totalFiles)111 p.SendProgress(progressChan, fmt.Sprintf("Downloading %s...", fileName), i+1, totalFiles)
114 112
115- switch err := p.downloadFile(file.url, file.destPath); {113+ if err := p.downloadFile(file.url, file.destPath); err != nil {
116- case err != nil:
117 errMsg := fmt.Errorf("failed to download %s: %w", fileName, err)114 errMsg := fmt.Errorf("failed to download %s: %w", fileName, err)
118 p.SendError(progressChan, errMsg)115 p.SendError(progressChan, errMsg)
119 return PhaseResult{Success: false, Error: errMsg}116 return PhaseResult{Success: false, Error: errMsg}
@@ -130,35 +127,30 @@ func (p *BootstrapPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
130 func (p *BootstrapPhase) downloadFile(url, destPath string) error {127 func (p *BootstrapPhase) downloadFile(url, destPath string) error {
131 // Create destination directory if needed128 // Create destination directory if needed
132 destDir := filepath.Dir(destPath)129 destDir := filepath.Dir(destPath)
133- switch err := p.fs.MkdirAll(destDir, 0755); {130+ if err := p.fs.MkdirAll(destDir, 0755); err != nil {
134- case err != nil:
135 return fmt.Errorf("failed to create directory: %w", err)131 return fmt.Errorf("failed to create directory: %w", err)
136 }132 }
137 133
138 // Download file134 // Download file
139 resp, err := p.httpClient.Get(url)135 resp, err := p.httpClient.Get(url)
140- switch {136+ if err != nil {
141- case err != nil:
142 return fmt.Errorf("HTTP request failed: %w", err)137 return fmt.Errorf("HTTP request failed: %w", err)
143 }138 }
144 defer resp.Body.Close()139 defer resp.Body.Close()
145 140
146- switch {141+ if resp.StatusCode != http.StatusOK {
147- case resp.StatusCode != http.StatusOK:
148 return fmt.Errorf("HTTP %d: %s", resp.StatusCode, resp.Status)142 return fmt.Errorf("HTTP %d: %s", resp.StatusCode, resp.Status)
149 }143 }
150 144
151 // Create destination file145 // Create destination file
152 destFile, err := p.fs.Create(destPath)146 destFile, err := p.fs.Create(destPath)
153- switch {147+ if err != nil {
154- case err != nil:
155 return fmt.Errorf("failed to create file: %w", err)148 return fmt.Errorf("failed to create file: %w", err)
156 }149 }
157 defer destFile.Close()150 defer destFile.Close()
158 151
159 // Copy content152 // Copy content
160- switch _, err := io.Copy(destFile, resp.Body); {153+ if _, err := io.Copy(destFile, resp.Body); err != nil {
161- case err != nil:
162 return fmt.Errorf("failed to write file: %w", err)154 return fmt.Errorf("failed to write file: %w", err)
163 }155 }
164 156
@@ -168,8 +160,7 @@ func (p *BootstrapPhase) downloadFile(url, destPath string) error {
168 // Rollback removes downloaded files160 // Rollback removes downloaded files
169 func (p *BootstrapPhase) Rollback() error {161 func (p *BootstrapPhase) Rollback() error {
170 // Remove install directory162 // Remove install directory
171- switch err := p.fs.RemoveAll(config.DefaultInstallDir); {163+ if err := p.fs.RemoveAll(config.DefaultInstallDir); err != nil {
172- case err != nil:
173 return fmt.Errorf("failed to remove install directory: %w", err)164 return fmt.Errorf("failed to remove install directory: %w", err)
174 }165 }
175 166
M internal/phases/partitioning.go +28 -56
@@ -25,8 +25,7 @@ func NewPartitioningPhase(cfg *config.Config, log *logger.Logger, sysExec interf
2525
2626 // PreCheck validates partitioning prerequisites
2727 func (p *PartitioningPhase) PreCheck() error {
28- switch {
29- case p.config.TargetDisk == "":
28+ if p.config.TargetDisk == "" {
3029 return fmt.Errorf("target disk not selected")
3130 }
3231
@@ -38,8 +37,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
3837 p.SendProgress(progressChan, "Starting partitioning...", 1, 5)
3938
4039 // Step 1: Wipe and partition
41- switch err := p.createPartitions(progressChan); {
42- case err != nil:
40+ if err := p.createPartitions(progressChan); err != nil {
4341 p.SendError(progressChan, err)
4442 return PhaseResult{Success: false, Error: err}
4543 }
@@ -47,8 +45,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
4745 p.SendProgress(progressChan, "Formatting partitions...", 2, 5)
4846
4947 // Step 2: Format partitions
50- switch err := p.formatPartitions(progressChan); {
51- case err != nil:
48+ if err := p.formatPartitions(progressChan); err != nil {
5249 p.SendError(progressChan, err)
5350 return PhaseResult{Success: false, Error: err}
5451 }
@@ -56,8 +53,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
5653 p.SendProgress(progressChan, "Creating btrfs subvolumes...", 3, 5)
5754
5855 // Step 3: Create subvolumes
59- switch err := p.createSubvolumes(progressChan); {
60- case err != nil:
56+ if err := p.createSubvolumes(progressChan); err != nil {
6157 p.SendError(progressChan, err)
6258 return PhaseResult{Success: false, Error: err}
6359 }
@@ -65,8 +61,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
6561 p.SendProgress(progressChan, "Mounting filesystems...", 4, 5)
6662
6763 // Step 4: Mount
68- switch err := p.mountFilesystems(progressChan); {
69- case err != nil:
64+ if err := p.mountFilesystems(progressChan); err != nil {
7065 p.SendError(progressChan, err)
7166 return PhaseResult{Success: false, Error: err}
7267 }
@@ -84,15 +79,13 @@ func (p *PartitioningPhase) createPartitions(progressChan chan<- ProgressUpdate)
8479
8580 // Wipe filesystem signatures
8681 result := p.logger.ExecCommand("wipefs", "-af", disk)
87- switch {
88- case result.ExitCode != 0:
82+ if result.ExitCode != 0 {
8983 return fmt.Errorf("wipefs failed: %w", result.Error)
9084 }
9185
9286 // Zap GPT and MBR
9387 result = p.logger.ExecCommand("sgdisk", "--zap-all", disk)
94- switch {
95- case result.ExitCode != 0:
88+ if result.ExitCode != 0 {
9689 return fmt.Errorf("sgdisk zap failed: %w", result.Error)
9790 }
9891
@@ -105,15 +98,13 @@ func (p *PartitioningPhase) createPartitions(progressChan chan<- ProgressUpdate)
10598 "--new=2:0:0", "--typecode=2:8300", "--change-name=2:ROOT",
10699 disk)
107100
108- switch {
109- case result.ExitCode != 0:
101+ if result.ExitCode != 0 {
110102 return fmt.Errorf("sgdisk partition creation failed: %w", result.Error)
111103 }
112104
113105 // Inform kernel of partition table changes
114106 result = p.logger.ExecCommand("partprobe", disk)
115- switch {
116- case result.ExitCode != 0:
107+ if result.ExitCode != 0 {
117108 return fmt.Errorf("partprobe failed: %w", result.Error)
118109 }
119110
@@ -143,14 +134,12 @@ func (p *PartitioningPhase) formatPartitions(progressChan chan<- ProgressUpdate)
143134 p.SendOutput(progressChan, "Formatting EFI partition...")
144135
145136 result := p.logger.ExecCommand("wipefs", "-af", p.config.EFIPartition)
146- switch {
147- case result.ExitCode != 0:
137+ if result.ExitCode != 0 {
148138 return fmt.Errorf("wipefs EFI failed: %w", result.Error)
149139 }
150140
151141 result = p.logger.ExecCommand("mkfs.fat", "-F32", "-n", "EFI", p.config.EFIPartition)
152- switch {
153- case result.ExitCode != 0:
142+ if result.ExitCode != 0 {
154143 return fmt.Errorf("mkfs.fat failed: %w", result.Error)
155144 }
156145
@@ -171,15 +160,13 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
171160
172161 // Use user password for encryption (as per preflight)
173162 password := p.config.UserPassword
174- switch {
175- case password == "":
163+ if password == "" {
176164 return fmt.Errorf("password required for encryption")
177165 }
178166
179167 // Wipe root partition
180168 result := p.logger.ExecCommand("wipefs", "-af", p.config.RootPartition)
181- switch {
182- case result.ExitCode != 0:
169+ if result.ExitCode != 0 {
183170 return fmt.Errorf("wipefs root failed: %w", result.Error)
184171 }
185172
@@ -192,8 +179,7 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
192179 fmt.Sprintf("printf '%%s' '%s' | cryptsetup luksFormat --type luks2 --batch-mode --pbkdf argon2id --iter-time 2000 --label ARCHUP_LUKS --key-file - %s",
193180 password, p.config.RootPartition))
194181
195- switch {
196- case result.ExitCode != 0:
182+ if result.ExitCode != 0 {
197183 return fmt.Errorf("luksFormat failed: %w", result.Error)
198184 }
199185
@@ -202,8 +188,7 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
202188 fmt.Sprintf("printf '%%s' '%s' | cryptsetup open --key-file=- %s cryptroot",
203189 password, p.config.RootPartition))
204190
205- switch {
206- case result.ExitCode != 0:
191+ if result.ExitCode != 0 {
207192 return fmt.Errorf("cryptsetup open failed: %w", result.Error)
208193 }
209194
@@ -212,8 +197,7 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
212197
213198 // Format encrypted device with btrfs
214199 result = p.logger.ExecCommand("mkfs.btrfs", "-f", "-L", "ROOT", p.config.CryptDevice)
215- switch {
216- case result.ExitCode != 0:
200+ if result.ExitCode != 0 {
217201 return fmt.Errorf("mkfs.btrfs on encrypted device failed: %w", result.Error)
218202 }
219203
@@ -226,8 +210,7 @@ func (p *PartitioningPhase) formatPlainRoot(progressChan chan<- ProgressUpdate)
226210 p.SendOutput(progressChan, "Formatting root partition...")
227211
228212 result := p.logger.ExecCommand("mkfs.btrfs", "-f", "-L", "ROOT", p.config.RootPartition)
229- switch {
230- case result.ExitCode != 0:
213+ if result.ExitCode != 0 {
231214 return fmt.Errorf("mkfs.btrfs failed: %w", result.Error)
232215 }
233216
@@ -248,31 +231,27 @@ func (p *PartitioningPhase) createSubvolumes(progressChan chan<- ProgressUpdate)
248231
249232 // Mount temporarily
250233 result := p.logger.ExecCommand("mount", device, "/mnt")
251- switch {
252- case result.ExitCode != 0:
234+ if result.ExitCode != 0 {
253235 return fmt.Errorf("temporary mount failed: %w", result.Error)
254236 }
255237
256238 // Create @ subvolume
257239 result = p.logger.ExecCommand("btrfs", "subvolume", "create", "/mnt/@")
258- switch {
259- case result.ExitCode != 0:
240+ if result.ExitCode != 0 {
260241 p.sysExec.RunSimple("umount", "/mnt") // Cleanup
261242 return fmt.Errorf("@ subvolume creation failed: %w", result.Error)
262243 }
263244
264245 // Create @home subvolume
265246 result = p.logger.ExecCommand("btrfs", "subvolume", "create", "/mnt/@home")
266- switch {
267- case result.ExitCode != 0:
247+ if result.ExitCode != 0 {
268248 p.sysExec.RunSimple("umount", "/mnt") // Cleanup
269249 return fmt.Errorf("@home subvolume creation failed: %w", result.Error)
270250 }
271251
272252 // Unmount
273253 result = p.logger.ExecCommand("umount", "/mnt")
274- switch {
275- case result.ExitCode != 0:
254+ if result.ExitCode != 0 {
276255 return fmt.Errorf("unmount after subvolume creation failed: %w", result.Error)
277256 }
278257
@@ -293,8 +272,7 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
293272
294273 // Mount @ subvolume as root
295274 result := p.logger.ExecCommand("mount", "-o", "noatime,compress=zstd,subvol=@", device, "/mnt")
296- switch {
297- case result.ExitCode != 0:
275+ if result.ExitCode != 0 {
298276 return fmt.Errorf("mount @ failed: %w", result.Error)
299277 }
300278
@@ -302,15 +280,13 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
302280
303281 // Create home directory
304282 result = p.logger.ExecCommand("mkdir", "-p", "/mnt/home")
305- switch {
306- case result.ExitCode != 0:
283+ if result.ExitCode != 0 {
307284 return fmt.Errorf("mkdir /mnt/home failed: %w", result.Error)
308285 }
309286
310287 // Mount @home subvolume
311288 result = p.logger.ExecCommand("mount", "-o", "noatime,compress=zstd,subvol=@home", device, "/mnt/home")
312- switch {
313- case result.ExitCode != 0:
289+ if result.ExitCode != 0 {
314290 return fmt.Errorf("mount @home failed: %w", result.Error)
315291 }
316292
@@ -318,14 +294,12 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
318294
319295 // Create and mount EFI
320296 result = p.logger.ExecCommand("mkdir", "-p", "/mnt/boot")
321- switch {
322- case result.ExitCode != 0:
297+ if result.ExitCode != 0 {
323298 return fmt.Errorf("mkdir /mnt/boot failed: %w", result.Error)
324299 }
325300
326301 result = p.logger.ExecCommand("mount", p.config.EFIPartition, "/mnt/boot")
327- switch {
328- case result.ExitCode != 0:
302+ if result.ExitCode != 0 {
329303 return fmt.Errorf("mount EFI failed: %w", result.Error)
330304 }
331305
@@ -337,8 +311,7 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
337311 func (p *PartitioningPhase) PostCheck() error {
338312 // Verify /mnt is mounted
339313 result := p.sysExec.RunSimple("mountpoint", "-q", "/mnt")
340- switch {
341- case result.ExitCode != 0:
314+ if result.ExitCode != 0 {
342315 return fmt.Errorf("/mnt is not mounted")
343316 }
344317
@@ -355,8 +328,7 @@ func (p *PartitioningPhase) Rollback() error {
355328 // Close LUKS if encrypted
356329 switch p.config.EncryptionType {
357330 case config.EncryptionLUKS, config.EncryptionLUKSLVM:
358- switch {
359- case p.config.CryptDevice != "":
331+ if p.config.CryptDevice != "" {
360332 p.sysExec.RunSimple("cryptsetup", "close", "cryptroot")
361333 }
362334 }
@@ -25,8 +25,7 @@ func NewPartitioningPhase(cfg *config.Config, log *logger.Logger, sysExec interf
25 25
26 // PreCheck validates partitioning prerequisites26 // PreCheck validates partitioning prerequisites
27 func (p *PartitioningPhase) PreCheck() error {27 func (p *PartitioningPhase) PreCheck() error {
28- switch {28+ if p.config.TargetDisk == "" {
29- case p.config.TargetDisk == "":
30 return fmt.Errorf("target disk not selected")29 return fmt.Errorf("target disk not selected")
31 }30 }
32 31
@@ -38,8 +37,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
38 p.SendProgress(progressChan, "Starting partitioning...", 1, 5)37 p.SendProgress(progressChan, "Starting partitioning...", 1, 5)
39 38
40 // Step 1: Wipe and partition39 // Step 1: Wipe and partition
41- switch err := p.createPartitions(progressChan); {40+ if err := p.createPartitions(progressChan); err != nil {
42- case err != nil:
43 p.SendError(progressChan, err)41 p.SendError(progressChan, err)
44 return PhaseResult{Success: false, Error: err}42 return PhaseResult{Success: false, Error: err}
45 }43 }
@@ -47,8 +45,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
47 p.SendProgress(progressChan, "Formatting partitions...", 2, 5)45 p.SendProgress(progressChan, "Formatting partitions...", 2, 5)
48 46
49 // Step 2: Format partitions47 // Step 2: Format partitions
50- switch err := p.formatPartitions(progressChan); {48+ if err := p.formatPartitions(progressChan); err != nil {
51- case err != nil:
52 p.SendError(progressChan, err)49 p.SendError(progressChan, err)
53 return PhaseResult{Success: false, Error: err}50 return PhaseResult{Success: false, Error: err}
54 }51 }
@@ -56,8 +53,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
56 p.SendProgress(progressChan, "Creating btrfs subvolumes...", 3, 5)53 p.SendProgress(progressChan, "Creating btrfs subvolumes...", 3, 5)
57 54
58 // Step 3: Create subvolumes55 // Step 3: Create subvolumes
59- switch err := p.createSubvolumes(progressChan); {56+ if err := p.createSubvolumes(progressChan); err != nil {
60- case err != nil:
61 p.SendError(progressChan, err)57 p.SendError(progressChan, err)
62 return PhaseResult{Success: false, Error: err}58 return PhaseResult{Success: false, Error: err}
63 }59 }
@@ -65,8 +61,7 @@ func (p *PartitioningPhase) Execute(progressChan chan<- ProgressUpdate) PhaseRes
65 p.SendProgress(progressChan, "Mounting filesystems...", 4, 5)61 p.SendProgress(progressChan, "Mounting filesystems...", 4, 5)
66 62
67 // Step 4: Mount63 // Step 4: Mount
68- switch err := p.mountFilesystems(progressChan); {64+ if err := p.mountFilesystems(progressChan); err != nil {
69- case err != nil:
70 p.SendError(progressChan, err)65 p.SendError(progressChan, err)
71 return PhaseResult{Success: false, Error: err}66 return PhaseResult{Success: false, Error: err}
72 }67 }
@@ -84,15 +79,13 @@ func (p *PartitioningPhase) createPartitions(progressChan chan<- ProgressUpdate)
84 79
85 // Wipe filesystem signatures80 // Wipe filesystem signatures
86 result := p.logger.ExecCommand("wipefs", "-af", disk)81 result := p.logger.ExecCommand("wipefs", "-af", disk)
87- switch {82+ if result.ExitCode != 0 {
88- case result.ExitCode != 0:
89 return fmt.Errorf("wipefs failed: %w", result.Error)83 return fmt.Errorf("wipefs failed: %w", result.Error)
90 }84 }
91 85
92 // Zap GPT and MBR86 // Zap GPT and MBR
93 result = p.logger.ExecCommand("sgdisk", "--zap-all", disk)87 result = p.logger.ExecCommand("sgdisk", "--zap-all", disk)
94- switch {88+ if result.ExitCode != 0 {
95- case result.ExitCode != 0:
96 return fmt.Errorf("sgdisk zap failed: %w", result.Error)89 return fmt.Errorf("sgdisk zap failed: %w", result.Error)
97 }90 }
98 91
@@ -105,15 +98,13 @@ func (p *PartitioningPhase) createPartitions(progressChan chan<- ProgressUpdate)
105 "--new=2:0:0", "--typecode=2:8300", "--change-name=2:ROOT",98 "--new=2:0:0", "--typecode=2:8300", "--change-name=2:ROOT",
106 disk)99 disk)
107 100
108- switch {101+ if result.ExitCode != 0 {
109- case result.ExitCode != 0:
110 return fmt.Errorf("sgdisk partition creation failed: %w", result.Error)102 return fmt.Errorf("sgdisk partition creation failed: %w", result.Error)
111 }103 }
112 104
113 // Inform kernel of partition table changes105 // Inform kernel of partition table changes
114 result = p.logger.ExecCommand("partprobe", disk)106 result = p.logger.ExecCommand("partprobe", disk)
115- switch {107+ if result.ExitCode != 0 {
116- case result.ExitCode != 0:
117 return fmt.Errorf("partprobe failed: %w", result.Error)108 return fmt.Errorf("partprobe failed: %w", result.Error)
118 }109 }
119 110
@@ -143,14 +134,12 @@ func (p *PartitioningPhase) formatPartitions(progressChan chan<- ProgressUpdate)
143 p.SendOutput(progressChan, "Formatting EFI partition...")134 p.SendOutput(progressChan, "Formatting EFI partition...")
144 135
145 result := p.logger.ExecCommand("wipefs", "-af", p.config.EFIPartition)136 result := p.logger.ExecCommand("wipefs", "-af", p.config.EFIPartition)
146- switch {137+ if result.ExitCode != 0 {
147- case result.ExitCode != 0:
148 return fmt.Errorf("wipefs EFI failed: %w", result.Error)138 return fmt.Errorf("wipefs EFI failed: %w", result.Error)
149 }139 }
150 140
151 result = p.logger.ExecCommand("mkfs.fat", "-F32", "-n", "EFI", p.config.EFIPartition)141 result = p.logger.ExecCommand("mkfs.fat", "-F32", "-n", "EFI", p.config.EFIPartition)
152- switch {142+ if result.ExitCode != 0 {
153- case result.ExitCode != 0:
154 return fmt.Errorf("mkfs.fat failed: %w", result.Error)143 return fmt.Errorf("mkfs.fat failed: %w", result.Error)
155 }144 }
156 145
@@ -171,15 +160,13 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
171 160
172 // Use user password for encryption (as per preflight)161 // Use user password for encryption (as per preflight)
173 password := p.config.UserPassword162 password := p.config.UserPassword
174- switch {163+ if password == "" {
175- case password == "":
176 return fmt.Errorf("password required for encryption")164 return fmt.Errorf("password required for encryption")
177 }165 }
178 166
179 // Wipe root partition167 // Wipe root partition
180 result := p.logger.ExecCommand("wipefs", "-af", p.config.RootPartition)168 result := p.logger.ExecCommand("wipefs", "-af", p.config.RootPartition)
181- switch {169+ if result.ExitCode != 0 {
182- case result.ExitCode != 0:
183 return fmt.Errorf("wipefs root failed: %w", result.Error)170 return fmt.Errorf("wipefs root failed: %w", result.Error)
184 }171 }
185 172
@@ -192,8 +179,7 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
192 fmt.Sprintf("printf '%%s' '%s' | cryptsetup luksFormat --type luks2 --batch-mode --pbkdf argon2id --iter-time 2000 --label ARCHUP_LUKS --key-file - %s",179 fmt.Sprintf("printf '%%s' '%s' | cryptsetup luksFormat --type luks2 --batch-mode --pbkdf argon2id --iter-time 2000 --label ARCHUP_LUKS --key-file - %s",
193 password, p.config.RootPartition))180 password, p.config.RootPartition))
194 181
195- switch {182+ if result.ExitCode != 0 {
196- case result.ExitCode != 0:
197 return fmt.Errorf("luksFormat failed: %w", result.Error)183 return fmt.Errorf("luksFormat failed: %w", result.Error)
198 }184 }
199 185
@@ -202,8 +188,7 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
202 fmt.Sprintf("printf '%%s' '%s' | cryptsetup open --key-file=- %s cryptroot",188 fmt.Sprintf("printf '%%s' '%s' | cryptsetup open --key-file=- %s cryptroot",
203 password, p.config.RootPartition))189 password, p.config.RootPartition))
204 190
205- switch {191+ if result.ExitCode != 0 {
206- case result.ExitCode != 0:
207 return fmt.Errorf("cryptsetup open failed: %w", result.Error)192 return fmt.Errorf("cryptsetup open failed: %w", result.Error)
208 }193 }
209 194
@@ -212,8 +197,7 @@ func (p *PartitioningPhase) formatEncryptedRoot(progressChan chan<- ProgressUpda
212 197
213 // Format encrypted device with btrfs198 // Format encrypted device with btrfs
214 result = p.logger.ExecCommand("mkfs.btrfs", "-f", "-L", "ROOT", p.config.CryptDevice)199 result = p.logger.ExecCommand("mkfs.btrfs", "-f", "-L", "ROOT", p.config.CryptDevice)
215- switch {200+ if result.ExitCode != 0 {
216- case result.ExitCode != 0:
217 return fmt.Errorf("mkfs.btrfs on encrypted device failed: %w", result.Error)201 return fmt.Errorf("mkfs.btrfs on encrypted device failed: %w", result.Error)
218 }202 }
219 203
@@ -226,8 +210,7 @@ func (p *PartitioningPhase) formatPlainRoot(progressChan chan<- ProgressUpdate)
226 p.SendOutput(progressChan, "Formatting root partition...")210 p.SendOutput(progressChan, "Formatting root partition...")
227 211
228 result := p.logger.ExecCommand("mkfs.btrfs", "-f", "-L", "ROOT", p.config.RootPartition)212 result := p.logger.ExecCommand("mkfs.btrfs", "-f", "-L", "ROOT", p.config.RootPartition)
229- switch {213+ if result.ExitCode != 0 {
230- case result.ExitCode != 0:
231 return fmt.Errorf("mkfs.btrfs failed: %w", result.Error)214 return fmt.Errorf("mkfs.btrfs failed: %w", result.Error)
232 }215 }
233 216
@@ -248,31 +231,27 @@ func (p *PartitioningPhase) createSubvolumes(progressChan chan<- ProgressUpdate)
248 231
249 // Mount temporarily232 // Mount temporarily
250 result := p.logger.ExecCommand("mount", device, "/mnt")233 result := p.logger.ExecCommand("mount", device, "/mnt")
251- switch {234+ if result.ExitCode != 0 {
252- case result.ExitCode != 0:
253 return fmt.Errorf("temporary mount failed: %w", result.Error)235 return fmt.Errorf("temporary mount failed: %w", result.Error)
254 }236 }
255 237
256 // Create @ subvolume238 // Create @ subvolume
257 result = p.logger.ExecCommand("btrfs", "subvolume", "create", "/mnt/@")239 result = p.logger.ExecCommand("btrfs", "subvolume", "create", "/mnt/@")
258- switch {240+ if result.ExitCode != 0 {
259- case result.ExitCode != 0:
260 p.sysExec.RunSimple("umount", "/mnt") // Cleanup241 p.sysExec.RunSimple("umount", "/mnt") // Cleanup
261 return fmt.Errorf("@ subvolume creation failed: %w", result.Error)242 return fmt.Errorf("@ subvolume creation failed: %w", result.Error)
262 }243 }
263 244
264 // Create @home subvolume245 // Create @home subvolume
265 result = p.logger.ExecCommand("btrfs", "subvolume", "create", "/mnt/@home")246 result = p.logger.ExecCommand("btrfs", "subvolume", "create", "/mnt/@home")
266- switch {247+ if result.ExitCode != 0 {
267- case result.ExitCode != 0:
268 p.sysExec.RunSimple("umount", "/mnt") // Cleanup248 p.sysExec.RunSimple("umount", "/mnt") // Cleanup
269 return fmt.Errorf("@home subvolume creation failed: %w", result.Error)249 return fmt.Errorf("@home subvolume creation failed: %w", result.Error)
270 }250 }
271 251
272 // Unmount252 // Unmount
273 result = p.logger.ExecCommand("umount", "/mnt")253 result = p.logger.ExecCommand("umount", "/mnt")
274- switch {254+ if result.ExitCode != 0 {
275- case result.ExitCode != 0:
276 return fmt.Errorf("unmount after subvolume creation failed: %w", result.Error)255 return fmt.Errorf("unmount after subvolume creation failed: %w", result.Error)
277 }256 }
278 257
@@ -293,8 +272,7 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
293 272
294 // Mount @ subvolume as root273 // Mount @ subvolume as root
295 result := p.logger.ExecCommand("mount", "-o", "noatime,compress=zstd,subvol=@", device, "/mnt")274 result := p.logger.ExecCommand("mount", "-o", "noatime,compress=zstd,subvol=@", device, "/mnt")
296- switch {275+ if result.ExitCode != 0 {
297- case result.ExitCode != 0:
298 return fmt.Errorf("mount @ failed: %w", result.Error)276 return fmt.Errorf("mount @ failed: %w", result.Error)
299 }277 }
300 278
@@ -302,15 +280,13 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
302 280
303 // Create home directory281 // Create home directory
304 result = p.logger.ExecCommand("mkdir", "-p", "/mnt/home")282 result = p.logger.ExecCommand("mkdir", "-p", "/mnt/home")
305- switch {283+ if result.ExitCode != 0 {
306- case result.ExitCode != 0:
307 return fmt.Errorf("mkdir /mnt/home failed: %w", result.Error)284 return fmt.Errorf("mkdir /mnt/home failed: %w", result.Error)
308 }285 }
309 286
310 // Mount @home subvolume287 // Mount @home subvolume
311 result = p.logger.ExecCommand("mount", "-o", "noatime,compress=zstd,subvol=@home", device, "/mnt/home")288 result = p.logger.ExecCommand("mount", "-o", "noatime,compress=zstd,subvol=@home", device, "/mnt/home")
312- switch {289+ if result.ExitCode != 0 {
313- case result.ExitCode != 0:
314 return fmt.Errorf("mount @home failed: %w", result.Error)290 return fmt.Errorf("mount @home failed: %w", result.Error)
315 }291 }
316 292
@@ -318,14 +294,12 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
318 294
319 // Create and mount EFI295 // Create and mount EFI
320 result = p.logger.ExecCommand("mkdir", "-p", "/mnt/boot")296 result = p.logger.ExecCommand("mkdir", "-p", "/mnt/boot")
321- switch {297+ if result.ExitCode != 0 {
322- case result.ExitCode != 0:
323 return fmt.Errorf("mkdir /mnt/boot failed: %w", result.Error)298 return fmt.Errorf("mkdir /mnt/boot failed: %w", result.Error)
324 }299 }
325 300
326 result = p.logger.ExecCommand("mount", p.config.EFIPartition, "/mnt/boot")301 result = p.logger.ExecCommand("mount", p.config.EFIPartition, "/mnt/boot")
327- switch {302+ if result.ExitCode != 0 {
328- case result.ExitCode != 0:
329 return fmt.Errorf("mount EFI failed: %w", result.Error)303 return fmt.Errorf("mount EFI failed: %w", result.Error)
330 }304 }
331 305
@@ -337,8 +311,7 @@ func (p *PartitioningPhase) mountFilesystems(progressChan chan<- ProgressUpdate)
337 func (p *PartitioningPhase) PostCheck() error {311 func (p *PartitioningPhase) PostCheck() error {
338 // Verify /mnt is mounted312 // Verify /mnt is mounted
339 result := p.sysExec.RunSimple("mountpoint", "-q", "/mnt")313 result := p.sysExec.RunSimple("mountpoint", "-q", "/mnt")
340- switch {314+ if result.ExitCode != 0 {
341- case result.ExitCode != 0:
342 return fmt.Errorf("/mnt is not mounted")315 return fmt.Errorf("/mnt is not mounted")
343 }316 }
344 317
@@ -355,8 +328,7 @@ func (p *PartitioningPhase) Rollback() error {
355 // Close LUKS if encrypted328 // Close LUKS if encrypted
356 switch p.config.EncryptionType {329 switch p.config.EncryptionType {
357 case config.EncryptionLUKS, config.EncryptionLUKSLVM:330 case config.EncryptionLUKS, config.EncryptionLUKSLVM:
358- switch {331+ if p.config.CryptDevice != "" {
359- case p.config.CryptDevice != "":
360 p.sysExec.RunSimple("cryptsetup", "close", "cryptroot")332 p.sysExec.RunSimple("cryptsetup", "close", "cryptroot")
361 }333 }
362 }334 }
M internal/phases/postinstall.go +54 -108
@@ -39,14 +39,12 @@ func NewPostInstallPhase(cfg *config.Config, log *logger.Logger, fs interfaces.F
3939 func (p *PostInstallPhase) PreCheck() error {
4040 // Verify /mnt is mounted
4141 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
42- switch {
43- case result.ExitCode != 0:
42+ if result.ExitCode != 0 {
4443 return fmt.Errorf("%s is not mounted", config.PathMnt)
4544 }
4645
4746 // Verify boot directory exists
48- switch _, err := p.fs.Stat(config.PathMntBoot); {
49- case p.fs.IsNotExist(err):
47+ if _, err := p.fs.Stat(config.PathMntBoot); p.fs.IsNotExist(err) {
5048 return fmt.Errorf("boot directory not found")
5149 }
5250
@@ -61,8 +59,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
6159 // Step 1: Boot logo
6260 currentStep++
6361 p.SendProgress(progressChan, "Installing boot logo...", currentStep, totalSteps)
64- switch err := p.installBootLogo(progressChan); {
65- case err != nil:
62+ if err := p.installBootLogo(progressChan); err != nil {
6663 // Non-fatal, continue
6764 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Boot logo failed: %v", err))
6865 }
@@ -70,8 +67,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
7067 // Step 2: Plymouth
7168 currentStep++
7269 p.SendProgress(progressChan, "Configuring Plymouth splash screen...", currentStep, totalSteps)
73- switch err := p.configurePlymouth(progressChan); {
74- case err != nil:
70+ if err := p.configurePlymouth(progressChan); err != nil {
7571 // Non-fatal, continue
7672 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Plymouth failed: %v", err))
7773 }
@@ -79,8 +75,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
7975 // Step 3: Snapper
8076 currentStep++
8177 p.SendProgress(progressChan, "Configuring btrfs snapshots...", currentStep, totalSteps)
82- switch err := p.configureSnapper(progressChan); {
83- case err != nil:
78+ if err := p.configureSnapper(progressChan); err != nil {
8479 // Non-fatal, continue
8580 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Snapper failed: %v", err))
8681 }
@@ -88,8 +83,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
8883 // Step 4: Pacman configuration
8984 currentStep++
9085 p.SendProgress(progressChan, "Configuring pacman...", currentStep, totalSteps)
91- switch err := p.configurePacman(progressChan); {
92- case err != nil:
86+ if err := p.configurePacman(progressChan); err != nil {
9387 p.SendError(progressChan, err)
9488 return PhaseResult{Success: false, Error: err}
9589 }
@@ -97,8 +91,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
9791 // Step 5: Post-boot setup
9892 currentStep++
9993 p.SendProgress(progressChan, "Setting up post-boot scripts...", currentStep, totalSteps)
100- switch err := p.setupPostBoot(progressChan); {
101- case err != nil:
94+ if err := p.setupPostBoot(progressChan); err != nil {
10295 p.SendError(progressChan, err)
10396 return PhaseResult{Success: false, Error: err}
10497 }
@@ -106,8 +99,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
10699 // Step 6: Pacman hooks
107100 currentStep++
108101 p.SendProgress(progressChan, "Installing pacman hooks...", currentStep, totalSteps)
109- switch err := p.installPacmanHooks(progressChan); {
110- case err != nil:
102+ if err := p.installPacmanHooks(progressChan); err != nil {
111103 p.SendError(progressChan, err)
112104 return PhaseResult{Success: false, Error: err}
113105 }
@@ -115,8 +107,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
115107 // Step 7: Shell configuration
116108 currentStep++
117109 p.SendProgress(progressChan, "Configuring shell environment...", currentStep, totalSteps)
118- switch err := p.configureShell(progressChan); {
119- case err != nil:
110+ if err := p.configureShell(progressChan); err != nil {
120111 p.SendError(progressChan, err)
121112 return PhaseResult{Success: false, Error: err}
122113 }
@@ -124,16 +115,14 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
124115 // Step 8: Verification
125116 currentStep++
126117 p.SendProgress(progressChan, "Verifying installation...", currentStep, totalSteps)
127- switch err := p.verifyInstallation(progressChan); {
128- case err != nil:
118+ if err := p.verifyInstallation(progressChan); err != nil {
129119 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Verification warnings: %v", err))
130120 }
131121
132122 // Step 9: Unmount
133123 currentStep++
134124 p.SendProgress(progressChan, "Unmounting filesystems...", currentStep, totalSteps)
135- switch err := p.unmountAll(progressChan); {
136- case err != nil:
125+ if err := p.unmountAll(progressChan); err != nil {
137126 p.SendError(progressChan, err)
138127 return PhaseResult{Success: false, Error: err}
139128 }
@@ -150,28 +139,24 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e
150139 logoURL := fmt.Sprintf("%s/%s", p.config.RawURL, config.ArchLogoURL)
151140
152141 resp, err := p.http.Get(logoURL)
153- switch {
154- case err != nil:
142+ if err != nil {
155143 return fmt.Errorf("failed to download logo: %w", err)
156144 }
157145 defer resp.Body.Close()
158146
159- switch {
160- case resp.StatusCode != http.StatusOK:
147+ if resp.StatusCode != http.StatusOK {
161148 return fmt.Errorf("failed to download logo: HTTP %d", resp.StatusCode)
162149 }
163150
164151 // Save to boot partition
165152 logoFile, err := p.fs.Create(config.PathMntBootLogo)
166- switch {
167- case err != nil:
153+ if err != nil {
168154 return fmt.Errorf("failed to create logo file: %w", err)
169155 }
170156 defer logoFile.Close()
171157
172158 _, err = io.Copy(logoFile, resp.Body)
173- switch {
174- case err != nil:
159+ if err != nil {
175160 return fmt.Errorf("failed to save logo: %w", err)
176161 }
177162
@@ -180,8 +165,7 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e
180165 // Update Limine config
181166 limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
182167 content, err := p.fs.ReadFile(limineConf)
183- switch {
184- case err != nil:
168+ if err != nil {
185169 return fmt.Errorf("failed to read limine.conf: %w", err)
186170 }
187171
@@ -194,8 +178,7 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e
194178 wallpaperSettings := "\nwallpaper: boot():/arch-logo.png\nwallpaper_style: centered\nbackdrop: 000000"
195179 contentStr = graphicsRegex.ReplaceAllString(contentStr, "graphics: yes"+wallpaperSettings)
196180
197- switch err := p.fs.WriteFile(limineConf, []byte(contentStr), 0644); {
198- case err != nil:
181+ if err := p.fs.WriteFile(limineConf, []byte(contentStr), 0644); err != nil {
199182 return fmt.Errorf("failed to update limine.conf: %w", err)
200183 }
201184
@@ -213,8 +196,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
213196
214197 // Create theme directory
215198 themeDir := filepath.Join(config.PathMntPlymouthThemes, config.PlymouthThemeName)
216- switch err := p.fs.MkdirAll(themeDir, 0755); {
217- case err != nil:
199+ if err := p.fs.MkdirAll(themeDir, 0755); err != nil {
218200 return fmt.Errorf("failed to create theme directory: %w", err)
219201 }
220202
@@ -224,13 +206,11 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
224206
225207 fileURL := fmt.Sprintf("%s/assets/plymouth/%s", p.config.RawURL, filename)
226208 resp, err := p.http.Get(fileURL)
227- switch {
228- case err != nil:
209+ if err != nil {
229210 return fmt.Errorf("failed to download %s: %w", filename, err)
230211 }
231212
232- switch {
233- case resp.StatusCode != http.StatusOK:
213+ if resp.StatusCode != http.StatusOK {
234214 resp.Body.Close()
235215 return fmt.Errorf("failed to download %s: HTTP %d", filename, resp.StatusCode)
236216 }
@@ -238,8 +218,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
238218 // Save file
239219 destPath := filepath.Join(themeDir, filename)
240220 destFile, err := p.fs.Create(destPath)
241- switch {
242- case err != nil:
221+ if err != nil {
243222 resp.Body.Close()
244223 return fmt.Errorf("failed to create %s: %w", filename, err)
245224 }
@@ -248,14 +227,12 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
248227 destFile.Close()
249228 resp.Body.Close()
250229
251- switch {
252- case err != nil:
230+ if err != nil {
253231 return fmt.Errorf("failed to save %s: %w", filename, err)
254232 }
255233
256234 // Set permissions
257- switch err := p.fs.Chmod(destPath, 0644); {
258- case err != nil:
235+ if err := p.fs.Chmod(destPath, 0644); err != nil {
259236 return fmt.Errorf("failed to set permissions on %s: %w", filename, err)
260237 }
261238 }
@@ -264,8 +241,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
264241
265242 // Set as default theme
266243 setThemeCmd := fmt.Sprintf("plymouth-set-default-theme %s", config.PlymouthThemeName)
267- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, setThemeCmd); {
268- case err != nil:
244+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, setThemeCmd); err != nil {
269245 return fmt.Errorf("failed to set Plymouth theme: %w", err)
270246 }
271247
@@ -273,8 +249,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
273249
274250 // Regenerate initramfs
275251 p.SendOutput(progressChan, "Regenerating initramfs with Plymouth...")
276- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); {
277- case err != nil:
252+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); err != nil {
278253 return fmt.Errorf("failed to regenerate initramfs: %w", err)
279254 }
280255
@@ -287,8 +262,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate)
287262 p.SendOutput(progressChan, "Installing limine-snapper-sync...")
288263
289264 // Install limine-snapper-sync
290- switch err := p.chrExec.ChrootPacman(p.logger.LogPath(),config.PathMnt, "-S", "--needed", "limine-snapper-sync"); {
291- case err != nil:
265+ if err := p.chrExec.ChrootPacman(p.logger.LogPath(),config.PathMnt, "-S", "--needed", "limine-snapper-sync"); err != nil {
292266 return fmt.Errorf("failed to install limine-snapper-sync: %w", err)
293267 }
294268
@@ -297,8 +271,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate)
297271 // Get kernel cmdline from existing Limine config
298272 limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
299273 content, err := p.fs.ReadFile(limineConf)
300- switch {
301- case err != nil:
274+ if err != nil {
302275 return fmt.Errorf("failed to read limine.conf: %w", err)
303276 }
304277
@@ -306,8 +279,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate)
306279 cmdlineRegex := regexp.MustCompile(`(?m)^\s*cmdline:\s*(.+)$`)
307280 matches := cmdlineRegex.FindStringSubmatch(string(content))
308281 cmdline := ""
309- switch {
310- case len(matches) > 1:
282+ if len(matches) > 1 {
311283 cmdline = strings.TrimSpace(matches[1])
312284 }
313285
@@ -330,16 +302,14 @@ MAX_SNAPSHOT_ENTRIES=5
330302 SNAPSHOT_FORMAT_CHOICE=5
331303 `, cmdline)
332304
333- switch err := p.fs.WriteFile(config.PathMntEtcDefaultLimine, []byte(limineDefaultConfig), 0644); {
334- case err != nil:
305+ if err := p.fs.WriteFile(config.PathMntEtcDefaultLimine, []byte(limineDefaultConfig), 0644); err != nil {
335306 return fmt.Errorf("failed to write limine config: %w", err)
336307 }
337308
338309 p.SendOutput(progressChan, "[OK] Limine snapper config created")
339310
340311 // Enable service
341- switch err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", "limine-snapper-sync.service"); {
342- case err != nil:
312+ if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", "limine-snapper-sync.service"); err != nil {
343313 return fmt.Errorf("failed to enable limine-snapper-sync: %w", err)
344314 }
345315
@@ -352,8 +322,7 @@ func (p *PostInstallPhase) configurePacman(progressChan chan<- ProgressUpdate) e
352322 p.SendOutput(progressChan, "Configuring pacman UX...")
353323
354324 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
355- switch {
356- case err != nil:
325+ if err != nil {
357326 return fmt.Errorf("failed to read pacman.conf: %w", err)
358327 }
359328
@@ -374,8 +343,7 @@ func (p *PostInstallPhase) configurePacman(progressChan chan<- ProgressUpdate) e
374343 contentStr = colorLineRegex.ReplaceAllString(contentStr, "Color\nILoveCandy")
375344 }
376345
377- switch err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); {
378- case err != nil:
346+ if err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); err != nil {
379347 return fmt.Errorf("failed to write pacman.conf: %w", err)
380348 }
381349
@@ -388,8 +356,7 @@ func (p *PostInstallPhase) installPacmanHooks(progressChan chan<- ProgressUpdate
388356 p.SendOutput(progressChan, "Installing pacman hooks...")
389357
390358 // Create hooks directory
391- switch err := p.fs.MkdirAll(config.PathMntEtcPacmanDHooks, 0755); {
392- case err != nil:
359+ if err := p.fs.MkdirAll(config.PathMntEtcPacmanDHooks, 0755); err != nil {
393360 return fmt.Errorf("failed to create hooks directory: %w", err)
394361 }
395362
@@ -407,8 +374,7 @@ Exec = /usr/bin/cp /usr/share/limine/BOOTX64.EFI /boot/EFI/limine/
407374 `
408375
409376 hookPath := filepath.Join(config.PathMntEtcPacmanDHooks, "99-limine.hook")
410- switch err := p.fs.WriteFile(hookPath, []byte(limineHook), 0644); {
411- case err != nil:
377+ if err := p.fs.WriteFile(hookPath, []byte(limineHook), 0644); err != nil {
412378 return fmt.Errorf("failed to write limine hook: %w", err)
413379 }
414380
@@ -438,33 +404,28 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
438404 p.SendOutput(progressChan, fmt.Sprintf("Configuring shell for user: %s", username))
439405
440406 // Create directory structure
441- switch err := p.fs.MkdirAll(archupDefaultBash, 0755); {
442- case err != nil:
407+ if err := p.fs.MkdirAll(archupDefaultBash, 0755); err != nil {
443408 return fmt.Errorf("failed to create shell config directory: %w", err)
444409 }
445410
446411 // Copy shell configuration files from templates
447- switch err := p.copyShellTemplates(archupDefault, archupDefaultBash); {
448- case err != nil:
412+ if err := p.copyShellTemplates(archupDefault, archupDefaultBash); err != nil {
449413 return fmt.Errorf("failed to copy shell templates: %w", err)
450414 }
451415
452416 // Create .bashrc
453417 bashrcContent, err := p.readTemplate(config.BashrcTemplate)
454- switch {
455- case err != nil:
418+ if err != nil {
456419 return fmt.Errorf("failed to read bashrc template: %w", err)
457420 }
458421
459422 bashrcPath := filepath.Join(userHome, ".bashrc")
460- switch err := p.fs.WriteFile(bashrcPath, bashrcContent, 0644); {
461- case err != nil:
423+ if err := p.fs.WriteFile(bashrcPath, bashrcContent, 0644); err != nil {
462424 return fmt.Errorf("failed to write .bashrc: %w", err)
463425 }
464426
465427 // Set ownership to user
466- switch err := p.setShellOwnership(userHome, username); {
467- case err != nil:
428+ if err := p.setShellOwnership(userHome, username); err != nil {
468429 return fmt.Errorf("failed to set ownership: %w", err)
469430 }
470431
@@ -486,15 +447,13 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
486447 // Create current theme symlink
487448 symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",
488449 username, currentDir, bleuThemeDir, currentDir)
489- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, symlinkCmd); {
490- case err != nil:
450+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, symlinkCmd); err != nil {
491451 p.SendOutput(progressChan, "[WARN] Failed to create theme symlink")
492452 }
493453
494454 // Apply themes to CLI tools
495455 p.SendOutput(progressChan, "Applying themes to CLI tools...")
496- switch err := p.applyThemes(progressChan, username, userHome); {
497- case err != nil:
456+ if err := p.applyThemes(progressChan, username, userHome); err != nil {
498457 // Non-fatal, log and continue
499458 p.SendOutput(progressChan, "[WARN] Some themes failed to apply")
500459 }
@@ -511,8 +470,7 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
511470 }
512471
513472 for _, gitCmd := range gitCommands {
514- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, gitCmd); {
515- case err != nil:
473+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, gitCmd); err != nil {
516474 // Non-fatal
517475 p.SendOutput(progressChan, "[WARN] Failed to configure git delta")
518476 break
@@ -536,13 +494,11 @@ func (p *PostInstallPhase) copyShellTemplates(archupDefault, archupDefaultBash s
536494
537495 for template, dest := range templates {
538496 content, err := p.readTemplate(template)
539- switch {
540- case err != nil:
497+ if err != nil {
541498 return fmt.Errorf("failed to read template %s: %w", template, err)
542499 }
543500
544- switch err := p.fs.WriteFile(dest, content, 0644); {
545- case err != nil:
501+ if err := p.fs.WriteFile(dest, content, 0644); err != nil {
546502 return fmt.Errorf("failed to write %s: %w", dest, err)
547503 }
548504 }
@@ -705,8 +661,7 @@ func (p *PostInstallPhase) unmountAll(progressChan chan<- ProgressUpdate) error
705661 p.SendOutput(progressChan, "Unmounting all partitions...")
706662
707663 // Unmount /mnt recursively
708- switch err := system.Unmount(p.logger.LogPath(), config.PathMnt); {
709- case err != nil:
664+ if err := system.Unmount(p.logger.LogPath(), config.PathMnt); err != nil {
710665 p.SendOutput(progressChan, "[WARN] Some partitions may still be mounted")
711666 return fmt.Errorf("failed to unmount cleanly: %w", err)
712667 }
@@ -751,8 +706,7 @@ func (p *PostInstallPhase) CanSkip() bool {
751706 func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) error {
752707 p.SendOutput(progressChan, "Configuring first-boot service...")
753708
754- switch err := p.fs.MkdirAll(config.PathMntPostBoot, 0755); {
755- case err != nil:
709+ if err := p.fs.MkdirAll(config.PathMntPostBoot, 0755); err != nil {
756710 return fmt.Errorf("failed to create post-boot directory: %w", err)
757711 }
758712
@@ -770,8 +724,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
770724
771725 logoPath := filepath.Join(config.PathMntPostBoot, "logo.txt")
772726 logoFile, err := p.fs.Create(logoPath)
773- switch {
774- case err != nil:
727+ if err != nil {
775728 resp.Body.Close()
776729 return fmt.Errorf("failed to create logo.txt: %w", err)
777730 }
@@ -779,8 +732,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
779732 _, err = io.Copy(logoFile, resp.Body)
780733 logoFile.Close()
781734 resp.Body.Close()
782- switch {
783- case err != nil:
735+ if err != nil {
784736 return fmt.Errorf("failed to save logo.txt: %w", err)
785737 }
786738
@@ -800,8 +752,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
800752
801753 scriptPath := filepath.Join(config.PathMntPostBoot, script)
802754 scriptFile, err := p.fs.Create(scriptPath)
803- switch {
804- case err != nil:
755+ if err != nil {
805756 resp.Body.Close()
806757 return fmt.Errorf("failed to create %s: %w", script, err)
807758 }
@@ -810,13 +761,11 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
810761 scriptFile.Close()
811762 resp.Body.Close()
812763
813- switch {
814- case err != nil:
764+ if err != nil {
815765 return fmt.Errorf("failed to save %s: %w", script, err)
816766 }
817767
818- switch err := p.fs.Chmod(scriptPath, 0755); {
819- case err != nil:
768+ if err := p.fs.Chmod(scriptPath, 0755); err != nil {
820769 return fmt.Errorf("failed to set permissions on %s: %w", script, err)
821770 }
822771 }
@@ -837,8 +786,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
837786
838787 templateBytes, err := io.ReadAll(resp.Body)
839788 resp.Body.Close()
840- switch {
841- case err != nil:
789+ if err != nil {
842790 return fmt.Errorf("failed to read service template: %w", err)
843791 }
844792
@@ -847,16 +795,14 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
847795 serviceContent = strings.ReplaceAll(serviceContent, "__ARCHUP_USERNAME__", p.config.Username)
848796
849797 servicePath := filepath.Join(config.PathMntSystemdSystem, config.PostBootServiceName)
850- switch err := p.fs.WriteFile(servicePath, []byte(serviceContent), 0644); {
851- case err != nil:
798+ if err := p.fs.WriteFile(servicePath, []byte(serviceContent), 0644); err != nil {
852799 return fmt.Errorf("failed to write service file: %w", err)
853800 }
854801
855802 p.SendOutput(progressChan, "[OK] Service file created")
856803
857804 p.SendOutput(progressChan, "Enabling first-boot service...")
858- switch err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); {
859- case err != nil:
805+ if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); err != nil {
860806 return fmt.Errorf("failed to enable service: %w", err)
861807 }
862808
@@ -39,14 +39,12 @@ func NewPostInstallPhase(cfg *config.Config, log *logger.Logger, fs interfaces.F
39 func (p *PostInstallPhase) PreCheck() error {39 func (p *PostInstallPhase) PreCheck() error {
40 // Verify /mnt is mounted40 // Verify /mnt is mounted
41 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)41 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
42- switch {42+ if result.ExitCode != 0 {
43- case result.ExitCode != 0:
44 return fmt.Errorf("%s is not mounted", config.PathMnt)43 return fmt.Errorf("%s is not mounted", config.PathMnt)
45 }44 }
46 45
47 // Verify boot directory exists46 // Verify boot directory exists
48- switch _, err := p.fs.Stat(config.PathMntBoot); {47+ if _, err := p.fs.Stat(config.PathMntBoot); p.fs.IsNotExist(err) {
49- case p.fs.IsNotExist(err):
50 return fmt.Errorf("boot directory not found")48 return fmt.Errorf("boot directory not found")
51 }49 }
52 50
@@ -61,8 +59,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
61 // Step 1: Boot logo59 // Step 1: Boot logo
62 currentStep++60 currentStep++
63 p.SendProgress(progressChan, "Installing boot logo...", currentStep, totalSteps)61 p.SendProgress(progressChan, "Installing boot logo...", currentStep, totalSteps)
64- switch err := p.installBootLogo(progressChan); {62+ if err := p.installBootLogo(progressChan); err != nil {
65- case err != nil:
66 // Non-fatal, continue63 // Non-fatal, continue
67 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Boot logo failed: %v", err))64 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Boot logo failed: %v", err))
68 }65 }
@@ -70,8 +67,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
70 // Step 2: Plymouth67 // Step 2: Plymouth
71 currentStep++68 currentStep++
72 p.SendProgress(progressChan, "Configuring Plymouth splash screen...", currentStep, totalSteps)69 p.SendProgress(progressChan, "Configuring Plymouth splash screen...", currentStep, totalSteps)
73- switch err := p.configurePlymouth(progressChan); {70+ if err := p.configurePlymouth(progressChan); err != nil {
74- case err != nil:
75 // Non-fatal, continue71 // Non-fatal, continue
76 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Plymouth failed: %v", err))72 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Plymouth failed: %v", err))
77 }73 }
@@ -79,8 +75,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
79 // Step 3: Snapper75 // Step 3: Snapper
80 currentStep++76 currentStep++
81 p.SendProgress(progressChan, "Configuring btrfs snapshots...", currentStep, totalSteps)77 p.SendProgress(progressChan, "Configuring btrfs snapshots...", currentStep, totalSteps)
82- switch err := p.configureSnapper(progressChan); {78+ if err := p.configureSnapper(progressChan); err != nil {
83- case err != nil:
84 // Non-fatal, continue79 // Non-fatal, continue
85 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Snapper failed: %v", err))80 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Snapper failed: %v", err))
86 }81 }
@@ -88,8 +83,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
88 // Step 4: Pacman configuration83 // Step 4: Pacman configuration
89 currentStep++84 currentStep++
90 p.SendProgress(progressChan, "Configuring pacman...", currentStep, totalSteps)85 p.SendProgress(progressChan, "Configuring pacman...", currentStep, totalSteps)
91- switch err := p.configurePacman(progressChan); {86+ if err := p.configurePacman(progressChan); err != nil {
92- case err != nil:
93 p.SendError(progressChan, err)87 p.SendError(progressChan, err)
94 return PhaseResult{Success: false, Error: err}88 return PhaseResult{Success: false, Error: err}
95 }89 }
@@ -97,8 +91,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
97 // Step 5: Post-boot setup91 // Step 5: Post-boot setup
98 currentStep++92 currentStep++
99 p.SendProgress(progressChan, "Setting up post-boot scripts...", currentStep, totalSteps)93 p.SendProgress(progressChan, "Setting up post-boot scripts...", currentStep, totalSteps)
100- switch err := p.setupPostBoot(progressChan); {94+ if err := p.setupPostBoot(progressChan); err != nil {
101- case err != nil:
102 p.SendError(progressChan, err)95 p.SendError(progressChan, err)
103 return PhaseResult{Success: false, Error: err}96 return PhaseResult{Success: false, Error: err}
104 }97 }
@@ -106,8 +99,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
106 // Step 6: Pacman hooks99 // Step 6: Pacman hooks
107 currentStep++100 currentStep++
108 p.SendProgress(progressChan, "Installing pacman hooks...", currentStep, totalSteps)101 p.SendProgress(progressChan, "Installing pacman hooks...", currentStep, totalSteps)
109- switch err := p.installPacmanHooks(progressChan); {102+ if err := p.installPacmanHooks(progressChan); err != nil {
110- case err != nil:
111 p.SendError(progressChan, err)103 p.SendError(progressChan, err)
112 return PhaseResult{Success: false, Error: err}104 return PhaseResult{Success: false, Error: err}
113 }105 }
@@ -115,8 +107,7 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
115 // Step 7: Shell configuration107 // Step 7: Shell configuration
116 currentStep++108 currentStep++
117 p.SendProgress(progressChan, "Configuring shell environment...", currentStep, totalSteps)109 p.SendProgress(progressChan, "Configuring shell environment...", currentStep, totalSteps)
118- switch err := p.configureShell(progressChan); {110+ if err := p.configureShell(progressChan); err != nil {
119- case err != nil:
120 p.SendError(progressChan, err)111 p.SendError(progressChan, err)
121 return PhaseResult{Success: false, Error: err}112 return PhaseResult{Success: false, Error: err}
122 }113 }
@@ -124,16 +115,14 @@ func (p *PostInstallPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResu
124 // Step 8: Verification115 // Step 8: Verification
125 currentStep++116 currentStep++
126 p.SendProgress(progressChan, "Verifying installation...", currentStep, totalSteps)117 p.SendProgress(progressChan, "Verifying installation...", currentStep, totalSteps)
127- switch err := p.verifyInstallation(progressChan); {118+ if err := p.verifyInstallation(progressChan); err != nil {
128- case err != nil:
129 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Verification warnings: %v", err))119 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Verification warnings: %v", err))
130 }120 }
131 121
132 // Step 9: Unmount122 // Step 9: Unmount
133 currentStep++123 currentStep++
134 p.SendProgress(progressChan, "Unmounting filesystems...", currentStep, totalSteps)124 p.SendProgress(progressChan, "Unmounting filesystems...", currentStep, totalSteps)
135- switch err := p.unmountAll(progressChan); {125+ if err := p.unmountAll(progressChan); err != nil {
136- case err != nil:
137 p.SendError(progressChan, err)126 p.SendError(progressChan, err)
138 return PhaseResult{Success: false, Error: err}127 return PhaseResult{Success: false, Error: err}
139 }128 }
@@ -150,28 +139,24 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e
150 logoURL := fmt.Sprintf("%s/%s", p.config.RawURL, config.ArchLogoURL)139 logoURL := fmt.Sprintf("%s/%s", p.config.RawURL, config.ArchLogoURL)
151 140
152 resp, err := p.http.Get(logoURL)141 resp, err := p.http.Get(logoURL)
153- switch {142+ if err != nil {
154- case err != nil:
155 return fmt.Errorf("failed to download logo: %w", err)143 return fmt.Errorf("failed to download logo: %w", err)
156 }144 }
157 defer resp.Body.Close()145 defer resp.Body.Close()
158 146
159- switch {147+ if resp.StatusCode != http.StatusOK {
160- case resp.StatusCode != http.StatusOK:
161 return fmt.Errorf("failed to download logo: HTTP %d", resp.StatusCode)148 return fmt.Errorf("failed to download logo: HTTP %d", resp.StatusCode)
162 }149 }
163 150
164 // Save to boot partition151 // Save to boot partition
165 logoFile, err := p.fs.Create(config.PathMntBootLogo)152 logoFile, err := p.fs.Create(config.PathMntBootLogo)
166- switch {153+ if err != nil {
167- case err != nil:
168 return fmt.Errorf("failed to create logo file: %w", err)154 return fmt.Errorf("failed to create logo file: %w", err)
169 }155 }
170 defer logoFile.Close()156 defer logoFile.Close()
171 157
172 _, err = io.Copy(logoFile, resp.Body)158 _, err = io.Copy(logoFile, resp.Body)
173- switch {159+ if err != nil {
174- case err != nil:
175 return fmt.Errorf("failed to save logo: %w", err)160 return fmt.Errorf("failed to save logo: %w", err)
176 }161 }
177 162
@@ -180,8 +165,7 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e
180 // Update Limine config165 // Update Limine config
181 limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)166 limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
182 content, err := p.fs.ReadFile(limineConf)167 content, err := p.fs.ReadFile(limineConf)
183- switch {168+ if err != nil {
184- case err != nil:
185 return fmt.Errorf("failed to read limine.conf: %w", err)169 return fmt.Errorf("failed to read limine.conf: %w", err)
186 }170 }
187 171
@@ -194,8 +178,7 @@ func (p *PostInstallPhase) installBootLogo(progressChan chan<- ProgressUpdate) e
194 wallpaperSettings := "\nwallpaper: boot():/arch-logo.png\nwallpaper_style: centered\nbackdrop: 000000"178 wallpaperSettings := "\nwallpaper: boot():/arch-logo.png\nwallpaper_style: centered\nbackdrop: 000000"
195 contentStr = graphicsRegex.ReplaceAllString(contentStr, "graphics: yes"+wallpaperSettings)179 contentStr = graphicsRegex.ReplaceAllString(contentStr, "graphics: yes"+wallpaperSettings)
196 180
197- switch err := p.fs.WriteFile(limineConf, []byte(contentStr), 0644); {181+ if err := p.fs.WriteFile(limineConf, []byte(contentStr), 0644); err != nil {
198- case err != nil:
199 return fmt.Errorf("failed to update limine.conf: %w", err)182 return fmt.Errorf("failed to update limine.conf: %w", err)
200 }183 }
201 184
@@ -213,8 +196,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
213 196
214 // Create theme directory197 // Create theme directory
215 themeDir := filepath.Join(config.PathMntPlymouthThemes, config.PlymouthThemeName)198 themeDir := filepath.Join(config.PathMntPlymouthThemes, config.PlymouthThemeName)
216- switch err := p.fs.MkdirAll(themeDir, 0755); {199+ if err := p.fs.MkdirAll(themeDir, 0755); err != nil {
217- case err != nil:
218 return fmt.Errorf("failed to create theme directory: %w", err)200 return fmt.Errorf("failed to create theme directory: %w", err)
219 }201 }
220 202
@@ -224,13 +206,11 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
224 206
225 fileURL := fmt.Sprintf("%s/assets/plymouth/%s", p.config.RawURL, filename)207 fileURL := fmt.Sprintf("%s/assets/plymouth/%s", p.config.RawURL, filename)
226 resp, err := p.http.Get(fileURL)208 resp, err := p.http.Get(fileURL)
227- switch {209+ if err != nil {
228- case err != nil:
229 return fmt.Errorf("failed to download %s: %w", filename, err)210 return fmt.Errorf("failed to download %s: %w", filename, err)
230 }211 }
231 212
232- switch {213+ if resp.StatusCode != http.StatusOK {
233- case resp.StatusCode != http.StatusOK:
234 resp.Body.Close()214 resp.Body.Close()
235 return fmt.Errorf("failed to download %s: HTTP %d", filename, resp.StatusCode)215 return fmt.Errorf("failed to download %s: HTTP %d", filename, resp.StatusCode)
236 }216 }
@@ -238,8 +218,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
238 // Save file218 // Save file
239 destPath := filepath.Join(themeDir, filename)219 destPath := filepath.Join(themeDir, filename)
240 destFile, err := p.fs.Create(destPath)220 destFile, err := p.fs.Create(destPath)
241- switch {221+ if err != nil {
242- case err != nil:
243 resp.Body.Close()222 resp.Body.Close()
244 return fmt.Errorf("failed to create %s: %w", filename, err)223 return fmt.Errorf("failed to create %s: %w", filename, err)
245 }224 }
@@ -248,14 +227,12 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
248 destFile.Close()227 destFile.Close()
249 resp.Body.Close()228 resp.Body.Close()
250 229
251- switch {230+ if err != nil {
252- case err != nil:
253 return fmt.Errorf("failed to save %s: %w", filename, err)231 return fmt.Errorf("failed to save %s: %w", filename, err)
254 }232 }
255 233
256 // Set permissions234 // Set permissions
257- switch err := p.fs.Chmod(destPath, 0644); {235+ if err := p.fs.Chmod(destPath, 0644); err != nil {
258- case err != nil:
259 return fmt.Errorf("failed to set permissions on %s: %w", filename, err)236 return fmt.Errorf("failed to set permissions on %s: %w", filename, err)
260 }237 }
261 }238 }
@@ -264,8 +241,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
264 241
265 // Set as default theme242 // Set as default theme
266 setThemeCmd := fmt.Sprintf("plymouth-set-default-theme %s", config.PlymouthThemeName)243 setThemeCmd := fmt.Sprintf("plymouth-set-default-theme %s", config.PlymouthThemeName)
267- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, setThemeCmd); {244+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, setThemeCmd); err != nil {
268- case err != nil:
269 return fmt.Errorf("failed to set Plymouth theme: %w", err)245 return fmt.Errorf("failed to set Plymouth theme: %w", err)
270 }246 }
271 247
@@ -273,8 +249,7 @@ func (p *PostInstallPhase) configurePlymouth(progressChan chan<- ProgressUpdate)
273 249
274 // Regenerate initramfs250 // Regenerate initramfs
275 p.SendOutput(progressChan, "Regenerating initramfs with Plymouth...")251 p.SendOutput(progressChan, "Regenerating initramfs with Plymouth...")
276- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); {252+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "mkinitcpio -P"); err != nil {
277- case err != nil:
278 return fmt.Errorf("failed to regenerate initramfs: %w", err)253 return fmt.Errorf("failed to regenerate initramfs: %w", err)
279 }254 }
280 255
@@ -287,8 +262,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate)
287 p.SendOutput(progressChan, "Installing limine-snapper-sync...")262 p.SendOutput(progressChan, "Installing limine-snapper-sync...")
288 263
289 // Install limine-snapper-sync264 // Install limine-snapper-sync
290- switch err := p.chrExec.ChrootPacman(p.logger.LogPath(),config.PathMnt, "-S", "--needed", "limine-snapper-sync"); {265+ if err := p.chrExec.ChrootPacman(p.logger.LogPath(),config.PathMnt, "-S", "--needed", "limine-snapper-sync"); err != nil {
291- case err != nil:
292 return fmt.Errorf("failed to install limine-snapper-sync: %w", err)266 return fmt.Errorf("failed to install limine-snapper-sync: %w", err)
293 }267 }
294 268
@@ -297,8 +271,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate)
297 // Get kernel cmdline from existing Limine config271 // Get kernel cmdline from existing Limine config
298 limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)272 limineConf := filepath.Join(config.PathMntBootEFILimine, config.FileLimineConfig)
299 content, err := p.fs.ReadFile(limineConf)273 content, err := p.fs.ReadFile(limineConf)
300- switch {274+ if err != nil {
301- case err != nil:
302 return fmt.Errorf("failed to read limine.conf: %w", err)275 return fmt.Errorf("failed to read limine.conf: %w", err)
303 }276 }
304 277
@@ -306,8 +279,7 @@ func (p *PostInstallPhase) configureSnapper(progressChan chan<- ProgressUpdate)
306 cmdlineRegex := regexp.MustCompile(`(?m)^\s*cmdline:\s*(.+)$`)279 cmdlineRegex := regexp.MustCompile(`(?m)^\s*cmdline:\s*(.+)$`)
307 matches := cmdlineRegex.FindStringSubmatch(string(content))280 matches := cmdlineRegex.FindStringSubmatch(string(content))
308 cmdline := ""281 cmdline := ""
309- switch {282+ if len(matches) > 1 {
310- case len(matches) > 1:
311 cmdline = strings.TrimSpace(matches[1])283 cmdline = strings.TrimSpace(matches[1])
312 }284 }
313 285
@@ -330,16 +302,14 @@ MAX_SNAPSHOT_ENTRIES=5
330 SNAPSHOT_FORMAT_CHOICE=5302 SNAPSHOT_FORMAT_CHOICE=5
331 `, cmdline)303 `, cmdline)
332 304
333- switch err := p.fs.WriteFile(config.PathMntEtcDefaultLimine, []byte(limineDefaultConfig), 0644); {305+ if err := p.fs.WriteFile(config.PathMntEtcDefaultLimine, []byte(limineDefaultConfig), 0644); err != nil {
334- case err != nil:
335 return fmt.Errorf("failed to write limine config: %w", err)306 return fmt.Errorf("failed to write limine config: %w", err)
336 }307 }
337 308
338 p.SendOutput(progressChan, "[OK] Limine snapper config created")309 p.SendOutput(progressChan, "[OK] Limine snapper config created")
339 310
340 // Enable service311 // Enable service
341- switch err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", "limine-snapper-sync.service"); {312+ if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", "limine-snapper-sync.service"); err != nil {
342- case err != nil:
343 return fmt.Errorf("failed to enable limine-snapper-sync: %w", err)313 return fmt.Errorf("failed to enable limine-snapper-sync: %w", err)
344 }314 }
345 315
@@ -352,8 +322,7 @@ func (p *PostInstallPhase) configurePacman(progressChan chan<- ProgressUpdate) e
352 p.SendOutput(progressChan, "Configuring pacman UX...")322 p.SendOutput(progressChan, "Configuring pacman UX...")
353 323
354 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)324 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
355- switch {325+ if err != nil {
356- case err != nil:
357 return fmt.Errorf("failed to read pacman.conf: %w", err)326 return fmt.Errorf("failed to read pacman.conf: %w", err)
358 }327 }
359 328
@@ -374,8 +343,7 @@ func (p *PostInstallPhase) configurePacman(progressChan chan<- ProgressUpdate) e
374 contentStr = colorLineRegex.ReplaceAllString(contentStr, "Color\nILoveCandy")343 contentStr = colorLineRegex.ReplaceAllString(contentStr, "Color\nILoveCandy")
375 }344 }
376 345
377- switch err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); {346+ if err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); err != nil {
378- case err != nil:
379 return fmt.Errorf("failed to write pacman.conf: %w", err)347 return fmt.Errorf("failed to write pacman.conf: %w", err)
380 }348 }
381 349
@@ -388,8 +356,7 @@ func (p *PostInstallPhase) installPacmanHooks(progressChan chan<- ProgressUpdate
388 p.SendOutput(progressChan, "Installing pacman hooks...")356 p.SendOutput(progressChan, "Installing pacman hooks...")
389 357
390 // Create hooks directory358 // Create hooks directory
391- switch err := p.fs.MkdirAll(config.PathMntEtcPacmanDHooks, 0755); {359+ if err := p.fs.MkdirAll(config.PathMntEtcPacmanDHooks, 0755); err != nil {
392- case err != nil:
393 return fmt.Errorf("failed to create hooks directory: %w", err)360 return fmt.Errorf("failed to create hooks directory: %w", err)
394 }361 }
395 362
@@ -407,8 +374,7 @@ Exec = /usr/bin/cp /usr/share/limine/BOOTX64.EFI /boot/EFI/limine/
407 `374 `
408 375
409 hookPath := filepath.Join(config.PathMntEtcPacmanDHooks, "99-limine.hook")376 hookPath := filepath.Join(config.PathMntEtcPacmanDHooks, "99-limine.hook")
410- switch err := p.fs.WriteFile(hookPath, []byte(limineHook), 0644); {377+ if err := p.fs.WriteFile(hookPath, []byte(limineHook), 0644); err != nil {
411- case err != nil:
412 return fmt.Errorf("failed to write limine hook: %w", err)378 return fmt.Errorf("failed to write limine hook: %w", err)
413 }379 }
414 380
@@ -438,33 +404,28 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
438 p.SendOutput(progressChan, fmt.Sprintf("Configuring shell for user: %s", username))404 p.SendOutput(progressChan, fmt.Sprintf("Configuring shell for user: %s", username))
439 405
440 // Create directory structure406 // Create directory structure
441- switch err := p.fs.MkdirAll(archupDefaultBash, 0755); {407+ if err := p.fs.MkdirAll(archupDefaultBash, 0755); err != nil {
442- case err != nil:
443 return fmt.Errorf("failed to create shell config directory: %w", err)408 return fmt.Errorf("failed to create shell config directory: %w", err)
444 }409 }
445 410
446 // Copy shell configuration files from templates411 // Copy shell configuration files from templates
447- switch err := p.copyShellTemplates(archupDefault, archupDefaultBash); {412+ if err := p.copyShellTemplates(archupDefault, archupDefaultBash); err != nil {
448- case err != nil:
449 return fmt.Errorf("failed to copy shell templates: %w", err)413 return fmt.Errorf("failed to copy shell templates: %w", err)
450 }414 }
451 415
452 // Create .bashrc416 // Create .bashrc
453 bashrcContent, err := p.readTemplate(config.BashrcTemplate)417 bashrcContent, err := p.readTemplate(config.BashrcTemplate)
454- switch {418+ if err != nil {
455- case err != nil:
456 return fmt.Errorf("failed to read bashrc template: %w", err)419 return fmt.Errorf("failed to read bashrc template: %w", err)
457 }420 }
458 421
459 bashrcPath := filepath.Join(userHome, ".bashrc")422 bashrcPath := filepath.Join(userHome, ".bashrc")
460- switch err := p.fs.WriteFile(bashrcPath, bashrcContent, 0644); {423+ if err := p.fs.WriteFile(bashrcPath, bashrcContent, 0644); err != nil {
461- case err != nil:
462 return fmt.Errorf("failed to write .bashrc: %w", err)424 return fmt.Errorf("failed to write .bashrc: %w", err)
463 }425 }
464 426
465 // Set ownership to user427 // Set ownership to user
466- switch err := p.setShellOwnership(userHome, username); {428+ if err := p.setShellOwnership(userHome, username); err != nil {
467- case err != nil:
468 return fmt.Errorf("failed to set ownership: %w", err)429 return fmt.Errorf("failed to set ownership: %w", err)
469 }430 }
470 431
@@ -486,15 +447,13 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
486 // Create current theme symlink447 // Create current theme symlink
487 symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",448 symlinkCmd := fmt.Sprintf("su - %s -c 'mkdir -p %s && ln -snf %s %s/theme'",
488 username, currentDir, bleuThemeDir, currentDir)449 username, currentDir, bleuThemeDir, currentDir)
489- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, symlinkCmd); {450+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, symlinkCmd); err != nil {
490- case err != nil:
491 p.SendOutput(progressChan, "[WARN] Failed to create theme symlink")451 p.SendOutput(progressChan, "[WARN] Failed to create theme symlink")
492 }452 }
493 453
494 // Apply themes to CLI tools454 // Apply themes to CLI tools
495 p.SendOutput(progressChan, "Applying themes to CLI tools...")455 p.SendOutput(progressChan, "Applying themes to CLI tools...")
496- switch err := p.applyThemes(progressChan, username, userHome); {456+ if err := p.applyThemes(progressChan, username, userHome); err != nil {
497- case err != nil:
498 // Non-fatal, log and continue457 // Non-fatal, log and continue
499 p.SendOutput(progressChan, "[WARN] Some themes failed to apply")458 p.SendOutput(progressChan, "[WARN] Some themes failed to apply")
500 }459 }
@@ -511,8 +470,7 @@ func (p *PostInstallPhase) configureShell(progressChan chan<- ProgressUpdate) er
511 }470 }
512 471
513 for _, gitCmd := range gitCommands {472 for _, gitCmd := range gitCommands {
514- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, gitCmd); {473+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, gitCmd); err != nil {
515- case err != nil:
516 // Non-fatal474 // Non-fatal
517 p.SendOutput(progressChan, "[WARN] Failed to configure git delta")475 p.SendOutput(progressChan, "[WARN] Failed to configure git delta")
518 break476 break
@@ -536,13 +494,11 @@ func (p *PostInstallPhase) copyShellTemplates(archupDefault, archupDefaultBash s
536 494
537 for template, dest := range templates {495 for template, dest := range templates {
538 content, err := p.readTemplate(template)496 content, err := p.readTemplate(template)
539- switch {497+ if err != nil {
540- case err != nil:
541 return fmt.Errorf("failed to read template %s: %w", template, err)498 return fmt.Errorf("failed to read template %s: %w", template, err)
542 }499 }
543 500
544- switch err := p.fs.WriteFile(dest, content, 0644); {501+ if err := p.fs.WriteFile(dest, content, 0644); err != nil {
545- case err != nil:
546 return fmt.Errorf("failed to write %s: %w", dest, err)502 return fmt.Errorf("failed to write %s: %w", dest, err)
547 }503 }
548 }504 }
@@ -705,8 +661,7 @@ func (p *PostInstallPhase) unmountAll(progressChan chan<- ProgressUpdate) error
705 p.SendOutput(progressChan, "Unmounting all partitions...")661 p.SendOutput(progressChan, "Unmounting all partitions...")
706 662
707 // Unmount /mnt recursively663 // Unmount /mnt recursively
708- switch err := system.Unmount(p.logger.LogPath(), config.PathMnt); {664+ if err := system.Unmount(p.logger.LogPath(), config.PathMnt); err != nil {
709- case err != nil:
710 p.SendOutput(progressChan, "[WARN] Some partitions may still be mounted")665 p.SendOutput(progressChan, "[WARN] Some partitions may still be mounted")
711 return fmt.Errorf("failed to unmount cleanly: %w", err)666 return fmt.Errorf("failed to unmount cleanly: %w", err)
712 }667 }
@@ -751,8 +706,7 @@ func (p *PostInstallPhase) CanSkip() bool {
751 func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) error {706 func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) error {
752 p.SendOutput(progressChan, "Configuring first-boot service...")707 p.SendOutput(progressChan, "Configuring first-boot service...")
753 708
754- switch err := p.fs.MkdirAll(config.PathMntPostBoot, 0755); {709+ if err := p.fs.MkdirAll(config.PathMntPostBoot, 0755); err != nil {
755- case err != nil:
756 return fmt.Errorf("failed to create post-boot directory: %w", err)710 return fmt.Errorf("failed to create post-boot directory: %w", err)
757 }711 }
758 712
@@ -770,8 +724,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
770 724
771 logoPath := filepath.Join(config.PathMntPostBoot, "logo.txt")725 logoPath := filepath.Join(config.PathMntPostBoot, "logo.txt")
772 logoFile, err := p.fs.Create(logoPath)726 logoFile, err := p.fs.Create(logoPath)
773- switch {727+ if err != nil {
774- case err != nil:
775 resp.Body.Close()728 resp.Body.Close()
776 return fmt.Errorf("failed to create logo.txt: %w", err)729 return fmt.Errorf("failed to create logo.txt: %w", err)
777 }730 }
@@ -779,8 +732,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
779 _, err = io.Copy(logoFile, resp.Body)732 _, err = io.Copy(logoFile, resp.Body)
780 logoFile.Close()733 logoFile.Close()
781 resp.Body.Close()734 resp.Body.Close()
782- switch {735+ if err != nil {
783- case err != nil:
784 return fmt.Errorf("failed to save logo.txt: %w", err)736 return fmt.Errorf("failed to save logo.txt: %w", err)
785 }737 }
786 738
@@ -800,8 +752,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
800 752
801 scriptPath := filepath.Join(config.PathMntPostBoot, script)753 scriptPath := filepath.Join(config.PathMntPostBoot, script)
802 scriptFile, err := p.fs.Create(scriptPath)754 scriptFile, err := p.fs.Create(scriptPath)
803- switch {755+ if err != nil {
804- case err != nil:
805 resp.Body.Close()756 resp.Body.Close()
806 return fmt.Errorf("failed to create %s: %w", script, err)757 return fmt.Errorf("failed to create %s: %w", script, err)
807 }758 }
@@ -810,13 +761,11 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
810 scriptFile.Close()761 scriptFile.Close()
811 resp.Body.Close()762 resp.Body.Close()
812 763
813- switch {764+ if err != nil {
814- case err != nil:
815 return fmt.Errorf("failed to save %s: %w", script, err)765 return fmt.Errorf("failed to save %s: %w", script, err)
816 }766 }
817 767
818- switch err := p.fs.Chmod(scriptPath, 0755); {768+ if err := p.fs.Chmod(scriptPath, 0755); err != nil {
819- case err != nil:
820 return fmt.Errorf("failed to set permissions on %s: %w", script, err)769 return fmt.Errorf("failed to set permissions on %s: %w", script, err)
821 }770 }
822 }771 }
@@ -837,8 +786,7 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
837 786
838 templateBytes, err := io.ReadAll(resp.Body)787 templateBytes, err := io.ReadAll(resp.Body)
839 resp.Body.Close()788 resp.Body.Close()
840- switch {789+ if err != nil {
841- case err != nil:
842 return fmt.Errorf("failed to read service template: %w", err)790 return fmt.Errorf("failed to read service template: %w", err)
843 }791 }
844 792
@@ -847,16 +795,14 @@ func (p *PostInstallPhase) setupPostBoot(progressChan chan<- ProgressUpdate) err
847 serviceContent = strings.ReplaceAll(serviceContent, "__ARCHUP_USERNAME__", p.config.Username)795 serviceContent = strings.ReplaceAll(serviceContent, "__ARCHUP_USERNAME__", p.config.Username)
848 796
849 servicePath := filepath.Join(config.PathMntSystemdSystem, config.PostBootServiceName)797 servicePath := filepath.Join(config.PathMntSystemdSystem, config.PostBootServiceName)
850- switch err := p.fs.WriteFile(servicePath, []byte(serviceContent), 0644); {798+ if err := p.fs.WriteFile(servicePath, []byte(serviceContent), 0644); err != nil {
851- case err != nil:
852 return fmt.Errorf("failed to write service file: %w", err)799 return fmt.Errorf("failed to write service file: %w", err)
853 }800 }
854 801
855 p.SendOutput(progressChan, "[OK] Service file created")802 p.SendOutput(progressChan, "[OK] Service file created")
856 803
857 p.SendOutput(progressChan, "Enabling first-boot service...")804 p.SendOutput(progressChan, "Enabling first-boot service...")
858- switch err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); {805+ if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(), config.PathMnt, "enable", config.PostBootServiceName); err != nil {
859- case err != nil:
860 return fmt.Errorf("failed to enable service: %w", err)806 return fmt.Errorf("failed to enable service: %w", err)
861 }807 }
862 808
M internal/phases/preflight.go +2 -4
@@ -90,13 +90,11 @@ func (p *PreflightPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
9090
9191 // SetDefaults sets default configuration values
9292 func (p *PreflightPhase) SetDefaults() {
93- switch {
94- case p.config.Hostname == "":
93+ if p.config.Hostname == "" {
9594 p.config.Hostname = "archup"
9695 }
9796
98- switch {
99- case p.config.Timezone == "":
97+ if p.config.Timezone == "" {
10098 p.config.Timezone = "UTC"
10199 }
102100
@@ -90,13 +90,11 @@ func (p *PreflightPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult
90 90
91 // SetDefaults sets default configuration values91 // SetDefaults sets default configuration values
92 func (p *PreflightPhase) SetDefaults() {92 func (p *PreflightPhase) SetDefaults() {
93- switch {93+ if p.config.Hostname == "" {
94- case p.config.Hostname == "":
95 p.config.Hostname = "archup"94 p.config.Hostname = "archup"
96 }95 }
97 96
98- switch {97+ if p.config.Timezone == "" {
99- case p.config.Timezone == "":
100 p.config.Timezone = "UTC"98 p.config.Timezone = "UTC"
101 }99 }
102 100
M internal/phases/repos.go +34 -68
@@ -69,21 +69,18 @@ func NewReposPhase(cfg *config.Config, log *logger.Logger, fs interfaces.FileSys
6969 // PreCheck validates repos prerequisites
7070 func (p *ReposPhase) PreCheck() error {
7171 // Validate AUR helper first (config validation before system checks)
72- switch {
73- case p.config.AURHelper != "" && !IsValidAURHelper(p.config.AURHelper):
72+ if p.config.AURHelper != "" && !IsValidAURHelper(p.config.AURHelper) {
7473 return fmt.Errorf("invalid AUR helper: %s (must be one of: %v)", p.config.AURHelper, ValidAURHelpers)
7574 }
7675
7776 // Verify /mnt is mounted
7877 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
79- switch {
80- case result.ExitCode != 0:
78+ if result.ExitCode != 0 {
8179 return fmt.Errorf("%s is not mounted", config.PathMnt)
8280 }
8381
8482 // Verify pacman.conf exists
85- switch _, err := p.fs.Stat(config.PathMntEtcPacmanConf); {
86- case p.fs.IsNotExist(err):
83+ if _, err := p.fs.Stat(config.PathMntEtcPacmanConf); p.fs.IsNotExist(err) {
8784 return fmt.Errorf("pacman.conf not found")
8885 }
8986
@@ -97,8 +94,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
9794 // Step 1: Enable multilib (optional)
9895 switch {
9996 case p.config.EnableMultilib:
100- switch err := p.enableMultilib(progressChan); {
101- case err != nil:
97+ if err := p.enableMultilib(progressChan); err != nil {
10298 p.SendError(progressChan, err)
10399 return PhaseResult{Success: false, Error: err}
104100 }
@@ -108,8 +104,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
108104
109105 // Step 2: Sync package databases after enabling multilib
110106 p.SendProgress(progressChan, "Syncing package databases...", 2, 5)
111- switch err := p.syncDatabases(progressChan); {
112- case err != nil:
107+ if err := p.syncDatabases(progressChan); err != nil {
113108 p.logger.Warn("Database sync failed", "error", err)
114109 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Database sync failed: %v", err))
115110 // Don't fail the phase, just warn
@@ -118,8 +113,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
118113 p.SendProgress(progressChan, "Installing extra packages...", 3, 5)
119114
120115 // Step 3: Install extra packages (always, from official repos)
121- switch err := p.installExtraPackages(progressChan); {
122- case err != nil:
116+ if err := p.installExtraPackages(progressChan); err != nil {
123117 // Don't fail the phase, just warn
124118 p.logger.Warn("Extra packages installation failed", "error", err)
125119 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Some extra packages failed: %v", err))
@@ -130,8 +124,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
130124 // Step 4: Enable Chaotic-AUR (optional)
131125 switch {
132126 case p.config.EnableChaotic:
133- switch err := p.enableChaoticAUR(progressChan); {
134- case err != nil:
127+ if err := p.enableChaoticAUR(progressChan); err != nil {
135128 p.SendError(progressChan, err)
136129 return PhaseResult{Success: false, Error: err}
137130 }
@@ -144,8 +137,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
144137 // Step 5: Install AUR helper (optional)
145138 switch {
146139 case p.config.AURHelper != "":
147- switch err := p.installAURHelper(progressChan); {
148- case err != nil:
140+ if err := p.installAURHelper(progressChan); err != nil {
149141 p.SendError(progressChan, err)
150142 return PhaseResult{Success: false, Error: err}
151143 }
@@ -163,8 +155,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
163155 func (p *ReposPhase) syncDatabases(progressChan chan<- ProgressUpdate) error {
164156 p.SendOutput(progressChan, "Syncing package databases...")
165157
166- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); {
167- case err != nil:
158+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); err != nil {
168159 return fmt.Errorf("failed to sync databases: %w", err)
169160 }
170161
@@ -178,8 +169,7 @@ func (p *ReposPhase) enableMultilib(progressChan chan<- ProgressUpdate) error {
178169
179170 // Read pacman.conf
180171 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
181- switch {
182- case err != nil:
172+ if err != nil {
183173 return fmt.Errorf("failed to read pacman.conf: %w", err)
184174 }
185175
@@ -189,8 +179,7 @@ func (p *ReposPhase) enableMultilib(progressChan chan<- ProgressUpdate) error {
189179 hasMultilibSection := strings.Contains(contentStr, "[multilib]") && !strings.Contains(contentStr, "#[multilib]")
190180 hasMultilibInclude := strings.Contains(contentStr, pacmanMultilibIncludeEnabled)
191181
192- switch {
193- case hasMultilibSection && hasMultilibInclude:
182+ if hasMultilibSection && hasMultilibInclude {
194183 p.SendOutput(progressChan, "[OK] Multilib already enabled")
195184 return nil
196185 }
@@ -221,8 +210,7 @@ func (p *ReposPhase) enableMultilib(progressChan chan<- ProgressUpdate) error {
221210 contentStr = strings.Join(lines, "\n")
222211
223212 // Write updated config
224- switch err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); {
225- case err != nil:
213+ if err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); err != nil {
226214 return fmt.Errorf("failed to write pacman.conf: %w", err)
227215 }
228216
@@ -236,8 +224,7 @@ func (p *ReposPhase) loadChaoticConfig() error {
236224 configPath := p.getInstallPath(config.ChaoticConfigFile)
237225
238226 file, err := p.fs.Open(configPath)
239- switch {
240- case err != nil:
227+ if err != nil {
241228 return fmt.Errorf("failed to open chaotic config: %w", err)
242229 }
243230 defer file.Close()
@@ -256,14 +243,12 @@ func (p *ReposPhase) loadChaoticConfig() error {
256243
257244 // Parse KEY=VALUE
258245 parts := strings.SplitN(line, "=", 2)
259- switch {
260- case len(parts) == 2:
246+ if len(parts) == 2 {
261247 p.chaoticConfig[parts[0]] = parts[1]
262248 }
263249 }
264250
265- switch err := scanner.Err(); {
266- case err != nil:
251+ if err := scanner.Err(); err != nil {
267252 return fmt.Errorf("error reading chaotic config: %w", err)
268253 }
269254
@@ -275,8 +260,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
275260 p.SendOutput(progressChan, "Adding Chaotic-AUR repository...")
276261
277262 // Load configuration for GPG key settings
278- switch err := p.loadChaoticConfig(); {
279- case err != nil:
263+ if err := p.loadChaoticConfig(); err != nil {
280264 return fmt.Errorf("failed to load Chaotic config: %w", err)
281265 }
282266
@@ -287,8 +271,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
287271
288272 // Import GPG key
289273 recvKeyCmd := fmt.Sprintf("pacman-key --recv-key %s --keyserver %s", keyID, keyserver)
290- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, recvKeyCmd); {
291- case err != nil:
274+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, recvKeyCmd); err != nil {
292275 p.logger.Warn("Failed to receive Chaotic GPG key, skipping Chaotic-AUR", "error", err)
293276 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (GPG key fetch failed)")
294277 return nil // Don't fail, just skip
@@ -296,8 +279,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
296279
297280 // Locally sign the key
298281 lsignKeyCmd := fmt.Sprintf("pacman-key --lsign-key %s", keyID)
299- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, lsignKeyCmd); {
300- case err != nil:
282+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, lsignKeyCmd); err != nil {
301283 p.logger.Warn("Failed to sign Chaotic GPG key, skipping Chaotic-AUR", "error", err)
302284 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (GPG key signing failed)")
303285 return nil // Don't fail, just skip
@@ -308,8 +290,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
308290 // Fetch live mirrorlist from GitLab
309291 p.SendOutput(progressChan, "Fetching Chaotic-AUR mirrors...")
310292 mirrors, err := system.FetchChaoticMirrorlist()
311- switch {
312- case err != nil:
293+ if err != nil {
313294 p.logger.Warn("Failed to fetch live Chaotic mirrors from GitLab, skipping Chaotic-AUR", "error", err)
314295 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (mirror fetch failed), skipping")
315296 return nil // Don't fail, just skip
@@ -353,8 +334,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
353334 // Download and install chaotic-keyring and chaotic-mirrorlist
354335 p.SendOutput(progressChan, "Downloading Chaotic-AUR packages...")
355336
356- switch err := p.chrExec.DownloadAndInstallPackages(p.logger.LogPath(), config.PathMnt, urls...); {
357- case err != nil:
337+ if err := p.chrExec.DownloadAndInstallPackages(p.logger.LogPath(), config.PathMnt, urls...); err != nil {
358338 p.logger.Warn("Failed to download/install Chaotic packages, skipping Chaotic-AUR", "error", err)
359339 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (package download failed), skipping")
360340 return nil // IMPORTANT: Exit early, don't add to pacman.conf
@@ -364,8 +344,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
364344
365345 // Add Chaotic-AUR to pacman.conf
366346 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
367- switch {
368- case err != nil:
347+ if err != nil {
369348 return fmt.Errorf("failed to read pacman.conf: %w", err)
370349 }
371350
@@ -380,8 +359,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
380359 chaoticSection := fmt.Sprintf("\n# Chaotic-AUR repository\n[%s]\nInclude = %s\n", repoName, mirrorlistPath)
381360 contentStr += chaoticSection
382361
383- switch err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); {
384- case err != nil:
362+ if err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); err != nil {
385363 return fmt.Errorf("failed to write pacman.conf: %w", err)
386364 }
387365
@@ -389,16 +367,14 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
389367 }
390368
391369 // Update package databases
392- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); {
393- case err != nil:
370+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); err != nil {
394371 return fmt.Errorf("failed to update package databases: %w", err)
395372 }
396373
397374 // Verify Chaotic-AUR is working
398375 verifyCmd := fmt.Sprintf("pacman -Sl %s", repoName)
399376 result := p.sysExec.RunSimple("arch-chroot", config.PathMnt, "sh", "-c", verifyCmd)
400- switch {
401- case result.ExitCode != 0:
377+ if result.ExitCode != 0 {
402378 p.SendOutput(progressChan, "[WARN] Chaotic-AUR verification failed")
403379 return fmt.Errorf("Chaotic-AUR verification failed")
404380 }
@@ -447,8 +423,7 @@ func (p *ReposPhase) installExtraPackages(progressChan chan<- ProgressUpdate) er
447423
448424 // Try batch installation first
449425 installCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", strings.Join(packages, " "))
450- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); {
451- case err == nil:
426+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err == nil {
452427 p.logger.Info("Extra packages installed successfully", "count", len(packages))
453428 p.SendOutput(progressChan, fmt.Sprintf("[OK] Installed %d extra packages", len(packages)))
454429 return nil
@@ -461,8 +436,7 @@ func (p *ReposPhase) installExtraPackages(progressChan chan<- ProgressUpdate) er
461436 successCount, failedPkgs := p.installPackagesIndividually(packages, progressChan)
462437
463438 // Report results
464- switch {
465- case len(failedPkgs) > 0:
439+ if len(failedPkgs) > 0 {
466440 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Failed to install: %s", strings.Join(failedPkgs, ", ")))
467441 p.logger.Warn("Some packages failed to install", "failed_count", len(failedPkgs), "packages", failedPkgs)
468442 }
@@ -484,8 +458,7 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) {
484458 packageFile := p.getInstallPath(config.ExtraPackagesFile)
485459
486460 file, err := p.fs.Open(packageFile)
487- switch {
488- case err != nil:
461+ if err != nil {
489462 return nil, fmt.Errorf("failed to open %s: %w", packageFile, err)
490463 }
491464 defer file.Close()
@@ -507,8 +480,7 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) {
507480 packages = append(packages, line)
508481 }
509482
510- switch err := scanner.Err(); {
511- case err != nil:
483+ if err := scanner.Err(); err != nil {
512484 return nil, fmt.Errorf("error reading package file: %w", err)
513485 }
514486
@@ -557,8 +529,7 @@ func (p *ReposPhase) ensureBuildDeps(progressChan chan<- ProgressUpdate, helper
557529
558530 // Always need base-devel and git
559531 baseCmd := "pacman -S --needed --noconfirm base-devel git"
560- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, baseCmd); {
561- case err != nil:
532+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, baseCmd); err != nil {
562533 p.logger.Warn("Failed to install base-devel", "error", err)
563534 return fmt.Errorf("failed to install base-devel: %w", err)
564535 }
@@ -575,8 +546,7 @@ func (p *ReposPhase) ensureBuildDeps(progressChan chan<- ProgressUpdate, helper
575546 if langDeps != "" {
576547 p.SendOutput(progressChan, fmt.Sprintf("Installing %s dependencies...", helper))
577548 depCmd := fmt.Sprintf("pacman -S --needed --noconfirm %s", langDeps)
578- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, depCmd); {
579- case err != nil:
549+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, depCmd); err != nil {
580550 p.logger.Warn("Failed to install language dependencies", "helper", helper, "deps", langDeps, "error", err)
581551 return fmt.Errorf("failed to install %s: %w", langDeps, err)
582552 }
@@ -595,16 +565,14 @@ func (p *ReposPhase) buildFromAUR(progressChan chan<- ProgressUpdate, helper str
595565 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
596566 defer cancel()
597567
598- switch err := p.chrExec.ChrootExecWithContext(ctx, p.logger.LogPath(), config.PathMnt, buildCmd); {
599- case err != nil:
568+ if err := p.chrExec.ChrootExecWithContext(ctx, p.logger.LogPath(), config.PathMnt, buildCmd); err != nil {
600569 return fmt.Errorf("build failed or timed out: %w", err)
601570 }
602571
603572 // Install built package
604573 p.SendOutput(progressChan, fmt.Sprintf("Installing %s...", helper))
605574 installCmd := fmt.Sprintf("pacman -U --noconfirm /tmp/%s/*.pkg.tar.zst", helper)
606- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); {
607- case err != nil:
575+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err != nil {
608576 return fmt.Errorf("failed to install %s: %w", helper, err)
609577 }
610578
@@ -625,8 +593,7 @@ func (p *ReposPhase) getInstallPath(filename string) string {
625593 func (p *ReposPhase) PostCheck() error {
626594 // Verify pacman.conf was modified
627595 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
628- switch {
629- case err != nil:
596+ if err != nil {
630597 return fmt.Errorf("failed to read pacman.conf: %w", err)
631598 }
632599
@@ -645,8 +612,7 @@ func (p *ReposPhase) PostCheck() error {
645612 switch {
646613 case p.config.EnableChaotic:
647614 repoName := p.chaoticConfig["CHAOTIC_REPO_NAME"]
648- switch {
649- case repoName == "":
615+ if repoName == "" {
650616 repoName = "chaotic-aur"
651617 }
652618
@@ -69,21 +69,18 @@ func NewReposPhase(cfg *config.Config, log *logger.Logger, fs interfaces.FileSys
69 // PreCheck validates repos prerequisites69 // PreCheck validates repos prerequisites
70 func (p *ReposPhase) PreCheck() error {70 func (p *ReposPhase) PreCheck() error {
71 // Validate AUR helper first (config validation before system checks)71 // Validate AUR helper first (config validation before system checks)
72- switch {72+ if p.config.AURHelper != "" && !IsValidAURHelper(p.config.AURHelper) {
73- case p.config.AURHelper != "" && !IsValidAURHelper(p.config.AURHelper):
74 return fmt.Errorf("invalid AUR helper: %s (must be one of: %v)", p.config.AURHelper, ValidAURHelpers)73 return fmt.Errorf("invalid AUR helper: %s (must be one of: %v)", p.config.AURHelper, ValidAURHelpers)
75 }74 }
76 75
77 // Verify /mnt is mounted76 // Verify /mnt is mounted
78 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)77 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
79- switch {78+ if result.ExitCode != 0 {
80- case result.ExitCode != 0:
81 return fmt.Errorf("%s is not mounted", config.PathMnt)79 return fmt.Errorf("%s is not mounted", config.PathMnt)
82 }80 }
83 81
84 // Verify pacman.conf exists82 // Verify pacman.conf exists
85- switch _, err := p.fs.Stat(config.PathMntEtcPacmanConf); {83+ if _, err := p.fs.Stat(config.PathMntEtcPacmanConf); p.fs.IsNotExist(err) {
86- case p.fs.IsNotExist(err):
87 return fmt.Errorf("pacman.conf not found")84 return fmt.Errorf("pacman.conf not found")
88 }85 }
89 86
@@ -97,8 +94,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
97 // Step 1: Enable multilib (optional)94 // Step 1: Enable multilib (optional)
98 switch {95 switch {
99 case p.config.EnableMultilib:96 case p.config.EnableMultilib:
100- switch err := p.enableMultilib(progressChan); {97+ if err := p.enableMultilib(progressChan); err != nil {
101- case err != nil:
102 p.SendError(progressChan, err)98 p.SendError(progressChan, err)
103 return PhaseResult{Success: false, Error: err}99 return PhaseResult{Success: false, Error: err}
104 }100 }
@@ -108,8 +104,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
108 104
109 // Step 2: Sync package databases after enabling multilib105 // Step 2: Sync package databases after enabling multilib
110 p.SendProgress(progressChan, "Syncing package databases...", 2, 5)106 p.SendProgress(progressChan, "Syncing package databases...", 2, 5)
111- switch err := p.syncDatabases(progressChan); {107+ if err := p.syncDatabases(progressChan); err != nil {
112- case err != nil:
113 p.logger.Warn("Database sync failed", "error", err)108 p.logger.Warn("Database sync failed", "error", err)
114 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Database sync failed: %v", err))109 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Database sync failed: %v", err))
115 // Don't fail the phase, just warn110 // Don't fail the phase, just warn
@@ -118,8 +113,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
118 p.SendProgress(progressChan, "Installing extra packages...", 3, 5)113 p.SendProgress(progressChan, "Installing extra packages...", 3, 5)
119 114
120 // Step 3: Install extra packages (always, from official repos)115 // Step 3: Install extra packages (always, from official repos)
121- switch err := p.installExtraPackages(progressChan); {116+ if err := p.installExtraPackages(progressChan); err != nil {
122- case err != nil:
123 // Don't fail the phase, just warn117 // Don't fail the phase, just warn
124 p.logger.Warn("Extra packages installation failed", "error", err)118 p.logger.Warn("Extra packages installation failed", "error", err)
125 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Some extra packages failed: %v", err))119 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Some extra packages failed: %v", err))
@@ -130,8 +124,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
130 // Step 4: Enable Chaotic-AUR (optional)124 // Step 4: Enable Chaotic-AUR (optional)
131 switch {125 switch {
132 case p.config.EnableChaotic:126 case p.config.EnableChaotic:
133- switch err := p.enableChaoticAUR(progressChan); {127+ if err := p.enableChaoticAUR(progressChan); err != nil {
134- case err != nil:
135 p.SendError(progressChan, err)128 p.SendError(progressChan, err)
136 return PhaseResult{Success: false, Error: err}129 return PhaseResult{Success: false, Error: err}
137 }130 }
@@ -144,8 +137,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
144 // Step 5: Install AUR helper (optional)137 // Step 5: Install AUR helper (optional)
145 switch {138 switch {
146 case p.config.AURHelper != "":139 case p.config.AURHelper != "":
147- switch err := p.installAURHelper(progressChan); {140+ if err := p.installAURHelper(progressChan); err != nil {
148- case err != nil:
149 p.SendError(progressChan, err)141 p.SendError(progressChan, err)
150 return PhaseResult{Success: false, Error: err}142 return PhaseResult{Success: false, Error: err}
151 }143 }
@@ -163,8 +155,7 @@ func (p *ReposPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
163 func (p *ReposPhase) syncDatabases(progressChan chan<- ProgressUpdate) error {155 func (p *ReposPhase) syncDatabases(progressChan chan<- ProgressUpdate) error {
164 p.SendOutput(progressChan, "Syncing package databases...")156 p.SendOutput(progressChan, "Syncing package databases...")
165 157
166- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); {158+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); err != nil {
167- case err != nil:
168 return fmt.Errorf("failed to sync databases: %w", err)159 return fmt.Errorf("failed to sync databases: %w", err)
169 }160 }
170 161
@@ -178,8 +169,7 @@ func (p *ReposPhase) enableMultilib(progressChan chan<- ProgressUpdate) error {
178 169
179 // Read pacman.conf170 // Read pacman.conf
180 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)171 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
181- switch {172+ if err != nil {
182- case err != nil:
183 return fmt.Errorf("failed to read pacman.conf: %w", err)173 return fmt.Errorf("failed to read pacman.conf: %w", err)
184 }174 }
185 175
@@ -189,8 +179,7 @@ func (p *ReposPhase) enableMultilib(progressChan chan<- ProgressUpdate) error {
189 hasMultilibSection := strings.Contains(contentStr, "[multilib]") && !strings.Contains(contentStr, "#[multilib]")179 hasMultilibSection := strings.Contains(contentStr, "[multilib]") && !strings.Contains(contentStr, "#[multilib]")
190 hasMultilibInclude := strings.Contains(contentStr, pacmanMultilibIncludeEnabled)180 hasMultilibInclude := strings.Contains(contentStr, pacmanMultilibIncludeEnabled)
191 181
192- switch {182+ if hasMultilibSection && hasMultilibInclude {
193- case hasMultilibSection && hasMultilibInclude:
194 p.SendOutput(progressChan, "[OK] Multilib already enabled")183 p.SendOutput(progressChan, "[OK] Multilib already enabled")
195 return nil184 return nil
196 }185 }
@@ -221,8 +210,7 @@ func (p *ReposPhase) enableMultilib(progressChan chan<- ProgressUpdate) error {
221 contentStr = strings.Join(lines, "\n")210 contentStr = strings.Join(lines, "\n")
222 211
223 // Write updated config212 // Write updated config
224- switch err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); {213+ if err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); err != nil {
225- case err != nil:
226 return fmt.Errorf("failed to write pacman.conf: %w", err)214 return fmt.Errorf("failed to write pacman.conf: %w", err)
227 }215 }
228 216
@@ -236,8 +224,7 @@ func (p *ReposPhase) loadChaoticConfig() error {
236 configPath := p.getInstallPath(config.ChaoticConfigFile)224 configPath := p.getInstallPath(config.ChaoticConfigFile)
237 225
238 file, err := p.fs.Open(configPath)226 file, err := p.fs.Open(configPath)
239- switch {227+ if err != nil {
240- case err != nil:
241 return fmt.Errorf("failed to open chaotic config: %w", err)228 return fmt.Errorf("failed to open chaotic config: %w", err)
242 }229 }
243 defer file.Close()230 defer file.Close()
@@ -256,14 +243,12 @@ func (p *ReposPhase) loadChaoticConfig() error {
256 243
257 // Parse KEY=VALUE244 // Parse KEY=VALUE
258 parts := strings.SplitN(line, "=", 2)245 parts := strings.SplitN(line, "=", 2)
259- switch {246+ if len(parts) == 2 {
260- case len(parts) == 2:
261 p.chaoticConfig[parts[0]] = parts[1]247 p.chaoticConfig[parts[0]] = parts[1]
262 }248 }
263 }249 }
264 250
265- switch err := scanner.Err(); {251+ if err := scanner.Err(); err != nil {
266- case err != nil:
267 return fmt.Errorf("error reading chaotic config: %w", err)252 return fmt.Errorf("error reading chaotic config: %w", err)
268 }253 }
269 254
@@ -275,8 +260,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
275 p.SendOutput(progressChan, "Adding Chaotic-AUR repository...")260 p.SendOutput(progressChan, "Adding Chaotic-AUR repository...")
276 261
277 // Load configuration for GPG key settings262 // Load configuration for GPG key settings
278- switch err := p.loadChaoticConfig(); {263+ if err := p.loadChaoticConfig(); err != nil {
279- case err != nil:
280 return fmt.Errorf("failed to load Chaotic config: %w", err)264 return fmt.Errorf("failed to load Chaotic config: %w", err)
281 }265 }
282 266
@@ -287,8 +271,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
287 271
288 // Import GPG key272 // Import GPG key
289 recvKeyCmd := fmt.Sprintf("pacman-key --recv-key %s --keyserver %s", keyID, keyserver)273 recvKeyCmd := fmt.Sprintf("pacman-key --recv-key %s --keyserver %s", keyID, keyserver)
290- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, recvKeyCmd); {274+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, recvKeyCmd); err != nil {
291- case err != nil:
292 p.logger.Warn("Failed to receive Chaotic GPG key, skipping Chaotic-AUR", "error", err)275 p.logger.Warn("Failed to receive Chaotic GPG key, skipping Chaotic-AUR", "error", err)
293 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (GPG key fetch failed)")276 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (GPG key fetch failed)")
294 return nil // Don't fail, just skip277 return nil // Don't fail, just skip
@@ -296,8 +279,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
296 279
297 // Locally sign the key280 // Locally sign the key
298 lsignKeyCmd := fmt.Sprintf("pacman-key --lsign-key %s", keyID)281 lsignKeyCmd := fmt.Sprintf("pacman-key --lsign-key %s", keyID)
299- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, lsignKeyCmd); {282+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, lsignKeyCmd); err != nil {
300- case err != nil:
301 p.logger.Warn("Failed to sign Chaotic GPG key, skipping Chaotic-AUR", "error", err)283 p.logger.Warn("Failed to sign Chaotic GPG key, skipping Chaotic-AUR", "error", err)
302 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (GPG key signing failed)")284 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (GPG key signing failed)")
303 return nil // Don't fail, just skip285 return nil // Don't fail, just skip
@@ -308,8 +290,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
308 // Fetch live mirrorlist from GitLab290 // Fetch live mirrorlist from GitLab
309 p.SendOutput(progressChan, "Fetching Chaotic-AUR mirrors...")291 p.SendOutput(progressChan, "Fetching Chaotic-AUR mirrors...")
310 mirrors, err := system.FetchChaoticMirrorlist()292 mirrors, err := system.FetchChaoticMirrorlist()
311- switch {293+ if err != nil {
312- case err != nil:
313 p.logger.Warn("Failed to fetch live Chaotic mirrors from GitLab, skipping Chaotic-AUR", "error", err)294 p.logger.Warn("Failed to fetch live Chaotic mirrors from GitLab, skipping Chaotic-AUR", "error", err)
314 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (mirror fetch failed), skipping")295 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (mirror fetch failed), skipping")
315 return nil // Don't fail, just skip296 return nil // Don't fail, just skip
@@ -353,8 +334,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
353 // Download and install chaotic-keyring and chaotic-mirrorlist334 // Download and install chaotic-keyring and chaotic-mirrorlist
354 p.SendOutput(progressChan, "Downloading Chaotic-AUR packages...")335 p.SendOutput(progressChan, "Downloading Chaotic-AUR packages...")
355 336
356- switch err := p.chrExec.DownloadAndInstallPackages(p.logger.LogPath(), config.PathMnt, urls...); {337+ if err := p.chrExec.DownloadAndInstallPackages(p.logger.LogPath(), config.PathMnt, urls...); err != nil {
357- case err != nil:
358 p.logger.Warn("Failed to download/install Chaotic packages, skipping Chaotic-AUR", "error", err)338 p.logger.Warn("Failed to download/install Chaotic packages, skipping Chaotic-AUR", "error", err)
359 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (package download failed), skipping")339 p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable (package download failed), skipping")
360 return nil // IMPORTANT: Exit early, don't add to pacman.conf340 return nil // IMPORTANT: Exit early, don't add to pacman.conf
@@ -364,8 +344,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
364 344
365 // Add Chaotic-AUR to pacman.conf345 // Add Chaotic-AUR to pacman.conf
366 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)346 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
367- switch {347+ if err != nil {
368- case err != nil:
369 return fmt.Errorf("failed to read pacman.conf: %w", err)348 return fmt.Errorf("failed to read pacman.conf: %w", err)
370 }349 }
371 350
@@ -380,8 +359,7 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
380 chaoticSection := fmt.Sprintf("\n# Chaotic-AUR repository\n[%s]\nInclude = %s\n", repoName, mirrorlistPath)359 chaoticSection := fmt.Sprintf("\n# Chaotic-AUR repository\n[%s]\nInclude = %s\n", repoName, mirrorlistPath)
381 contentStr += chaoticSection360 contentStr += chaoticSection
382 361
383- switch err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); {362+ if err := p.fs.WriteFile(config.PathMntEtcPacmanConf, []byte(contentStr), 0644); err != nil {
384- case err != nil:
385 return fmt.Errorf("failed to write pacman.conf: %w", err)363 return fmt.Errorf("failed to write pacman.conf: %w", err)
386 }364 }
387 365
@@ -389,16 +367,14 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
389 }367 }
390 368
391 // Update package databases369 // Update package databases
392- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); {370+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, "pacman -Sy --noconfirm"); err != nil {
393- case err != nil:
394 return fmt.Errorf("failed to update package databases: %w", err)371 return fmt.Errorf("failed to update package databases: %w", err)
395 }372 }
396 373
397 // Verify Chaotic-AUR is working374 // Verify Chaotic-AUR is working
398 verifyCmd := fmt.Sprintf("pacman -Sl %s", repoName)375 verifyCmd := fmt.Sprintf("pacman -Sl %s", repoName)
399 result := p.sysExec.RunSimple("arch-chroot", config.PathMnt, "sh", "-c", verifyCmd)376 result := p.sysExec.RunSimple("arch-chroot", config.PathMnt, "sh", "-c", verifyCmd)
400- switch {377+ if result.ExitCode != 0 {
401- case result.ExitCode != 0:
402 p.SendOutput(progressChan, "[WARN] Chaotic-AUR verification failed")378 p.SendOutput(progressChan, "[WARN] Chaotic-AUR verification failed")
403 return fmt.Errorf("Chaotic-AUR verification failed")379 return fmt.Errorf("Chaotic-AUR verification failed")
404 }380 }
@@ -447,8 +423,7 @@ func (p *ReposPhase) installExtraPackages(progressChan chan<- ProgressUpdate) er
447 423
448 // Try batch installation first424 // Try batch installation first
449 installCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", strings.Join(packages, " "))425 installCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", strings.Join(packages, " "))
450- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); {426+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err == nil {
451- case err == nil:
452 p.logger.Info("Extra packages installed successfully", "count", len(packages))427 p.logger.Info("Extra packages installed successfully", "count", len(packages))
453 p.SendOutput(progressChan, fmt.Sprintf("[OK] Installed %d extra packages", len(packages)))428 p.SendOutput(progressChan, fmt.Sprintf("[OK] Installed %d extra packages", len(packages)))
454 return nil429 return nil
@@ -461,8 +436,7 @@ func (p *ReposPhase) installExtraPackages(progressChan chan<- ProgressUpdate) er
461 successCount, failedPkgs := p.installPackagesIndividually(packages, progressChan)436 successCount, failedPkgs := p.installPackagesIndividually(packages, progressChan)
462 437
463 // Report results438 // Report results
464- switch {439+ if len(failedPkgs) > 0 {
465- case len(failedPkgs) > 0:
466 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Failed to install: %s", strings.Join(failedPkgs, ", ")))440 p.SendOutput(progressChan, fmt.Sprintf("[WARN] Failed to install: %s", strings.Join(failedPkgs, ", ")))
467 p.logger.Warn("Some packages failed to install", "failed_count", len(failedPkgs), "packages", failedPkgs)441 p.logger.Warn("Some packages failed to install", "failed_count", len(failedPkgs), "packages", failedPkgs)
468 }442 }
@@ -484,8 +458,7 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) {
484 packageFile := p.getInstallPath(config.ExtraPackagesFile)458 packageFile := p.getInstallPath(config.ExtraPackagesFile)
485 459
486 file, err := p.fs.Open(packageFile)460 file, err := p.fs.Open(packageFile)
487- switch {461+ if err != nil {
488- case err != nil:
489 return nil, fmt.Errorf("failed to open %s: %w", packageFile, err)462 return nil, fmt.Errorf("failed to open %s: %w", packageFile, err)
490 }463 }
491 defer file.Close()464 defer file.Close()
@@ -507,8 +480,7 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) {
507 packages = append(packages, line)480 packages = append(packages, line)
508 }481 }
509 482
510- switch err := scanner.Err(); {483+ if err := scanner.Err(); err != nil {
511- case err != nil:
512 return nil, fmt.Errorf("error reading package file: %w", err)484 return nil, fmt.Errorf("error reading package file: %w", err)
513 }485 }
514 486
@@ -557,8 +529,7 @@ func (p *ReposPhase) ensureBuildDeps(progressChan chan<- ProgressUpdate, helper
557 529
558 // Always need base-devel and git530 // Always need base-devel and git
559 baseCmd := "pacman -S --needed --noconfirm base-devel git"531 baseCmd := "pacman -S --needed --noconfirm base-devel git"
560- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, baseCmd); {532+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, baseCmd); err != nil {
561- case err != nil:
562 p.logger.Warn("Failed to install base-devel", "error", err)533 p.logger.Warn("Failed to install base-devel", "error", err)
563 return fmt.Errorf("failed to install base-devel: %w", err)534 return fmt.Errorf("failed to install base-devel: %w", err)
564 }535 }
@@ -575,8 +546,7 @@ func (p *ReposPhase) ensureBuildDeps(progressChan chan<- ProgressUpdate, helper
575 if langDeps != "" {546 if langDeps != "" {
576 p.SendOutput(progressChan, fmt.Sprintf("Installing %s dependencies...", helper))547 p.SendOutput(progressChan, fmt.Sprintf("Installing %s dependencies...", helper))
577 depCmd := fmt.Sprintf("pacman -S --needed --noconfirm %s", langDeps)548 depCmd := fmt.Sprintf("pacman -S --needed --noconfirm %s", langDeps)
578- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, depCmd); {549+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, depCmd); err != nil {
579- case err != nil:
580 p.logger.Warn("Failed to install language dependencies", "helper", helper, "deps", langDeps, "error", err)550 p.logger.Warn("Failed to install language dependencies", "helper", helper, "deps", langDeps, "error", err)
581 return fmt.Errorf("failed to install %s: %w", langDeps, err)551 return fmt.Errorf("failed to install %s: %w", langDeps, err)
582 }552 }
@@ -595,16 +565,14 @@ func (p *ReposPhase) buildFromAUR(progressChan chan<- ProgressUpdate, helper str
595 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)565 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
596 defer cancel()566 defer cancel()
597 567
598- switch err := p.chrExec.ChrootExecWithContext(ctx, p.logger.LogPath(), config.PathMnt, buildCmd); {568+ if err := p.chrExec.ChrootExecWithContext(ctx, p.logger.LogPath(), config.PathMnt, buildCmd); err != nil {
599- case err != nil:
600 return fmt.Errorf("build failed or timed out: %w", err)569 return fmt.Errorf("build failed or timed out: %w", err)
601 }570 }
602 571
603 // Install built package572 // Install built package
604 p.SendOutput(progressChan, fmt.Sprintf("Installing %s...", helper))573 p.SendOutput(progressChan, fmt.Sprintf("Installing %s...", helper))
605 installCmd := fmt.Sprintf("pacman -U --noconfirm /tmp/%s/*.pkg.tar.zst", helper)574 installCmd := fmt.Sprintf("pacman -U --noconfirm /tmp/%s/*.pkg.tar.zst", helper)
606- switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); {575+ if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err != nil {
607- case err != nil:
608 return fmt.Errorf("failed to install %s: %w", helper, err)576 return fmt.Errorf("failed to install %s: %w", helper, err)
609 }577 }
610 578
@@ -625,8 +593,7 @@ func (p *ReposPhase) getInstallPath(filename string) string {
625 func (p *ReposPhase) PostCheck() error {593 func (p *ReposPhase) PostCheck() error {
626 // Verify pacman.conf was modified594 // Verify pacman.conf was modified
627 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)595 content, err := p.fs.ReadFile(config.PathMntEtcPacmanConf)
628- switch {596+ if err != nil {
629- case err != nil:
630 return fmt.Errorf("failed to read pacman.conf: %w", err)597 return fmt.Errorf("failed to read pacman.conf: %w", err)
631 }598 }
632 599
@@ -645,8 +612,7 @@ func (p *ReposPhase) PostCheck() error {
645 switch {612 switch {
646 case p.config.EnableChaotic:613 case p.config.EnableChaotic:
647 repoName := p.chaoticConfig["CHAOTIC_REPO_NAME"]614 repoName := p.chaoticConfig["CHAOTIC_REPO_NAME"]
648- switch {615+ if repoName == "" {
649- case repoName == "":
650 repoName = "chaotic-aur"616 repoName = "chaotic-aur"
651 }617 }
652 618
M internal/phases/systemconfig.go +23 -46
@@ -31,8 +31,7 @@ func NewConfigPhase(cfg *config.Config, log *logger.Logger, fs interfaces.FileSy
3131 func (p *ConfigPhase) PreCheck() error {
3232 // Verify /mnt is mounted
3333 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
34- switch {
35- case result.ExitCode != 0:
34+ if result.ExitCode != 0 {
3635 return fmt.Errorf("%s is not mounted", config.PathMnt)
3736 }
3837
@@ -56,8 +55,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
5655 p.SendProgress(progressChan, "Starting system configuration...", 1, 4)
5756
5857 // Step 1: System config (timezone, locale, hostname)
59- switch err := p.configureSystem(progressChan); {
60- case err != nil:
58+ if err := p.configureSystem(progressChan); err != nil {
6159 p.SendError(progressChan, err)
6260 return PhaseResult{Success: false, Error: err}
6361 }
@@ -65,8 +63,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
6563 p.SendProgress(progressChan, "Configuring network...", 2, 4)
6664
6765 // Step 2: Network config
68- switch err := p.configureNetwork(progressChan); {
69- case err != nil:
66+ if err := p.configureNetwork(progressChan); err != nil {
7067 p.SendError(progressChan, err)
7168 return PhaseResult{Success: false, Error: err}
7269 }
@@ -74,8 +71,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
7471 p.SendProgress(progressChan, "Creating user account...", 3, 4)
7572
7673 // Step 3: User creation
77- switch err := p.createUser(progressChan); {
78- case err != nil:
74+ if err := p.createUser(progressChan); err != nil {
7975 p.SendError(progressChan, err)
8076 return PhaseResult{Success: false, Error: err}
8177 }
@@ -83,8 +79,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
8379 p.SendProgress(progressChan, "Configuring zram swap...", 4, 4)
8480
8581 // Step 4: Configure zram
86- switch err := p.configureZram(progressChan); {
87- case err != nil:
82+ if err := p.configureZram(progressChan); err != nil {
8883 p.SendError(progressChan, err)
8984 return PhaseResult{Success: false, Error: err}
9085 }
@@ -102,14 +97,12 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error
10297 // Set timezone
10398 timezonePath := filepath.Join(config.PathUsrShareZoneinfo, p.config.Timezone)
10499 tzCmd := fmt.Sprintf("ln -sf %s %s", timezonePath, config.PathEtcLocaltime)
105- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, tzCmd); {
106- case err != nil:
100+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, tzCmd); err != nil {
107101 return fmt.Errorf("failed to set timezone: %w", err)
108102 }
109103
110104 // Set hardware clock
111- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "hwclock --systohc"); {
112- case err != nil:
105+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "hwclock --systohc"); err != nil {
113106 return fmt.Errorf("failed to set hardware clock: %w", err)
114107 }
115108
@@ -117,38 +110,32 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error
117110
118111 // Set locale
119112 localeGen := p.config.Locale + " UTF-8\n"
120- switch err := p.fs.WriteFile(config.PathMntEtcLocaleGen, []byte(localeGen), 0644); {
121- case err != nil:
113+ if err := p.fs.WriteFile(config.PathMntEtcLocaleGen, []byte(localeGen), 0644); err != nil {
122114 return fmt.Errorf("failed to write locale.gen: %w", err)
123115 }
124116
125- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "locale-gen"); {
126- case err != nil:
117+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "locale-gen"); err != nil {
127118 return fmt.Errorf("failed to generate locale: %w", err)
128119 }
129120
130121 localeConf := fmt.Sprintf("LANG=%s\n", p.config.Locale)
131- switch err := p.fs.WriteFile(config.PathMntEtcLocaleConf, []byte(localeConf), 0644); {
132- case err != nil:
122+ if err := p.fs.WriteFile(config.PathMntEtcLocaleConf, []byte(localeConf), 0644); err != nil {
133123 return fmt.Errorf("failed to write locale.conf: %w", err)
134124 }
135125
136126 p.SendOutput(progressChan, fmt.Sprintf("[OK] Locale set to: %s", p.config.Locale))
137127
138128 // Set console keymap
139- switch {
140- case p.config.Keymap != "":
129+ if p.config.Keymap != "" {
141130 vconsoleConf := fmt.Sprintf("KEYMAP=%s\n", p.config.Keymap)
142- switch err := p.fs.WriteFile(config.PathMntEtcVconsole, []byte(vconsoleConf), 0644); {
143- case err != nil:
131+ if err := p.fs.WriteFile(config.PathMntEtcVconsole, []byte(vconsoleConf), 0644); err != nil {
144132 return fmt.Errorf("failed to write vconsole.conf: %w", err)
145133 }
146134 p.SendOutput(progressChan, fmt.Sprintf("[OK] Console keymap set to: %s", p.config.Keymap))
147135 }
148136
149137 // Set hostname
150- switch err := p.fs.WriteFile(config.PathMntEtcHostname, []byte(p.config.Hostname+"\n"), 0644); {
151- case err != nil:
138+ if err := p.fs.WriteFile(config.PathMntEtcHostname, []byte(p.config.Hostname+"\n"), 0644); err != nil {
152139 return fmt.Errorf("failed to write hostname: %w", err)
153140 }
154141
@@ -158,8 +145,7 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error
158145 127.0.1.1 %s.localdomain %s
159146 `, p.config.Hostname, p.config.Hostname)
160147
161- switch err := p.fs.WriteFile(config.PathMntEtcHosts, []byte(hostsContent), 0644); {
162- case err != nil:
148+ if err := p.fs.WriteFile(config.PathMntEtcHosts, []byte(hostsContent), 0644); err != nil {
163149 return fmt.Errorf("failed to write hosts file: %w", err)
164150 }
165151
@@ -173,8 +159,7 @@ func (p *ConfigPhase) configureNetwork(progressChan chan<- ProgressUpdate) error
173159 p.SendOutput(progressChan, "Configuring network...")
174160
175161 // Enable NetworkManager service
176- switch err := p.chrExec.ChrootSystemctl(p.logger.LogPath(),config.PathMnt, "enable", config.ServiceNetworkManager); {
177- case err != nil:
162+ if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(),config.PathMnt, "enable", config.ServiceNetworkManager); err != nil {
178163 return fmt.Errorf("failed to enable NetworkManager: %w", err)
179164 }
180165
@@ -189,21 +174,18 @@ func (p *ConfigPhase) createUser(progressChan chan<- ProgressUpdate) error {
189174
190175 // Create user with home directory
191176 userAddCmd := fmt.Sprintf("useradd -m -G %s -s %s %s", config.GroupWheel, config.ShellBash, p.config.Username)
192- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, userAddCmd); {
193- case err != nil:
177+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, userAddCmd); err != nil {
194178 return fmt.Errorf("failed to create user: %w", err)
195179 }
196180
197181 // Set user password using stdin (secure - not visible in process list)
198182 userPassInput := fmt.Sprintf("%s:%s", p.config.Username, p.config.UserPassword)
199- switch err := p.chrExec.ChrootExecWithStdin(p.logger.LogPath(), config.PathMnt, "chpasswd", userPassInput); {
200- case err != nil:
183+ if err := p.chrExec.ChrootExecWithStdin(p.logger.LogPath(), config.PathMnt, "chpasswd", userPassInput); err != nil {
201184 return fmt.Errorf("failed to set user password: %w", err)
202185 }
203186
204187 // Enable sudo for wheel group (passwordless for convenience)
205- switch err := p.fs.WriteFile(config.PathMntEtcSudoersD, []byte(config.SudoersWheelContent), config.SudoersWheelPerms); {
206- case err != nil:
188+ if err := p.fs.WriteFile(config.PathMntEtcSudoersD, []byte(config.SudoersWheelContent), config.SudoersWheelPerms); err != nil {
207189 return fmt.Errorf("failed to write sudoers config: %w", err)
208190 }
209191
@@ -219,15 +201,13 @@ func (p *ConfigPhase) configureZram(progressChan chan<- ProgressUpdate) error {
219201
220202 // Create zram-generator config
221203 zramConfigPath := filepath.Join(config.PathMntEtcSystemd, config.FileZramGenerator)
222- switch err := p.fs.WriteFile(zramConfigPath, []byte(config.ZramConfigContent), 0644); {
223- case err != nil:
204+ if err := p.fs.WriteFile(zramConfigPath, []byte(config.ZramConfigContent), 0644); err != nil {
224205 return fmt.Errorf("failed to write zram-generator.conf: %w", err)
225206 }
226207
227208 // Create sysctl config for zram optimization
228209 sysctlConfigPath := filepath.Join(config.PathMntEtcSysctlD, config.FileSysctlZramParams)
229- switch err := p.fs.WriteFile(sysctlConfigPath, []byte(config.ZramSysctlContent), 0644); {
230- case err != nil:
210+ if err := p.fs.WriteFile(sysctlConfigPath, []byte(config.ZramSysctlContent), 0644); err != nil {
231211 return fmt.Errorf("failed to write sysctl zram config: %w", err)
232212 }
233213
@@ -239,21 +219,18 @@ func (p *ConfigPhase) configureZram(progressChan chan<- ProgressUpdate) error {
239219 // PostCheck validates configuration
240220 func (p *ConfigPhase) PostCheck() error {
241221 // Verify hostname was set
242- switch _, err := p.fs.Stat(config.PathMntEtcHostname); {
243- case p.fs.IsNotExist(err):
222+ if _, err := p.fs.Stat(config.PathMntEtcHostname); p.fs.IsNotExist(err) {
244223 return fmt.Errorf("hostname file was not created")
245224 }
246225
247226 // Verify locale was set
248- switch _, err := p.fs.Stat(config.PathMntEtcLocaleConf); {
249- case p.fs.IsNotExist(err):
227+ if _, err := p.fs.Stat(config.PathMntEtcLocaleConf); p.fs.IsNotExist(err) {
250228 return fmt.Errorf("locale.conf was not created")
251229 }
252230
253231 // Verify zram config exists
254232 zramConfigPath := filepath.Join(config.PathMntEtcSystemd, config.FileZramGenerator)
255- switch _, err := p.fs.Stat(zramConfigPath); {
256- case p.fs.IsNotExist(err):
233+ if _, err := p.fs.Stat(zramConfigPath); p.fs.IsNotExist(err) {
257234 return fmt.Errorf("zram-generator.conf was not created")
258235 }
259236
@@ -31,8 +31,7 @@ func NewConfigPhase(cfg *config.Config, log *logger.Logger, fs interfaces.FileSy
31 func (p *ConfigPhase) PreCheck() error {31 func (p *ConfigPhase) PreCheck() error {
32 // Verify /mnt is mounted32 // Verify /mnt is mounted
33 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)33 result := p.sysExec.RunSimple("mountpoint", "-q", config.PathMnt)
34- switch {34+ if result.ExitCode != 0 {
35- case result.ExitCode != 0:
36 return fmt.Errorf("%s is not mounted", config.PathMnt)35 return fmt.Errorf("%s is not mounted", config.PathMnt)
37 }36 }
38 37
@@ -56,8 +55,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
56 p.SendProgress(progressChan, "Starting system configuration...", 1, 4)55 p.SendProgress(progressChan, "Starting system configuration...", 1, 4)
57 56
58 // Step 1: System config (timezone, locale, hostname)57 // Step 1: System config (timezone, locale, hostname)
59- switch err := p.configureSystem(progressChan); {58+ if err := p.configureSystem(progressChan); err != nil {
60- case err != nil:
61 p.SendError(progressChan, err)59 p.SendError(progressChan, err)
62 return PhaseResult{Success: false, Error: err}60 return PhaseResult{Success: false, Error: err}
63 }61 }
@@ -65,8 +63,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
65 p.SendProgress(progressChan, "Configuring network...", 2, 4)63 p.SendProgress(progressChan, "Configuring network...", 2, 4)
66 64
67 // Step 2: Network config65 // Step 2: Network config
68- switch err := p.configureNetwork(progressChan); {66+ if err := p.configureNetwork(progressChan); err != nil {
69- case err != nil:
70 p.SendError(progressChan, err)67 p.SendError(progressChan, err)
71 return PhaseResult{Success: false, Error: err}68 return PhaseResult{Success: false, Error: err}
72 }69 }
@@ -74,8 +71,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
74 p.SendProgress(progressChan, "Creating user account...", 3, 4)71 p.SendProgress(progressChan, "Creating user account...", 3, 4)
75 72
76 // Step 3: User creation73 // Step 3: User creation
77- switch err := p.createUser(progressChan); {74+ if err := p.createUser(progressChan); err != nil {
78- case err != nil:
79 p.SendError(progressChan, err)75 p.SendError(progressChan, err)
80 return PhaseResult{Success: false, Error: err}76 return PhaseResult{Success: false, Error: err}
81 }77 }
@@ -83,8 +79,7 @@ func (p *ConfigPhase) Execute(progressChan chan<- ProgressUpdate) PhaseResult {
83 p.SendProgress(progressChan, "Configuring zram swap...", 4, 4)79 p.SendProgress(progressChan, "Configuring zram swap...", 4, 4)
84 80
85 // Step 4: Configure zram81 // Step 4: Configure zram
86- switch err := p.configureZram(progressChan); {82+ if err := p.configureZram(progressChan); err != nil {
87- case err != nil:
88 p.SendError(progressChan, err)83 p.SendError(progressChan, err)
89 return PhaseResult{Success: false, Error: err}84 return PhaseResult{Success: false, Error: err}
90 }85 }
@@ -102,14 +97,12 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error
102 // Set timezone97 // Set timezone
103 timezonePath := filepath.Join(config.PathUsrShareZoneinfo, p.config.Timezone)98 timezonePath := filepath.Join(config.PathUsrShareZoneinfo, p.config.Timezone)
104 tzCmd := fmt.Sprintf("ln -sf %s %s", timezonePath, config.PathEtcLocaltime)99 tzCmd := fmt.Sprintf("ln -sf %s %s", timezonePath, config.PathEtcLocaltime)
105- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, tzCmd); {100+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, tzCmd); err != nil {
106- case err != nil:
107 return fmt.Errorf("failed to set timezone: %w", err)101 return fmt.Errorf("failed to set timezone: %w", err)
108 }102 }
109 103
110 // Set hardware clock104 // Set hardware clock
111- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "hwclock --systohc"); {105+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "hwclock --systohc"); err != nil {
112- case err != nil:
113 return fmt.Errorf("failed to set hardware clock: %w", err)106 return fmt.Errorf("failed to set hardware clock: %w", err)
114 }107 }
115 108
@@ -117,38 +110,32 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error
117 110
118 // Set locale111 // Set locale
119 localeGen := p.config.Locale + " UTF-8\n"112 localeGen := p.config.Locale + " UTF-8\n"
120- switch err := p.fs.WriteFile(config.PathMntEtcLocaleGen, []byte(localeGen), 0644); {113+ if err := p.fs.WriteFile(config.PathMntEtcLocaleGen, []byte(localeGen), 0644); err != nil {
121- case err != nil:
122 return fmt.Errorf("failed to write locale.gen: %w", err)114 return fmt.Errorf("failed to write locale.gen: %w", err)
123 }115 }
124 116
125- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "locale-gen"); {117+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, "locale-gen"); err != nil {
126- case err != nil:
127 return fmt.Errorf("failed to generate locale: %w", err)118 return fmt.Errorf("failed to generate locale: %w", err)
128 }119 }
129 120
130 localeConf := fmt.Sprintf("LANG=%s\n", p.config.Locale)121 localeConf := fmt.Sprintf("LANG=%s\n", p.config.Locale)
131- switch err := p.fs.WriteFile(config.PathMntEtcLocaleConf, []byte(localeConf), 0644); {122+ if err := p.fs.WriteFile(config.PathMntEtcLocaleConf, []byte(localeConf), 0644); err != nil {
132- case err != nil:
133 return fmt.Errorf("failed to write locale.conf: %w", err)123 return fmt.Errorf("failed to write locale.conf: %w", err)
134 }124 }
135 125
136 p.SendOutput(progressChan, fmt.Sprintf("[OK] Locale set to: %s", p.config.Locale))126 p.SendOutput(progressChan, fmt.Sprintf("[OK] Locale set to: %s", p.config.Locale))
137 127
138 // Set console keymap128 // Set console keymap
139- switch {129+ if p.config.Keymap != "" {
140- case p.config.Keymap != "":
141 vconsoleConf := fmt.Sprintf("KEYMAP=%s\n", p.config.Keymap)130 vconsoleConf := fmt.Sprintf("KEYMAP=%s\n", p.config.Keymap)
142- switch err := p.fs.WriteFile(config.PathMntEtcVconsole, []byte(vconsoleConf), 0644); {131+ if err := p.fs.WriteFile(config.PathMntEtcVconsole, []byte(vconsoleConf), 0644); err != nil {
143- case err != nil:
144 return fmt.Errorf("failed to write vconsole.conf: %w", err)132 return fmt.Errorf("failed to write vconsole.conf: %w", err)
145 }133 }
146 p.SendOutput(progressChan, fmt.Sprintf("[OK] Console keymap set to: %s", p.config.Keymap))134 p.SendOutput(progressChan, fmt.Sprintf("[OK] Console keymap set to: %s", p.config.Keymap))
147 }135 }
148 136
149 // Set hostname137 // Set hostname
150- switch err := p.fs.WriteFile(config.PathMntEtcHostname, []byte(p.config.Hostname+"\n"), 0644); {138+ if err := p.fs.WriteFile(config.PathMntEtcHostname, []byte(p.config.Hostname+"\n"), 0644); err != nil {
151- case err != nil:
152 return fmt.Errorf("failed to write hostname: %w", err)139 return fmt.Errorf("failed to write hostname: %w", err)
153 }140 }
154 141
@@ -158,8 +145,7 @@ func (p *ConfigPhase) configureSystem(progressChan chan<- ProgressUpdate) error
158 127.0.1.1 %s.localdomain %s145 127.0.1.1 %s.localdomain %s
159 `, p.config.Hostname, p.config.Hostname)146 `, p.config.Hostname, p.config.Hostname)
160 147
161- switch err := p.fs.WriteFile(config.PathMntEtcHosts, []byte(hostsContent), 0644); {148+ if err := p.fs.WriteFile(config.PathMntEtcHosts, []byte(hostsContent), 0644); err != nil {
162- case err != nil:
163 return fmt.Errorf("failed to write hosts file: %w", err)149 return fmt.Errorf("failed to write hosts file: %w", err)
164 }150 }
165 151
@@ -173,8 +159,7 @@ func (p *ConfigPhase) configureNetwork(progressChan chan<- ProgressUpdate) error
173 p.SendOutput(progressChan, "Configuring network...")159 p.SendOutput(progressChan, "Configuring network...")
174 160
175 // Enable NetworkManager service161 // Enable NetworkManager service
176- switch err := p.chrExec.ChrootSystemctl(p.logger.LogPath(),config.PathMnt, "enable", config.ServiceNetworkManager); {162+ if err := p.chrExec.ChrootSystemctl(p.logger.LogPath(),config.PathMnt, "enable", config.ServiceNetworkManager); err != nil {
177- case err != nil:
178 return fmt.Errorf("failed to enable NetworkManager: %w", err)163 return fmt.Errorf("failed to enable NetworkManager: %w", err)
179 }164 }
180 165
@@ -189,21 +174,18 @@ func (p *ConfigPhase) createUser(progressChan chan<- ProgressUpdate) error {
189 174
190 // Create user with home directory175 // Create user with home directory
191 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)
192- switch err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, userAddCmd); {177+ if err := p.chrExec.ChrootExec(p.logger.LogPath(),config.PathMnt, userAddCmd); err != nil {
193- case err != nil:
194 return fmt.Errorf("failed to create user: %w", err)178 return fmt.Errorf("failed to create user: %w", err)
195 }179 }
196 180
197 // Set user password using stdin (secure - not visible in process list)181 // Set user password using stdin (secure - not visible in process list)
198 userPassInput := fmt.Sprintf("%s:%s", p.config.Username, p.config.UserPassword)182 userPassInput := fmt.Sprintf("%s:%s", p.config.Username, p.config.UserPassword)
199- switch err := p.chrExec.ChrootExecWithStdin(p.logger.LogPath(), config.PathMnt, "chpasswd", userPassInput); {183+ if err := p.chrExec.ChrootExecWithStdin(p.logger.LogPath(), config.PathMnt, "chpasswd", userPassInput); err != nil {
200- case err != nil:
201 return fmt.Errorf("failed to set user password: %w", err)184 return fmt.Errorf("failed to set user password: %w", err)
202 }185 }
203 186
204 // Enable sudo for wheel group (passwordless for convenience)187 // Enable sudo for wheel group (passwordless for convenience)
205- switch err := p.fs.WriteFile(config.PathMntEtcSudoersD, []byte(config.SudoersWheelContent), config.SudoersWheelPerms); {188+ if err := p.fs.WriteFile(config.PathMntEtcSudoersD, []byte(config.SudoersWheelContent), config.SudoersWheelPerms); err != nil {
206- case err != nil:
207 return fmt.Errorf("failed to write sudoers config: %w", err)189 return fmt.Errorf("failed to write sudoers config: %w", err)
208 }190 }
209 191
@@ -219,15 +201,13 @@ func (p *ConfigPhase) configureZram(progressChan chan<- ProgressUpdate) error {
219 201
220 // Create zram-generator config202 // Create zram-generator config
221 zramConfigPath := filepath.Join(config.PathMntEtcSystemd, config.FileZramGenerator)203 zramConfigPath := filepath.Join(config.PathMntEtcSystemd, config.FileZramGenerator)
222- switch err := p.fs.WriteFile(zramConfigPath, []byte(config.ZramConfigContent), 0644); {204+ if err := p.fs.WriteFile(zramConfigPath, []byte(config.ZramConfigContent), 0644); err != nil {
223- case err != nil:
224 return fmt.Errorf("failed to write zram-generator.conf: %w", err)205 return fmt.Errorf("failed to write zram-generator.conf: %w", err)
225 }206 }
226 207
227 // Create sysctl config for zram optimization208 // Create sysctl config for zram optimization
228 sysctlConfigPath := filepath.Join(config.PathMntEtcSysctlD, config.FileSysctlZramParams)209 sysctlConfigPath := filepath.Join(config.PathMntEtcSysctlD, config.FileSysctlZramParams)
229- switch err := p.fs.WriteFile(sysctlConfigPath, []byte(config.ZramSysctlContent), 0644); {210+ if err := p.fs.WriteFile(sysctlConfigPath, []byte(config.ZramSysctlContent), 0644); err != nil {
230- case err != nil:
231 return fmt.Errorf("failed to write sysctl zram config: %w", err)211 return fmt.Errorf("failed to write sysctl zram config: %w", err)
232 }212 }
233 213
@@ -239,21 +219,18 @@ func (p *ConfigPhase) configureZram(progressChan chan<- ProgressUpdate) error {
239 // PostCheck validates configuration219 // PostCheck validates configuration
240 func (p *ConfigPhase) PostCheck() error {220 func (p *ConfigPhase) PostCheck() error {
241 // Verify hostname was set221 // Verify hostname was set
242- switch _, err := p.fs.Stat(config.PathMntEtcHostname); {222+ if _, err := p.fs.Stat(config.PathMntEtcHostname); p.fs.IsNotExist(err) {
243- case p.fs.IsNotExist(err):
244 return fmt.Errorf("hostname file was not created")223 return fmt.Errorf("hostname file was not created")
245 }224 }
246 225
247 // Verify locale was set226 // Verify locale was set
248- switch _, err := p.fs.Stat(config.PathMntEtcLocaleConf); {227+ if _, err := p.fs.Stat(config.PathMntEtcLocaleConf); p.fs.IsNotExist(err) {
249- case p.fs.IsNotExist(err):
250 return fmt.Errorf("locale.conf was not created")228 return fmt.Errorf("locale.conf was not created")
251 }229 }
252 230
253 // Verify zram config exists231 // Verify zram config exists
254 zramConfigPath := filepath.Join(config.PathMntEtcSystemd, config.FileZramGenerator)232 zramConfigPath := filepath.Join(config.PathMntEtcSystemd, config.FileZramGenerator)
255- switch _, err := p.fs.Stat(zramConfigPath); {233+ if _, err := p.fs.Stat(zramConfigPath); p.fs.IsNotExist(err) {
256- case p.fs.IsNotExist(err):
257 return fmt.Errorf("zram-generator.conf was not created")234 return fmt.Errorf("zram-generator.conf was not created")
258 }235 }
259 236
M internal/system/cpu.go +7 -14
@@ -45,8 +45,7 @@ type CPUInfo struct {
4545 // DetectCPUVendor reads /proc/cpuinfo and returns the CPU vendor
4646 func DetectCPUVendor() (CPUVendor, error) {
4747 data, err := os.ReadFile("/proc/cpuinfo")
48- switch {
49- case err != nil:
48+ if err != nil {
5049 return CPUVendorUnknown, fmt.Errorf("failed to read /proc/cpuinfo: %w", err)
5150 }
5251
@@ -57,8 +56,7 @@ func DetectCPUVendor() (CPUVendor, error) {
5756 switch {
5857 case strings.HasPrefix(line, "vendor_id"):
5958 parts := strings.Split(line, ":")
60- switch {
61- case len(parts) < 2:
59+ if len(parts) < 2 {
6260 continue
6361 }
6462
@@ -93,8 +91,7 @@ func DetectMicrocode(vendor CPUVendor) string {
9391 func CheckCPPCSupport() bool {
9492 // Check /proc/cpuinfo for cppc flag
9593 data, err := os.ReadFile("/proc/cpuinfo")
96- switch {
97- case err != nil:
94+ if err != nil {
9895 return false
9996 }
10097
@@ -105,8 +102,7 @@ func CheckCPPCSupport() bool {
105102
106103 // Check if amd_pstate directory exists
107104 _, err = os.Stat("/sys/devices/system/cpu/cpu0/cpufreq/amd_pstate")
108- switch {
109- case err == nil:
105+ if err == nil {
110106 return true
111107 }
112108
@@ -137,8 +133,7 @@ func DetectAMDPStateModes() []AMDPStateMode {
137133 }
138134
139135 // If we found modes, return them
140- switch {
141- case len(modes) > 0:
136+ if len(modes) > 0 {
142137 return modes
143138 }
144139 }
@@ -335,8 +330,7 @@ func GetCPUModelName() string {
335330 // DetectCPUInfo detects all CPU information in one call (DRY)
336331 func DetectCPUInfo() (*CPUInfo, error) {
337332 vendor, err := DetectCPUVendor()
338- switch {
339- case err != nil:
333+ if err != nil {
340334 return nil, err
341335 }
342336
@@ -347,8 +341,7 @@ func DetectCPUInfo() (*CPUInfo, error) {
347341 }
348342
349343 // Detect AMD-specific features only for AMD CPUs
350- switch vendor {
351- case CPUVendorAMD:
344+ if vendor == CPUVendorAMD {
352345 zenGen, err := DetectAMDZenGeneration()
353346 if err == nil {
354347 info.AMDZenGen = zenGen
@@ -45,8 +45,7 @@ type CPUInfo struct {
45 // DetectCPUVendor reads /proc/cpuinfo and returns the CPU vendor45 // DetectCPUVendor reads /proc/cpuinfo and returns the CPU vendor
46 func DetectCPUVendor() (CPUVendor, error) {46 func DetectCPUVendor() (CPUVendor, error) {
47 data, err := os.ReadFile("/proc/cpuinfo")47 data, err := os.ReadFile("/proc/cpuinfo")
48- switch {48+ if err != nil {
49- case err != nil:
50 return CPUVendorUnknown, fmt.Errorf("failed to read /proc/cpuinfo: %w", err)49 return CPUVendorUnknown, fmt.Errorf("failed to read /proc/cpuinfo: %w", err)
51 }50 }
52 51
@@ -57,8 +56,7 @@ func DetectCPUVendor() (CPUVendor, error) {
57 switch {56 switch {
58 case strings.HasPrefix(line, "vendor_id"):57 case strings.HasPrefix(line, "vendor_id"):
59 parts := strings.Split(line, ":")58 parts := strings.Split(line, ":")
60- switch {59+ if len(parts) < 2 {
61- case len(parts) < 2:
62 continue60 continue
63 }61 }
64 62
@@ -93,8 +91,7 @@ func DetectMicrocode(vendor CPUVendor) string {
93 func CheckCPPCSupport() bool {91 func CheckCPPCSupport() bool {
94 // Check /proc/cpuinfo for cppc flag92 // Check /proc/cpuinfo for cppc flag
95 data, err := os.ReadFile("/proc/cpuinfo")93 data, err := os.ReadFile("/proc/cpuinfo")
96- switch {94+ if err != nil {
97- case err != nil:
98 return false95 return false
99 }96 }
100 97
@@ -105,8 +102,7 @@ func CheckCPPCSupport() bool {
105 102
106 // Check if amd_pstate directory exists103 // Check if amd_pstate directory exists
107 _, err = os.Stat("/sys/devices/system/cpu/cpu0/cpufreq/amd_pstate")104 _, err = os.Stat("/sys/devices/system/cpu/cpu0/cpufreq/amd_pstate")
108- switch {105+ if err == nil {
109- case err == nil:
110 return true106 return true
111 }107 }
112 108
@@ -137,8 +133,7 @@ func DetectAMDPStateModes() []AMDPStateMode {
137 }133 }
138 134
139 // If we found modes, return them135 // If we found modes, return them
140- switch {136+ if len(modes) > 0 {
141- case len(modes) > 0:
142 return modes137 return modes
143 }138 }
144 }139 }
@@ -335,8 +330,7 @@ func GetCPUModelName() string {
335 // DetectCPUInfo detects all CPU information in one call (DRY)330 // DetectCPUInfo detects all CPU information in one call (DRY)
336 func DetectCPUInfo() (*CPUInfo, error) {331 func DetectCPUInfo() (*CPUInfo, error) {
337 vendor, err := DetectCPUVendor()332 vendor, err := DetectCPUVendor()
338- switch {333+ if err != nil {
339- case err != nil:
340 return nil, err334 return nil, err
341 }335 }
342 336
@@ -347,8 +341,7 @@ func DetectCPUInfo() (*CPUInfo, error) {
347 }341 }
348 342
349 // Detect AMD-specific features only for AMD CPUs343 // Detect AMD-specific features only for AMD CPUs
350- switch vendor {344+ if vendor == CPUVendorAMD {
351- case CPUVendorAMD:
352 zenGen, err := DetectAMDZenGeneration()345 zenGen, err := DetectAMDZenGeneration()
353 if err == nil {346 if err == nil {
354 info.AMDZenGen = zenGen347 info.AMDZenGen = zenGen
M internal/ui/installer_forms.go +8 -16
@@ -24,8 +24,7 @@ func CreatePreflightForm(cfg *config.Config, fb *components.FormBuilder, sys *sy
2424 }
2525
2626 // Set default keymap if not already set
27- switch {
28- case cfg.Keymap == "":
27+ if cfg.Keymap == "" {
2928 cfg.Keymap = config.KeymapDefault
3029 }
3130
@@ -86,20 +85,17 @@ func CreateDiskSelectionForm(cfg *config.Config, fb *components.FormBuilder) *hu
8685 label := disk.Path + " (" + disk.Size + ")"
8786
8887 // Add model if available
89- switch {
90- case disk.Model != "":
88+ if disk.Model != "" {
9189 label += " " + disk.Model
9290 }
9391
9492 // Add serial if available
95- switch {
96- case disk.Serial != "":
93+ if disk.Serial != "" {
9794 label += " [" + disk.Serial + "]"
9895 }
9996
10097 // Add vendor if available
101- switch {
102- case disk.Vendor != "" && disk.Model == "":
98+ if disk.Vendor != "" && disk.Model == "" {
10399 label += " " + disk.Vendor
104100 }
105101
@@ -120,8 +116,7 @@ func CreateOptionsForm(cfg *config.Config, fb *components.FormBuilder) *huh.Form
120116
121117 // Auto-detect CPU information
122118 cpuInfo, err := system.DetectCPUInfo()
123- switch {
124- case err == nil:
119+ if err == nil {
125120 cfg.CPUVendor = string(cpuInfo.Vendor)
126121 cfg.Microcode = cpuInfo.Microcode
127122 }
@@ -227,18 +222,15 @@ func CreateAMDPStateForm(cfg *config.Config, cpuInfo *system.CPUInfo, fb *compon
227222 func FormatDiskOption(disk system.Disk) string {
228223 label := fmt.Sprintf("%s (%s)", disk.Path, disk.Size)
229224
230- switch {
231- case disk.Model != "":
225+ if disk.Model != "" {
232226 label += " " + disk.Model
233227 }
234228
235- switch {
236- case disk.Serial != "":
229+ if disk.Serial != "" {
237230 label += " [" + disk.Serial + "]"
238231 }
239232
240- switch {
241- case disk.Vendor != "" && disk.Model == "":
233+ if disk.Vendor != "" && disk.Model == "" {
242234 label += " " + disk.Vendor
243235 }
244236
@@ -24,8 +24,7 @@ func CreatePreflightForm(cfg *config.Config, fb *components.FormBuilder, sys *sy
24 }24 }
25 25
26 // Set default keymap if not already set26 // Set default keymap if not already set
27- switch {27+ if cfg.Keymap == "" {
28- case cfg.Keymap == "":
29 cfg.Keymap = config.KeymapDefault28 cfg.Keymap = config.KeymapDefault
30 }29 }
31 30
@@ -86,20 +85,17 @@ func CreateDiskSelectionForm(cfg *config.Config, fb *components.FormBuilder) *hu
86 label := disk.Path + " (" + disk.Size + ")"85 label := disk.Path + " (" + disk.Size + ")"
87 86
88 // Add model if available87 // Add model if available
89- switch {88+ if disk.Model != "" {
90- case disk.Model != "":
91 label += " " + disk.Model89 label += " " + disk.Model
92 }90 }
93 91
94 // Add serial if available92 // Add serial if available
95- switch {93+ if disk.Serial != "" {
96- case disk.Serial != "":
97 label += " [" + disk.Serial + "]"94 label += " [" + disk.Serial + "]"
98 }95 }
99 96
100 // Add vendor if available97 // Add vendor if available
101- switch {98+ if disk.Vendor != "" && disk.Model == "" {
102- case disk.Vendor != "" && disk.Model == "":
103 label += " " + disk.Vendor99 label += " " + disk.Vendor
104 }100 }
105 101
@@ -120,8 +116,7 @@ func CreateOptionsForm(cfg *config.Config, fb *components.FormBuilder) *huh.Form
120 116
121 // Auto-detect CPU information117 // Auto-detect CPU information
122 cpuInfo, err := system.DetectCPUInfo()118 cpuInfo, err := system.DetectCPUInfo()
123- switch {119+ if err == nil {
124- case err == nil:
125 cfg.CPUVendor = string(cpuInfo.Vendor)120 cfg.CPUVendor = string(cpuInfo.Vendor)
126 cfg.Microcode = cpuInfo.Microcode121 cfg.Microcode = cpuInfo.Microcode
127 }122 }
@@ -227,18 +222,15 @@ func CreateAMDPStateForm(cfg *config.Config, cpuInfo *system.CPUInfo, fb *compon
227 func FormatDiskOption(disk system.Disk) string {222 func FormatDiskOption(disk system.Disk) string {
228 label := fmt.Sprintf("%s (%s)", disk.Path, disk.Size)223 label := fmt.Sprintf("%s (%s)", disk.Path, disk.Size)
229 224
230- switch {225+ if disk.Model != "" {
231- case disk.Model != "":
232 label += " " + disk.Model226 label += " " + disk.Model
233 }227 }
234 228
235- switch {229+ if disk.Serial != "" {
236- case disk.Serial != "":
237 label += " [" + disk.Serial + "]"230 label += " [" + disk.Serial + "]"
238 }231 }
239 232
240- switch {233+ if disk.Vendor != "" && disk.Model == "" {
241- case disk.Vendor != "" && disk.Model == "":
242 label += " " + disk.Vendor234 label += " " + disk.Vendor
243 }235 }
244 236
M internal/ui/model.go +3 -6
@@ -173,8 +173,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
173173 return m, m.currentForm.Init()
174174
175175 case phaseCompleteMsg:
176- switch {
177- case msg.err != nil:
176+ if msg.err != nil {
178177 m.logger.Error("Phase execution failed", "error", msg.err)
179178 m.err = msg.err
180179 m.installEndTime = time.Since(m.installStartTime)
@@ -224,8 +223,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
224223 m.currentForm = f
225224
226225 // Check if form is completed
227- switch {
228- case m.currentForm.State == huh.StateCompleted:
226+ if m.currentForm.State == huh.StateCompleted {
229227 return m, m.handleFormComplete()
230228 }
231229 }
@@ -293,8 +291,7 @@ func (m *Model) handleFormComplete() tea.Cmd {
293291 "use_same_password_for_encryption", m.config.UseSamePasswordForEncryption)
294292
295293 // Handle encryption password setting based on checkbox
296- switch {
297- case m.config.UseSamePasswordForEncryption:
294+ if m.config.UseSamePasswordForEncryption {
298295 m.config.EncryptPassword = m.config.UserPassword
299296 }
300297
@@ -173,8 +173,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
173 return m, m.currentForm.Init()173 return m, m.currentForm.Init()
174 174
175 case phaseCompleteMsg:175 case phaseCompleteMsg:
176- switch {176+ if msg.err != nil {
177- case msg.err != nil:
178 m.logger.Error("Phase execution failed", "error", msg.err)177 m.logger.Error("Phase execution failed", "error", msg.err)
179 m.err = msg.err178 m.err = msg.err
180 m.installEndTime = time.Since(m.installStartTime)179 m.installEndTime = time.Since(m.installStartTime)
@@ -224,8 +223,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
224 m.currentForm = f223 m.currentForm = f
225 224
226 // Check if form is completed225 // Check if form is completed
227- switch {226+ if m.currentForm.State == huh.StateCompleted {
228- case m.currentForm.State == huh.StateCompleted:
229 return m, m.handleFormComplete()227 return m, m.handleFormComplete()
230 }228 }
231 }229 }
@@ -293,8 +291,7 @@ func (m *Model) handleFormComplete() tea.Cmd {
293 "use_same_password_for_encryption", m.config.UseSamePasswordForEncryption)291 "use_same_password_for_encryption", m.config.UseSamePasswordForEncryption)
294 292
295 // Handle encryption password setting based on checkbox293 // Handle encryption password setting based on checkbox
296- switch {294+ if m.config.UseSamePasswordForEncryption {
297- case m.config.UseSamePasswordForEncryption:
298 m.config.EncryptPassword = m.config.UserPassword295 m.config.EncryptPassword = m.config.UserPassword
299 }296 }
300 297

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 0

    ↑↓ moveenter openesc close