refactor(repos): simplify AUR helper to Chaotic-AUR only
Remove complex build-from-source logic for AUR helpers (yay/paru). AUR helpers now only install from Chaotic-AUR repository. Rationale: - Building paru from source takes 13+ minutes (exceeds reasonable timeout) - Build-from-source adds significant complexity (122 lines removed) - Users can manually install AUR helpers post-installation if needed - Chaotic-AUR provides pre-built packages when enabled Changes: - installAURHelper(): Simplified to Chaotic-AUR only, skips if disabled - Removed: ensureBuildDeps() - dependency installation logic - Removed: buildFromAUR() - entire session-based build implementation - Removed: Unused error constants and imports (context, time) Breaking change: AUR helpers require Chaotic-AUR to be enabled during installation. Users without Chaotic-AUR will need to install helpers manually after first boot.
- commit
- 4d8d7e23b3574288a222b15d9c136adf8a49e0e7
- author
- bnema · · 2025-10-31 06:00 UTC
- parent
- dc9b97d
- signature
- GPG Unverified
2B82207D370127A0The key is unknown
1 file · +13 -113
M internal/phases/repos.go +13 -113
| @@ -2,11 +2,9 @@ package phases | |||
| 2 | 2 | ||
| 3 | 3 | import ( | |
| 4 | 4 | "bufio" | |
| 5 | - | "context" | |
| 6 | 5 | "fmt" | |
| 7 | 6 | "path/filepath" | |
| 8 | 7 | "strings" | |
| 9 | - | "time" | |
| 10 | 8 | ||
| 11 | 9 | "github.com/bnema/archup/internal/config" | |
| 12 | 10 | "github.com/bnema/archup/internal/interfaces" | |
| @@ -487,125 +485,27 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) { | |||
| 487 | 485 | return packages, nil | |
| 488 | 486 | } | |
| 489 | 487 | ||
| 490 | - | // installAURHelper installs the selected AUR helper | |
| 491 | - | // Uses Chaotic-AUR if available, falls back to building from source | |
| 488 | + | // installAURHelper installs the selected AUR helper from Chaotic-AUR | |
| 489 | + | // Requires Chaotic-AUR to be enabled (no build-from-source fallback) | |
| 492 | 490 | func (p *ReposPhase) installAURHelper(progressChan chan<- ProgressUpdate) error { | |
| 493 | 491 | helper := p.config.AURHelper | |
| 494 | 492 | ||
| 495 | - | // Strategy 1: Try Chaotic-AUR if available | |
| 496 | - | if p.chaoticAUREnabled { | |
| 497 | - | p.SendOutput(progressChan, fmt.Sprintf("Attempting to install %s from Chaotic-AUR...", helper)) | |
| 498 | - | tryCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", helper) | |
| 499 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, tryCmd); { | |
| 500 | - | case err == nil: | |
| 501 | - | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s installed from Chaotic-AUR", helper)) | |
| 502 | - | p.logger.Info("AUR helper installed from Chaotic-AUR", "helper", helper) | |
| 503 | - | return nil | |
| 504 | - | default: | |
| 505 | - | p.logger.Warn("Failed to install from Chaotic-AUR, building from source", "error", err) | |
| 506 | - | p.SendOutput(progressChan, "[WARN] Chaotic-AUR installation failed, building from source...") | |
| 507 | - | } | |
| 508 | - | } | |
| 509 | - | ||
| 510 | - | // Strategy 2: Build from source with proper dependency verification | |
| 511 | - | p.SendOutput(progressChan, fmt.Sprintf("Building %s from AUR...", helper)) | |
| 512 | - | if err := p.ensureBuildDeps(progressChan, helper); err != nil { | |
| 513 | - | return fmt.Errorf("failed to ensure build dependencies: %w", err) | |
| 514 | - | } | |
| 515 | - | ||
| 516 | - | if err := p.buildFromAUR(progressChan, helper); err != nil { | |
| 517 | - | return fmt.Errorf("failed to build %s: %w", helper, err) | |
| 518 | - | } | |
| 519 | - | ||
| 520 | - | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s built and installed successfully", helper)) | |
| 521 | - | p.logger.Info("AUR helper built from source", "helper", helper) | |
| 522 | - | ||
| 523 | - | return nil | |
| 524 | - | } | |
| 525 | - | ||
| 526 | - | // ensureBuildDeps verifies and installs build dependencies | |
| 527 | - | func (p *ReposPhase) ensureBuildDeps(progressChan chan<- ProgressUpdate, helper string) error { | |
| 528 | - | p.SendOutput(progressChan, "Verifying build dependencies...") | |
| 529 | - | ||
| 530 | - | // Always need base-devel and git | |
| 531 | - | baseCmd := "pacman -S --needed --noconfirm base-devel git" | |
| 532 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, baseCmd); err != nil { | |
| 533 | - | p.logger.Warn("Failed to install base-devel", "error", err) | |
| 534 | - | return fmt.Errorf("failed to install base-devel: %w", err) | |
| 535 | - | } | |
| 536 | - | ||
| 537 | - | // Install language-specific dependencies | |
| 538 | - | var langDeps string | |
| 539 | - | switch helper { | |
| 540 | - | case "yay": | |
| 541 | - | langDeps = "go" | |
| 542 | - | case "paru": | |
| 543 | - | langDeps = "rust cargo" | |
| 544 | - | } | |
| 545 | - | ||
| 546 | - | if langDeps != "" { | |
| 547 | - | p.SendOutput(progressChan, fmt.Sprintf("Installing %s dependencies...", helper)) | |
| 548 | - | depCmd := fmt.Sprintf("pacman -S --needed --noconfirm %s", langDeps) | |
| 549 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, depCmd); err != nil { | |
| 550 | - | p.logger.Warn("Failed to install language dependencies", "helper", helper, "deps", langDeps, "error", err) | |
| 551 | - | return fmt.Errorf("failed to install %s: %w", langDeps, err) | |
| 552 | - | } | |
| 553 | - | } | |
| 554 | - | ||
| 555 | - | p.SendOutput(progressChan, "[OK] Build dependencies verified") | |
| 556 | - | return nil | |
| 557 | - | } | |
| 558 | - | ||
| 559 | - | // buildFromAUR builds an AUR package from source with timeout | |
| 560 | - | func (p *ReposPhase) buildFromAUR(progressChan chan<- ProgressUpdate, helper string) error { | |
| 561 | - | // Build as user with timeout (10 minutes max) | |
| 562 | - | p.SendOutput(progressChan, fmt.Sprintf("Compiling %s (this may take a few minutes)...", helper)) | |
| 563 | - | buildCmd := fmt.Sprintf("su - %s -c 'cd /tmp && rm -rf %s && git clone https://aur.archlinux.org/%s.git && cd %s && makepkg -s --noconfirm'", p.config.Username, helper, helper, helper) | |
| 564 | - | ||
| 565 | - | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) | |
| 566 | - | defer cancel() | |
| 567 | - | ||
| 568 | - | if err := p.chrExec.ChrootExecWithContext(ctx, p.logger.LogPath(), config.PathMnt, buildCmd); err != nil { | |
| 569 | - | return fmt.Errorf("build failed or timed out: %w", err) | |
| 570 | - | } | |
| 571 | - | ||
| 572 | - | // Get exact package filename using makepkg --packagelist | |
| 573 | - | p.SendOutput(progressChan, fmt.Sprintf("Locating %s package...", helper)) | |
| 574 | - | listCmd := fmt.Sprintf("su - %s -c 'cd /tmp/%s && makepkg --packagelist'", p.config.Username, helper) | |
| 575 | - | ||
| 576 | - | output, err := p.chrExec.ChrootExecWithOutput(p.logger.LogPath(), config.PathMnt, listCmd) | |
| 577 | - | if err != nil { | |
| 578 | - | return fmt.Errorf("failed to get package list: %w", err) | |
| 579 | - | } | |
| 580 | - | ||
| 581 | - | // Parse output and filter out debug packages | |
| 582 | - | lines := strings.Split(strings.TrimSpace(output), "\n") | |
| 583 | - | var mainPackage string | |
| 584 | - | for _, line := range lines { | |
| 585 | - | line = strings.TrimSpace(line) | |
| 586 | - | // Skip debug packages (contain "-debug-" in the filename) | |
| 587 | - | if line != "" && !strings.Contains(line, "-debug-") { | |
| 588 | - | mainPackage = line | |
| 589 | - | break | |
| 590 | - | } | |
| 591 | - | } | |
| 592 | - | ||
| 593 | - | if mainPackage == "" { | |
| 594 | - | return fmt.Errorf("no package found for %s", helper) | |
| 493 | + | // Only install if Chaotic-AUR is enabled | |
| 494 | + | if !p.chaoticAUREnabled { | |
| 495 | + | p.SendOutput(progressChan, "[SKIP] AUR helper installation (Chaotic-AUR required)") | |
| 496 | + | p.logger.Info("Skipping AUR helper installation - Chaotic-AUR not enabled", "helper", helper) | |
| 497 | + | return nil | |
| 595 | 498 | } | |
| 596 | 499 | ||
| 597 | - | p.logger.Info("Found package", "helper", helper, "package", mainPackage) | |
| 598 | - | p.SendOutput(progressChan, fmt.Sprintf("Installing %s...", helper)) | |
| 599 | - | ||
| 600 | - | // Install using exact package path | |
| 601 | - | installCmd := fmt.Sprintf("pacman -U --noconfirm %s", mainPackage) | |
| 500 | + | // Install from Chaotic-AUR | |
| 501 | + | p.SendOutput(progressChan, fmt.Sprintf("Installing %s from Chaotic-AUR...", helper)) | |
| 502 | + | installCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", helper) | |
| 602 | 503 | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err != nil { | |
| 603 | - | return fmt.Errorf("failed to install %s: %w", helper, err) | |
| 504 | + | return fmt.Errorf("failed to install %s from Chaotic-AUR: %w", helper, err) | |
| 604 | 505 | } | |
| 605 | 506 | ||
| 606 | - | // Cleanup | |
| 607 | - | cleanCmd := fmt.Sprintf("rm -rf /tmp/%s", helper) | |
| 608 | - | _ = p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cleanCmd) | |
| 507 | + | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s installed from Chaotic-AUR", helper)) | |
| 508 | + | p.logger.Info("AUR helper installed from Chaotic-AUR", "helper", helper) | |
| 609 | 509 | ||
| 610 | 510 | return nil | |
| 611 | 511 | } | |
| @@ -2,11 +2,9 @@ package phases | |||||
| 2 | 2 | ||||
| 3 | import ( | 3 | import ( | ||
| 4 | "bufio" | 4 | "bufio" | ||
| 5 | - | "context" | |||
| 6 | "fmt" | 5 | "fmt" | ||
| 7 | "path/filepath" | 6 | "path/filepath" | ||
| 8 | "strings" | 7 | "strings" | ||
| 9 | - | "time" | |||
| 10 | 8 | ||||
| 11 | "github.com/bnema/archup/internal/config" | 9 | "github.com/bnema/archup/internal/config" | ||
| 12 | "github.com/bnema/archup/internal/interfaces" | 10 | "github.com/bnema/archup/internal/interfaces" | ||
| @@ -487,125 +485,27 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) { | |||||
| 487 | return packages, nil | 485 | return packages, nil | ||
| 488 | } | 486 | } | ||
| 489 | 487 | ||||
| 490 | - | // installAURHelper installs the selected AUR helper | 488 | + | // installAURHelper installs the selected AUR helper from Chaotic-AUR |
| 491 | - | // Uses Chaotic-AUR if available, falls back to building from source | 489 | + | // Requires Chaotic-AUR to be enabled (no build-from-source fallback) |
| 492 | func (p *ReposPhase) installAURHelper(progressChan chan<- ProgressUpdate) error { | 490 | func (p *ReposPhase) installAURHelper(progressChan chan<- ProgressUpdate) error { | ||
| 493 | helper := p.config.AURHelper | 491 | helper := p.config.AURHelper | ||
| 494 | 492 | ||||
| 495 | - | // Strategy 1: Try Chaotic-AUR if available | 493 | + | // Only install if Chaotic-AUR is enabled |
| 496 | - | if p.chaoticAUREnabled { | 494 | + | if !p.chaoticAUREnabled { |
| 497 | - | p.SendOutput(progressChan, fmt.Sprintf("Attempting to install %s from Chaotic-AUR...", helper)) | 495 | + | p.SendOutput(progressChan, "[SKIP] AUR helper installation (Chaotic-AUR required)") |
| 498 | - | tryCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", helper) | 496 | + | p.logger.Info("Skipping AUR helper installation - Chaotic-AUR not enabled", "helper", helper) |
| 499 | - | switch err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, tryCmd); { | 497 | + | return nil |
| 500 | - | case err == nil: | |||
| 501 | - | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s installed from Chaotic-AUR", helper)) | |||
| 502 | - | p.logger.Info("AUR helper installed from Chaotic-AUR", "helper", helper) | |||
| 503 | - | return nil | |||
| 504 | - | default: | |||
| 505 | - | p.logger.Warn("Failed to install from Chaotic-AUR, building from source", "error", err) | |||
| 506 | - | p.SendOutput(progressChan, "[WARN] Chaotic-AUR installation failed, building from source...") | |||
| 507 | - | } | |||
| 508 | - | } | |||
| 509 | - | ||||
| 510 | - | // Strategy 2: Build from source with proper dependency verification | |||
| 511 | - | p.SendOutput(progressChan, fmt.Sprintf("Building %s from AUR...", helper)) | |||
| 512 | - | if err := p.ensureBuildDeps(progressChan, helper); err != nil { | |||
| 513 | - | return fmt.Errorf("failed to ensure build dependencies: %w", err) | |||
| 514 | - | } | |||
| 515 | - | ||||
| 516 | - | if err := p.buildFromAUR(progressChan, helper); err != nil { | |||
| 517 | - | return fmt.Errorf("failed to build %s: %w", helper, err) | |||
| 518 | - | } | |||
| 519 | - | ||||
| 520 | - | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s built and installed successfully", helper)) | |||
| 521 | - | p.logger.Info("AUR helper built from source", "helper", helper) | |||
| 522 | - | ||||
| 523 | - | return nil | |||
| 524 | - | } | |||
| 525 | - | ||||
| 526 | - | // ensureBuildDeps verifies and installs build dependencies | |||
| 527 | - | func (p *ReposPhase) ensureBuildDeps(progressChan chan<- ProgressUpdate, helper string) error { | |||
| 528 | - | p.SendOutput(progressChan, "Verifying build dependencies...") | |||
| 529 | - | ||||
| 530 | - | // Always need base-devel and git | |||
| 531 | - | baseCmd := "pacman -S --needed --noconfirm base-devel git" | |||
| 532 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, baseCmd); err != nil { | |||
| 533 | - | p.logger.Warn("Failed to install base-devel", "error", err) | |||
| 534 | - | return fmt.Errorf("failed to install base-devel: %w", err) | |||
| 535 | - | } | |||
| 536 | - | ||||
| 537 | - | // Install language-specific dependencies | |||
| 538 | - | var langDeps string | |||
| 539 | - | switch helper { | |||
| 540 | - | case "yay": | |||
| 541 | - | langDeps = "go" | |||
| 542 | - | case "paru": | |||
| 543 | - | langDeps = "rust cargo" | |||
| 544 | - | } | |||
| 545 | - | ||||
| 546 | - | if langDeps != "" { | |||
| 547 | - | p.SendOutput(progressChan, fmt.Sprintf("Installing %s dependencies...", helper)) | |||
| 548 | - | depCmd := fmt.Sprintf("pacman -S --needed --noconfirm %s", langDeps) | |||
| 549 | - | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, depCmd); err != nil { | |||
| 550 | - | p.logger.Warn("Failed to install language dependencies", "helper", helper, "deps", langDeps, "error", err) | |||
| 551 | - | return fmt.Errorf("failed to install %s: %w", langDeps, err) | |||
| 552 | - | } | |||
| 553 | - | } | |||
| 554 | - | ||||
| 555 | - | p.SendOutput(progressChan, "[OK] Build dependencies verified") | |||
| 556 | - | return nil | |||
| 557 | - | } | |||
| 558 | - | ||||
| 559 | - | // buildFromAUR builds an AUR package from source with timeout | |||
| 560 | - | func (p *ReposPhase) buildFromAUR(progressChan chan<- ProgressUpdate, helper string) error { | |||
| 561 | - | // Build as user with timeout (10 minutes max) | |||
| 562 | - | p.SendOutput(progressChan, fmt.Sprintf("Compiling %s (this may take a few minutes)...", helper)) | |||
| 563 | - | buildCmd := fmt.Sprintf("su - %s -c 'cd /tmp && rm -rf %s && git clone https://aur.archlinux.org/%s.git && cd %s && makepkg -s --noconfirm'", p.config.Username, helper, helper, helper) | |||
| 564 | - | ||||
| 565 | - | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) | |||
| 566 | - | defer cancel() | |||
| 567 | - | ||||
| 568 | - | if err := p.chrExec.ChrootExecWithContext(ctx, p.logger.LogPath(), config.PathMnt, buildCmd); err != nil { | |||
| 569 | - | return fmt.Errorf("build failed or timed out: %w", err) | |||
| 570 | - | } | |||
| 571 | - | ||||
| 572 | - | // Get exact package filename using makepkg --packagelist | |||
| 573 | - | p.SendOutput(progressChan, fmt.Sprintf("Locating %s package...", helper)) | |||
| 574 | - | listCmd := fmt.Sprintf("su - %s -c 'cd /tmp/%s && makepkg --packagelist'", p.config.Username, helper) | |||
| 575 | - | ||||
| 576 | - | output, err := p.chrExec.ChrootExecWithOutput(p.logger.LogPath(), config.PathMnt, listCmd) | |||
| 577 | - | if err != nil { | |||
| 578 | - | return fmt.Errorf("failed to get package list: %w", err) | |||
| 579 | - | } | |||
| 580 | - | ||||
| 581 | - | // Parse output and filter out debug packages | |||
| 582 | - | lines := strings.Split(strings.TrimSpace(output), "\n") | |||
| 583 | - | var mainPackage string | |||
| 584 | - | for _, line := range lines { | |||
| 585 | - | line = strings.TrimSpace(line) | |||
| 586 | - | // Skip debug packages (contain "-debug-" in the filename) | |||
| 587 | - | if line != "" && !strings.Contains(line, "-debug-") { | |||
| 588 | - | mainPackage = line | |||
| 589 | - | break | |||
| 590 | - | } | |||
| 591 | - | } | |||
| 592 | - | ||||
| 593 | - | if mainPackage == "" { | |||
| 594 | - | return fmt.Errorf("no package found for %s", helper) | |||
| 595 | } | 498 | } | ||
| 596 | 499 | ||||
| 597 | - | p.logger.Info("Found package", "helper", helper, "package", mainPackage) | 500 | + | // Install from Chaotic-AUR |
| 598 | - | p.SendOutput(progressChan, fmt.Sprintf("Installing %s...", helper)) | 501 | + | p.SendOutput(progressChan, fmt.Sprintf("Installing %s from Chaotic-AUR...", helper)) |
| 599 | - | 502 | + | installCmd := fmt.Sprintf("pacman -S --noconfirm --needed %s", helper) | |
| 600 | - | // Install using exact package path | |||
| 601 | - | installCmd := fmt.Sprintf("pacman -U --noconfirm %s", mainPackage) | |||
| 602 | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err != nil { | 503 | if err := p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, installCmd); err != nil { | ||
| 603 | - | return fmt.Errorf("failed to install %s: %w", helper, err) | 504 | + | return fmt.Errorf("failed to install %s from Chaotic-AUR: %w", helper, err) |
| 604 | } | 505 | } | ||
| 605 | 506 | ||||
| 606 | - | // Cleanup | 507 | + | p.SendOutput(progressChan, fmt.Sprintf("[OK] %s installed from Chaotic-AUR", helper)) |
| 607 | - | cleanCmd := fmt.Sprintf("rm -rf /tmp/%s", helper) | 508 | + | p.logger.Info("AUR helper installed from Chaotic-AUR", "helper", helper) |
| 608 | - | _ = p.chrExec.ChrootExec(p.logger.LogPath(), config.PathMnt, cleanCmd) | |||
| 609 | 509 | ||||
| 610 | return nil | 510 | return nil | ||
| 611 | } | 511 | } | ||