detached 9700fec

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 @@
55 snapper
66 snap-pac
77
8-# Go toolchain (for AUR helper)
8+# Build tools (for AUR helpers)
9+base-devel
910 go
11+cargo
1012
1113 # System utilities
1214 dosfstools
@@ -5,8 +5,10 @@
5 snapper5 snapper
6 snap-pac6 snap-pac
7 7
8-# Go toolchain (for AUR helper)8+# Build tools (for AUR helpers)
9+base-devel
9 go10 go
11+cargo
10 12
11 # System utilities13 # System utilities
12 dosfstools14 dosfstools
M internal/phases/repos.go +24 -20
@@ -215,11 +215,12 @@ func (p *ReposPhase) enableChaoticAUR(progressChan chan<- ProgressUpdate) error
215215
216216 p.SendOutput(progressChan, "[OK] Chaotic GPG key imported")
217217
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
223224 }
224225
225226 p.SendOutput(progressChan, "[OK] Chaotic packages installed")
@@ -339,24 +340,27 @@ func (p *ReposPhase) loadExtraPackages() ([]string, error) {
339340
340341 // installAURHelper installs the selected AUR helper
341342 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)
349357 }
350358
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)
358362
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))
360364
361365 return nil
362366 }
@@ -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-mirrorlist218+ // 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 helper341 // 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-AUR345+ // 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 installation359+ // 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 nil365 return nil
362 }366 }
M internal/system/pacman.go +21 -0
@@ -42,3 +42,24 @@ func PacmanRemove(logPath string, packages ...string) error {
4242 }
4343 return nil
4444 }
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 nil43 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+}

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