⋯ 1 hidden line@@ -8,6 +9,7 @@ import ( 8 9 9 "github.com/bnema/archup/internal/application/commands" 10 "github.com/bnema/archup/internal/application/commands" 10 "github.com/bnema/archup/internal/application/dto" 11 "github.com/bnema/archup/internal/application/dto" 12 + "github.com/bnema/archup/internal/config" 11 "github.com/bnema/archup/internal/domain/packages" 13 "github.com/bnema/archup/internal/domain/packages" 12 "github.com/bnema/archup/internal/domain/ports" 14 "github.com/bnema/archup/internal/domain/ports" 13 ) 15 ) ⋯ 46 hidden lines@@ -60,25 +62,20 @@ func (h *ReposHandler) Handle(ctx context.Context, cmd commands.SetupRepositorie 60 "aurHelper" , repo.AURHelper()) 62 "aurHelper" , repo.AURHelper()) 61 63 62 pacmanConfPath := filepath.Join(cmd.MountPoint, "etc" , "pacman.conf" ) 64 pacmanConfPath := filepath.Join(cmd.MountPoint, "etc" , "pacman.conf" ) 63 - if repo.EnableMultilib() || repo.EnableChaotic() { 65 + 66 + // Enable multilib first (doesn't require external files) 67 + if repo.EnableMultilib() { 64 confBytes, err := h.fs.ReadFile(pacmanConfPath) 68 confBytes, err := h.fs.ReadFile(pacmanConfPath) 65 if err != nil { 69 if err != nil { 66 return fail("Failed to read pacman.conf" , err) 70 return fail("Failed to read pacman.conf" , err) 67 } 71 } 68 - 72 + conf := enableMultilibSection(string(confBytes)) 69 - conf := string(confBytes) 70 - if repo.EnableMultilib() { 71 - conf = enableMultilibSection(conf) 72 - } 73 - if repo.EnableChaotic() { 74 - conf = ensureChaoticRepo(conf) 75 - } 76 - 77 if err := h.fs.WriteFile(pacmanConfPath, []byte(conf), 0644); err != nil { 73 if err := h.fs.WriteFile(pacmanConfPath, []byte(conf), 0644); err != nil { 78 return fail("Failed to write pacman.conf" , err) 74 return fail("Failed to write pacman.conf" , err) 79 } 75 } 80 } 76 } 81 77 78 + // For chaotic-aur: install keyring and mirrorlist BEFORE adding to pacman.conf 82 if repo.EnableChaotic() { 79 if repo.EnableChaotic() { 83 if _, err := h.chrExec.ExecuteInChroot(ctx, cmd.MountPoint, "pacman-key" , "--recv-key" , "3056513887B78AEB" , "--keyserver" , "keyserver.ubuntu.com" ); err != nil { 80 if _, err := h.chrExec.ExecuteInChroot(ctx, cmd.MountPoint, "pacman-key" , "--recv-key" , "3056513887B78AEB" , "--keyserver" , "keyserver.ubuntu.com" ); err != nil { 84 return fail("Failed to receive Chaotic-AUR key" , err) 81 return fail("Failed to receive Chaotic-AUR key" , err) ⋯ 8 hidden lines@@ -93,8 +90,19 @@ func (h *ReposHandler) Handle(ctx context.Context, cmd commands.SetupRepositorie 93 "https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst" ); err != nil { 90 "https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst" ); err != nil { 94 return fail("Failed to install Chaotic-AUR keyring" , err) 91 return fail("Failed to install Chaotic-AUR keyring" , err) 95 } 92 } 93 + 94 + // Now that mirrorlist exists, add chaotic-aur to pacman.conf 95 + confBytes, err := h.fs.ReadFile(pacmanConfPath) 96 + if err != nil { 97 + return fail("Failed to read pacman.conf" , err) 98 + } 99 + conf := ensureChaoticRepo(string(confBytes)) 100 + if err := h.fs.WriteFile(pacmanConfPath, []byte(conf), 0644); err != nil { 101 + return fail("Failed to write pacman.conf" , err) 102 + } 96 } 103 } 97 104 105 + // Sync repos after all config changes 98 if repo.EnableMultilib() || repo.EnableChaotic() { 106 if repo.EnableMultilib() || repo.EnableChaotic() { 99 if _, err := h.chrExec.ExecuteInChroot(ctx, cmd.MountPoint, "pacman" , "-Sy" , "--noconfirm" ); err != nil { 107 if _, err := h.chrExec.ExecuteInChroot(ctx, cmd.MountPoint, "pacman" , "-Sy" , "--noconfirm" ); err != nil { 100 return fail("Failed to sync pacman repositories" , err) 108 return fail("Failed to sync pacman repositories" , err) ⋯ 6 hidden lines@@ -107,6 +115,19 @@ func (h *ReposHandler) Handle(ctx context.Context, cmd commands.SetupRepositorie 107 } 115 } 108 } 116 } 109 117 118 + // Install extra packages from extra.packages file 119 + extraPkgs, err := h.loadExtraPackages() 120 + if err != nil { 121 + h.logger.Warn("Could not load extra.packages" , "error" , err) 122 + } else if len(extraPkgs) > 0 { 123 + h.logger.Info("Installing extra packages" , "count" , len(extraPkgs)) 124 + args := append([]string{"-S" , "--noconfirm" , "--needed" }, extraPkgs...) 125 + if _, err := h.chrExec.ExecuteInChroot(ctx, cmd.MountPoint, "pacman" , args...); err != nil { 126 + return fail("Failed to install extra packages" , err) 127 + } 128 + h.logger.Info("Extra packages installed successfully" ) 129 + } 130 + 110 result.Success = true 131 result.Success = true 111 result.AURHelper = repo.AURHelper().String() 132 result.AURHelper = repo.AURHelper().String() 112 133 ⋯ 1 hidden line@@ -114,6 +135,37 @@ func (h *ReposHandler) Handle(ctx context.Context, cmd commands.SetupRepositorie 114 return result, nil 135 return result, nil 115 } 136 } 116 137 138 + // loadExtraPackages reads the extra package list from file 139 + func (h *ReposHandler) loadExtraPackages() ([]string, error) {140 + packageFile := filepath.Join(config.DefaultInstallDir, config.ExtraPackagesFile) 141 + 142 + content, err := h.fs.ReadFile(packageFile) 143 + if err != nil { 144 + return nil , fmt.Errorf("failed to read %s: %w" , packageFile, err) 145 + } 146 + 147 + var pkgs []string 148 + scanner := bufio.NewScanner(strings.NewReader(string(content))) 149 + 150 + for scanner.Scan() { 151 + line := strings.TrimSpace(scanner.Text()) 152 + 153 + // Skip comments and empty lines 154 + if line == "" || strings.HasPrefix(line, "#" ) { 155 + continue 156 + } 157 + 158 + pkgs = append(pkgs, line) 159 + } 160 + 161 + if err := scanner.Err(); err != nil { 162 + return nil , fmt.Errorf("error reading package file: %w" , err) 163 + } 164 + 165 + h.logger.Info("Loaded extra packages from file" , "file" , packageFile, "count" , len(pkgs)) 166 + return pkgs, nil 167 + } 168 + 117 func enableMultilibSection(conf string) string {169 func enableMultilibSection(conf string) string {118 lines := strings.Split(conf, "\n" ) 170 lines := strings.Split(conf, "\n" ) 119 inSection := false 171 inSection := false