From 3d329073fb7dc827f93117ba734e5b695510db36 Mon Sep 17 00:00:00 2001 From: rain Date: Mon, 22 Jun 2026 15:38:27 -0400 Subject: [PATCH] Force bun as a system package on arch (no curl-install shadow) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per user preference (memory 2026-06-22): PMs first (pacman via chaotic-aur on arch, apt on debian), curl-install only as last-resort fallback. bun is in [extra] on arch since 1.2.x, so the pacman package is the right install path. Three changes to run_once_20-install-user-packages.sh.tmpl: 1. Arch missing-detect: for the bun entry, check Installed From : extra Name : bun Version : 1.3.14-1 Description : Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one Architecture : x86_64 URL : https://github.com/oven-sh/bun Licenses : MIT Groups : None Provides : None Depends On : glibc icu Optional Deps : None Required By : None Optional For : None Conflicts With : None Replaces : None Installed Size : 66.08 MiB Packager : Sven-Hendrik Haase Build Date : Sun 17 May 2026 09:29:39 AM EDT Install Date : Sun 14 Jun 2026 12:05:09 AM EDT Install Reason : Explicitly installed Install Script : No Validated By : Signature (system-package tracking) instead of /usr/bin/bun (binary on PATH). A curl-installed bun at ~/.bun/bin/bun or ~/.local/bin/bun would otherwise pass the command check, leaving us with a non-PM-managed install that topgrade wouldn't see. 2. Post-install verification on arch: assert that Installed From : extra Name : bun Version : 1.3.14-1 Description : Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one Architecture : x86_64 URL : https://github.com/oven-sh/bun Licenses : MIT Groups : None Provides : None Depends On : glibc icu Optional Deps : None Required By : None Optional For : None Conflicts With : None Replaces : None Installed Size : 66.08 MiB Packager : Sven-Hendrik Haase Build Date : Sun 17 May 2026 09:29:39 AM EDT Install Date : Sun 14 Jun 2026 12:05:09 AM EDT Install Reason : Explicitly installed Install Script : No Validated By : Signature succeeds and report the installed version + repo. Fails loudly if bun is not tracked by pacman (curl shadow or failed install) so the operator can clean up and re-run. 3. Same post-install verification on debian: assert that /usr/bin/bun succeeds after the curl-install, and report the version. On debian bun is not in apt, so curl is the last-resort install path. Verify that the resulting binary is reachable on PATH. PATH order: in run_once_20, /usr/bin and /bin are now first so any pacman-managed bun wins over a curl-installed shadow at ~/.bun/bin or ~/.local/bin. ~/.local/bin, ~/.bun/bin, ~/.cargo/bin still come next so omp (installed via bun to ~/.bun/bin) is also reachable. Triggered a re-run of the script on each box to confirm the verification line shows up: 'bun: 1.3.14-1 (from extra) — system-package install verified'. --- run_once_20-install-user-packages.sh.tmpl | 54 +++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/run_once_20-install-user-packages.sh.tmpl b/run_once_20-install-user-packages.sh.tmpl index f56b823..1ebfb63 100755 --- a/run_once_20-install-user-packages.sh.tmpl +++ b/run_once_20-install-user-packages.sh.tmpl @@ -16,7 +16,13 @@ set -euo pipefail # invoked from a non-interactive context (e.g. `chezmoi apply` over SSH). # These are normally added by .zshrc, but this script runs in a plain # shell where those rc files aren't sourced. -export PATH="$HOME/.local/bin:$HOME/.bun/bin:$HOME/.cargo/bin:$PATH" +# +# For `bun` on arch: we deliberately put /usr/bin BEFORE the user +# locations so the pacman-managed binary wins over any curl-installed +# copy that might be shadowing it. The post-install verification below +# fails loudly if pacman doesn't actually have bun, so the operator +# can remove the curl shadow and re-run. +export PATH="/usr/bin:/bin:$HOME/.local/bin:$HOME/.bun/bin:$HOME/.cargo/bin:$PATH" log() { printf '\033[1;34m[packages]\033[0m %s\n' "$*"; } die() { printf '\033[1;31m[packages ERROR]\033[0m %s\n' "$*" >&2; exit 1; } @@ -29,6 +35,13 @@ ZSH_CUSTOM="${ZSH_CUSTOM:-$USER_HOME/.oh-my-zsh/custom}" # Only run pacman if anything is actually missing. Avoids a no-op sudo # (which would still prompt for a password even when there's nothing to # install) on boxes where all the user packages are already present. +# +# For `bun` specifically, we check `pacman -Qi bun` (not `command -v +# bun`) so the script forces a system-package install via pacman, not a +# curl-installed binary in ~/.bun/bin or ~/.local/bin. Per user +# preference: PMs first (pacman via chaotic-aur on arch, apt on debian), +# `curl | bash` only as last-resort fallback when the package isn't in +# any repo. bun is in [extra] on arch since 1.2.x, so pacman handles it. PACMAN_PKGS=( zsh tmux neovim git base-devel bat btop htop fastfetch @@ -40,7 +53,15 @@ PACMAN_PKGS=( ) MISSING_PKGS=() for p in "${PACMAN_PKGS[@]}"; do - if ! command -v "$p" >/dev/null 2>&1 && ! pacman -Qi "$p" >/dev/null 2>&1; then + if [[ "$p" == "bun" ]]; then + # System-package check for bun: must be tracked by pacman, not + # just a binary on PATH. A curl-installed bun at ~/.bun/bin/bun + # would otherwise pass the `command -v` check and skip pacman, + # leaving us with a non-PM-managed install. + if ! pacman -Qi "$p" >/dev/null 2>&1; then + MISSING_PKGS+=("$p") + fi + elif ! command -v "$p" >/dev/null 2>&1 && ! pacman -Qi "$p" >/dev/null 2>&1; then MISSING_PKGS+=("$p") fi done @@ -53,6 +74,19 @@ else log "all user packages already installed; skipping pacman" fi +# Post-install verification: bun must come from the system package +# manager, not a curl-install. If it does, fail loudly so the operator +# can remove the curl-installed binary and re-run. +if ! pacman -Qi bun >/dev/null 2>&1; then + log "ERROR: bun is not tracked by pacman after install" + log " (a curl-installed binary may be shadowing the package)" + log " remove ~/.bun/ and ~/.local/bin/bun, then re-run" + exit 1 +fi +BUN_FROM=$(pacman -Qi bun 2>/dev/null | awk -F': *' '/^Installed From/ {print $2}') +BUN_VER=$(pacman -Qi bun 2>/dev/null | awk -F': *' '/^Version/ {print $2}') +log "bun: $BUN_VER (from $BUN_FROM) — system-package install verified" + # --------------------------- Pi coding agent + oh-my-pi --------------------- # Arch: bun comes from pacman (above), used here for the global install. if command -v bun >/dev/null 2>&1; then @@ -103,12 +137,26 @@ fi # bun isn't in debian repos. Install via official script into ~/.local # (so the binary lands at ~/.local/bin/bun, which is already in PATH -# via .zshrc — no extra PATH config needed). +# via .zshrc — no extra PATH config needed). Per user preference, this +# is a last-resort fallback: PMs first, then pinned binaries from +# official sources, then `curl | bash`. apt on debian-stable has no +# bun, so we land on the official install. if ! command -v bun >/dev/null 2>&1; then log "installing bun to ~/.local/bin (debian: not in apt)" curl -fsSL https://bun.sh/install | BUN_INSTALL="$HOME/.local" bash fi +# Post-install verification: confirm bun is reachable on PATH. On +# debian, the official install puts it at $BUN_INSTALL/bin/bun, so we +# expect ~/.local/bin/bun in this case. +if ! command -v bun >/dev/null 2>&1; then + log "ERROR: bun install succeeded but bun is not on PATH" + log " check \$BUN_INSTALL/bin/bun exists and is in PATH" + exit 1 +fi +BUN_VER=$(bun --version 2>/dev/null) +log "bun: $BUN_VER (from official bun.sh installer; debian has no apt package)" + # fd on Debian ships as 'fdfind' to avoid clashing with fd (the dedupe tool). # Symlink so .zshrc can find 'fd' on PATH. if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then