fix(repos): build AUR helpers from source, handle Chaotic-AUR unavailability
- Add base-devel and cargo to extra.packages for building AUR helpers - Update installAURHelper to build paru/yay from AUR source using makepkg - Add DownloadAndInstallPackages helper using curl -L to follow redirects - Gracefully skip Chaotic-AUR if packages unavailable (404 errors) - No longer depends on Chaotic-AUR for AUR helper installation Fixes installation failures when Chaotic-AUR infrastructure is down.
- commit
- 9700fec392a74d028d343f9a1f020c6462d58fde
- author
- bnema · · 2025-10-28 04:17 UTC
- parent
- 0c4b74a
- signature
- unsigned
3 files · +48 -21
M install/extra.packages +3 -1
| @@ -5,8 +5,10 @@ | |||
| 5 | 5 | snapper | |
| 6 | 6 | snap-pac | |
| 7 | 7 | ||
| 8 | - | # Go toolchain (for AUR helper) | |
| 8 | + | # Build tools (for AUR helpers) | |
| 9 | + | base-devel | |
| 9 | 10 | go | |
| 11 | + | cargo | |
| 10 | 12 | ||
| 11 | 13 | # System utilities | |
| 12 | 14 | dosfstools | |
| @@ -5,8 +5,10 @@ | |||||
| 5 | snapper | 5 | snapper | ||
| 6 | snap-pac | 6 | snap-pac | ||
| 7 | 7 | ||||
| 8 | - | # Go toolchain (for AUR helper) | 8 | + | # Build tools (for AUR helpers) |
| 9 | + | base-devel | |||
| 9 | go | 10 | go | ||
| 11 | + | cargo | |||
| 10 | 12 | ||||
| 11 | # System utilities | 13 | # System utilities | ||
| 12 | dosfstools | 14 | dosfstools | ||
M internal/phases/repos.go +24 -20
| @@ -215,11 +215,12 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error | |||
| 215 | 215 | ||
| 216 | 216 | p.SendOutput(progressChan, "[OK] Chaotic GPG key imported") | |
| 217 | 217 | ||
| 218 | - | // Install chaotic-keyring and chaotic-mirrorlist | |
| 219 | - | installCmd := fmt.Sprintf("pacman -U --noconfirm '%s' '%s'", keyringURL, mirrorlistURL) | |
| 220 | - | switch err := system.ChrootExec(p.logger.LogPath(),config.PathMnt, installCmd); { | |
| 221 | - | case err != nil: | |
| 222 | - | return fmt.Errorf("failed to install Chaotic packages: %w", err) | |
| 218 | + | // Download and install chaotic-keyring and chaotic-mirrorlist | |
| 219 | + | p.SendOutput(progressChan, "Downloading Chaotic-AUR packages...") | |
| 220 | + | if err := system.DownloadAndInstallPackages(p.logger.LogPath(), config.PathMnt, keyringURL, mirrorlistURL); err != nil { | |
| 221 | + | p.logger.Warn("Chaotic-AUR packages unavailable, skipping", "error", err) | |
| 222 | + | p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable, skipping (AUR helper will be built from source)") | |
| 223 | + | return nil | |
| 223 | 224 | } | |
| 224 | 225 | ||
| 225 | 226 | p.SendOutput(progressChan, "[OK] Chaotic packages installed") | |
| @@ -339,24 +340,27 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) { | |||
| 339 | 340 | ||
| 340 | 341 | // installAURHelper installs the selected AUR helper | |
| 341 | 342 | func (p *ReposPhase) installAURHelper(progressChan chan<- ProgressUpdate) error { | |
| 342 | - | p.SendOutput(progressChan, fmt.Sprintf("Installing %s AUR helper...", p.config.AURHelper)) | |
| 343 | - | ||
| 344 | - | // Install AUR helper from Chaotic-AUR | |
| 345 | - | installCmd := fmt.Sprintf("pacman -S --noconfirm %s", p.config.AURHelper) | |
| 346 | - | switch err := system.ChrootExec(p.logger.LogPath(),config.PathMnt, installCmd); { | |
| 347 | - | case err != nil: | |
| 348 | - | return fmt.Errorf("failed to install %s: %w", p.config.AURHelper, err) | |
| 343 | + | p.SendOutput(progressChan, fmt.Sprintf("Building %s from AUR...", p.config.AURHelper)) | |
| 344 | + | ||
| 345 | + | // Build AUR helper from source | |
| 346 | + | buildCmd := fmt.Sprintf(` | |
| 347 | + | su - %s -c ' | |
| 348 | + | cd /tmp && | |
| 349 | + | git clone https://aur.archlinux.org/%s.git && | |
| 350 | + | cd %s && | |
| 351 | + | makepkg -si --noconfirm | |
| 352 | + | ' | |
| 353 | + | `, p.config.Username, p.config.AURHelper, p.config.AURHelper) | |
| 354 | + | ||
| 355 | + | if err := system.ChrootExec(p.logger.LogPath(), config.PathMnt, buildCmd); err != nil { | |
| 356 | + | return fmt.Errorf("failed to build %s: %w", p.config.AURHelper, err) | |
| 349 | 357 | } | |
| 350 | 358 | ||
| 351 | - | // Verify installation | |
| 352 | - | verifyCmd := fmt.Sprintf("su - %s -c '%s --version'", p.config.Username, p.config.AURHelper) | |
| 353 | - | result := system.RunSimple("arch-chroot", config.PathMnt, "sh", "-c", verifyCmd) | |
| 354 | - | switch { | |
| 355 | - | case result.ExitCode != 0: | |
| 356 | - | return fmt.Errorf("%s verification failed", p.config.AURHelper) | |
| 357 | - | } | |
| 359 | + | // Cleanup | |
| 360 | + | cleanupCmd := fmt.Sprintf("rm -rf /home/%s/tmp/%s", p.config.Username, p.config.AURHelper) | |
| 361 | + | system.ChrootExec(p.logger.LogPath(), config.PathMnt, cleanupCmd) | |
| 358 | 362 | ||
| 359 | - | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s installed successfully", p.config.AURHelper)) | |
| 363 | + | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s built and installed", p.config.AURHelper)) | |
| 360 | 364 | ||
| 361 | 365 | return nil | |
| 362 | 366 | } | |
| @@ -215,11 +215,12 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error | |||||
| 215 | 215 | ||||
| 216 | p.SendOutput(progressChan, "[OK] Chaotic GPG key imported") | 216 | p.SendOutput(progressChan, "[OK] Chaotic GPG key imported") | ||
| 217 | 217 | ||||
| 218 | - | // Install chaotic-keyring and chaotic-mirrorlist | 218 | + | // Download and install chaotic-keyring and chaotic-mirrorlist |
| 219 | - | installCmd := fmt.Sprintf("pacman -U --noconfirm '%s' '%s'", keyringURL, mirrorlistURL) | 219 | + | p.SendOutput(progressChan, "Downloading Chaotic-AUR packages...") |
| 220 | - | switch err := system.ChrootExec(p.logger.LogPath(),config.PathMnt, installCmd); { | 220 | + | if err := system.DownloadAndInstallPackages(p.logger.LogPath(), config.PathMnt, keyringURL, mirrorlistURL); err != nil { |
| 221 | - | case err != nil: | 221 | + | p.logger.Warn("Chaotic-AUR packages unavailable, skipping", "error", err) |
| 222 | - | return fmt.Errorf("failed to install Chaotic packages: %w", err) | 222 | + | p.SendOutput(progressChan, "[WARN] Chaotic-AUR unavailable, skipping (AUR helper will be built from source)") |
| 223 | + | return nil | |||
| 223 | } | 224 | } | ||
| 224 | 225 | ||||
| 225 | p.SendOutput(progressChan, "[OK] Chaotic packages installed") | 226 | p.SendOutput(progressChan, "[OK] Chaotic packages installed") | ||
| @@ -339,24 +340,27 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) { | |||||
| 339 | 340 | ||||
| 340 | // installAURHelper installs the selected AUR helper | 341 | // installAURHelper installs the selected AUR helper | ||
| 341 | func (p *ReposPhase) installAURHelper(progressChan chan<- ProgressUpdate) error { | 342 | func (p *ReposPhase) installAURHelper(progressChan chan<- ProgressUpdate) error { | ||
| 342 | - | p.SendOutput(progressChan, fmt.Sprintf("Installing %s AUR helper...", p.config.AURHelper)) | 343 | + | p.SendOutput(progressChan, fmt.Sprintf("Building %s from AUR...", p.config.AURHelper)) |
| 343 | - | 344 | + | ||
| 344 | - | // Install AUR helper from Chaotic-AUR | 345 | + | // Build AUR helper from source |
| 345 | - | installCmd := fmt.Sprintf("pacman -S --noconfirm %s", p.config.AURHelper) | 346 | + | buildCmd := fmt.Sprintf(` |
| 346 | - | switch err := system.ChrootExec(p.logger.LogPath(),config.PathMnt, installCmd); { | 347 | + | su - %s -c ' |
| 347 | - | case err != nil: | 348 | + | cd /tmp && |
| 348 | - | return fmt.Errorf("failed to install %s: %w", p.config.AURHelper, err) | 349 | + | git clone https://aur.archlinux.org/%s.git && |
| 350 | + | cd %s && | |||
| 351 | + | makepkg -si --noconfirm | |||
| 352 | + | ' | |||
| 353 | + | `, p.config.Username, p.config.AURHelper, p.config.AURHelper) | |||
| 354 | + | ||||
| 355 | + | if err := system.ChrootExec(p.logger.LogPath(), config.PathMnt, buildCmd); err != nil { | |||
| 356 | + | return fmt.Errorf("failed to build %s: %w", p.config.AURHelper, err) | |||
| 349 | } | 357 | } | ||
| 350 | 358 | ||||
| 351 | - | // Verify installation | 359 | + | // Cleanup |
| 352 | - | verifyCmd := fmt.Sprintf("su - %s -c '%s --version'", p.config.Username, p.config.AURHelper) | 360 | + | cleanupCmd := fmt.Sprintf("rm -rf /home/%s/tmp/%s", p.config.Username, p.config.AURHelper) |
| 353 | - | result := system.RunSimple("arch-chroot", config.PathMnt, "sh", "-c", verifyCmd) | 361 | + | system.ChrootExec(p.logger.LogPath(), config.PathMnt, cleanupCmd) |
| 354 | - | switch { | |||
| 355 | - | case result.ExitCode != 0: | |||
| 356 | - | return fmt.Errorf("%s verification failed", p.config.AURHelper) | |||
| 357 | - | } | |||
| 358 | 362 | ||||
| 359 | - | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s installed successfully", p.config.AURHelper)) | 363 | + | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s built and installed", p.config.AURHelper)) |
| 360 | 364 | ||||
| 361 | return nil | 365 | return nil | ||
| 362 | } | 366 | } | ||
M internal/system/pacman.go +21 -0
| @@ -42,3 +42,24 @@ func PacmanRemove(logPath string, packages ...string) error { | |||
| 42 | 42 | } | |
| 43 | 43 | return nil | |
| 44 | 44 | } | |
| 45 | + | ||
| 46 | + | // DownloadAndInstallPackages downloads packages from URLs using curl and installs them in chroot | |
| 47 | + | func DownloadAndInstallPackages(logPath, chrootPath string, urls ...string) error { | |
| 48 | + | if len(urls) == 0 { | |
| 49 | + | return fmt.Errorf("no URLs provided") | |
| 50 | + | } | |
| 51 | + | ||
| 52 | + | // Download and install in one command | |
| 53 | + | cmd := "mkdir -p /tmp && " | |
| 54 | + | for i, url := range urls { | |
| 55 | + | cmd += fmt.Sprintf("curl -L -f -o /tmp/pkg%d.tar.zst '%s' && ", i, url) | |
| 56 | + | } | |
| 57 | + | cmd += "pacman -U --noconfirm /tmp/pkg*.tar.zst && rm -f /tmp/pkg*.tar.zst" | |
| 58 | + | ||
| 59 | + | if err := ChrootExec(logPath, chrootPath, cmd); err != nil { | |
| 60 | + | ChrootExec(logPath, chrootPath, "rm -f /tmp/pkg*.tar.zst") // Cleanup | |
| 61 | + | return err | |
| 62 | + | } | |
| 63 | + | ||
| 64 | + | return nil | |
| 65 | + | } | |
| @@ -42,3 +42,24 @@ func PacmanRemove(logPath string, packages ...string) error { | |||||
| 42 | } | 42 | } | ||
| 43 | return nil | 43 | return nil | ||
| 44 | } | 44 | } | ||
| 45 | + | ||||
| 46 | + | // DownloadAndInstallPackages downloads packages from URLs using curl and installs them in chroot | |||
| 47 | + | func DownloadAndInstallPackages(logPath, chrootPath string, urls ...string) error { | |||
| 48 | + | if len(urls) == 0 { | |||
| 49 | + | return fmt.Errorf("no URLs provided") | |||
| 50 | + | } | |||
| 51 | + | ||||
| 52 | + | // Download and install in one command | |||
| 53 | + | cmd := "mkdir -p /tmp && " | |||
| 54 | + | for i, url := range urls { | |||
| 55 | + | cmd += fmt.Sprintf("curl -L -f -o /tmp/pkg%d.tar.zst '%s' && ", i, url) | |||
| 56 | + | } | |||
| 57 | + | cmd += "pacman -U --noconfirm /tmp/pkg*.tar.zst && rm -f /tmp/pkg*.tar.zst" | |||
| 58 | + | ||||
| 59 | + | if err := ChrootExec(logPath, chrootPath, cmd); err != nil { | |||
| 60 | + | ChrootExec(logPath, chrootPath, "rm -f /tmp/pkg*.tar.zst") // Cleanup | |||
| 61 | + | return err | |||
| 62 | + | } | |||
| 63 | + | ||||
| 64 | + | return nil | |||
| 65 | + | } | |||