From b4a4b6e6b451b325cbcd8671dbe904dc00a59756 Mon Sep 17 00:00:00 2001 From: rain Date: Sun, 21 Jun 2026 20:43:38 -0400 Subject: [PATCH] Add pacstall for neovim install + version updates on debian Three changes: 1. NEW run_once_05-install-pacstall.sh.tmpl (debian-only) Installs pacstall via its official installer. Pacstall is an AUR-like package manager for debian/ubuntu, with neovim at 0.12.2-1 (current as of bootstrap). The installer requires root and prompts for 'install axel?', so we run it under sudo with NON_INTERACTIVE=true and stdin redirected from /dev/null. 2. UPDATE run_once_20-install-user-packages.sh.tmpl On debian, prefer pacstall over the GitHub tarball when pacstall is available. The tarball fallback remains for the case where pacstall install failed or isn't wanted. 3. NEW dot_config/topgrade/topgrade.toml Topgrade's built-in pacstall step auto-detects pacstall and runs 'pacstall -U -Up' (update repo + upgrade packages). Built-in chezmoi step also auto-detects chezmoi. So our topgrade config just sets pre_sudo=true for password caching and ignore_failures for node. --- dot_config/topgrade/topgrade.toml | 17 ++++++ run_once_05-install-pacstall.sh.tmpl | 58 ++++++++++++++++++ run_once_20-install-user-packages.sh.tmpl | 73 +++++++++++++---------- 3 files changed, 116 insertions(+), 32 deletions(-) create mode 100644 dot_config/topgrade/topgrade.toml create mode 100644 run_once_05-install-pacstall.sh.tmpl diff --git a/dot_config/topgrade/topgrade.toml b/dot_config/topgrade/topgrade.toml new file mode 100644 index 0000000..5c6bd1f --- /dev/null +++ b/dot_config/topgrade/topgrade.toml @@ -0,0 +1,17 @@ +# ============================================================================= +# topgrade.toml — chezmoi-managed +# Most steps (system, pacstall, flatpak, snap, cargo, npm, pyenv, rustup, etc.) +# are auto-detected by topgrade when their binaries are on $PATH. Only set +# custom config here. +# ============================================================================= + +[misc] +# Run `sudo -v` at the start so cached credentials cover the whole run. +# Without this, topgrade will pause for password mid-run on each sudo invocation. +pre_sudo = true + +# Don't fail the whole run if one step fails. +ignore_failures = ["node"] + +# Print the time in step titles for verbose output. +display_time = true \ No newline at end of file diff --git a/run_once_05-install-pacstall.sh.tmpl b/run_once_05-install-pacstall.sh.tmpl new file mode 100644 index 0000000..f4654f8 --- /dev/null +++ b/run_once_05-install-pacstall.sh.tmpl @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# ============================================================================= +# run_once_05-install-pacstall.sh.tmpl (debian-only) +# Install pacstall: AUR-like package manager for debian/ubuntu. +# Reference: https://pacstall.dev +# +# Steps: +# 1. Install pacstall's apt dependencies via apt +# 2. Run pacstall's official installer (must be root, hence sudo) +# +# Body wrapped in os_family guard: no-op on arch (already has AUR + chaotic). +# ============================================================================= +set -euo pipefail + +log() { printf '\033[1;34m[pacstall]\033[0m %s\n' "$*"; } +die() { printf '\033[1;31m[pacstall ERROR]\033[0m %s\n' "$*" >&2; exit 1; } + +# This script runs as the invoking user; sudo handles elevation. + +{{ if eq .os_family "debian" -}} +# Skip if pacstall is already installed +if command -v pacstall >/dev/null 2>&1; then + log "pacstall already installed: $(pacstall -V 2>/dev/null || echo unknown)" + exit 0 +fi + +# Install pacstall's apt deps first (idempotent — pacstall will skip if present) +log "installing pacstall apt dependencies" +sudo apt-get update -y +sudo apt-get install -y --no-install-recommends \ + sudo wget build-essential unzip git zstd iputils-ping \ + aptitude bubblewrap jq distro-info-data spdx-licenses \ + gettext curl ca-certificates + +# Fetch and run pacstall's official installer. +# It must be invoked as root (sudo). NON_INTERACTIVE=true + /dev/null 2>&1; then + die "pacstall installer ran but pacstall not on PATH" +fi + +log "pacstall installed: $(pacstall -V 2>/dev/null || echo unknown)" + +{{ else -}} +# Not a debian-base box — nothing to do. +log "skipping pacstall install (os_family={{ .os_family }}, not debian)" + +{{ end -}} \ No newline at end of file diff --git a/run_once_20-install-user-packages.sh.tmpl b/run_once_20-install-user-packages.sh.tmpl index 5474366..dae6644 100755 --- a/run_once_20-install-user-packages.sh.tmpl +++ b/run_once_20-install-user-packages.sh.tmpl @@ -62,41 +62,50 @@ if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then ln -sf "$(command -v fdfind)" "$USER_HOME/.local/bin/fd" fi -# Neovim — always install the latest official binary tarball on debian. -# apt's neovim is too old for LazyVim on stable (bookworm), and even on -# trixie we want a known-good version. Detect arch for the right tarball. -ARCH="$(uname -m)" -case "$ARCH" in - x86_64) NVIM_TARBALL="nvim-linux64.tar.gz" ;; - aarch64|arm64) NVIM_TARBALL="nvim-linux-arm64.tar.gz" ;; - *) - die "unsupported arch for neovim tarball: $ARCH" - ;; -esac - -if command -v nvim >/dev/null 2>&1; then - NVIM_VER="$(nvim --version | head -1 | awk '{print $2}' | tr -d 'v')" - NVIM_MAJOR="$(echo "$NVIM_VER" | cut -d. -f1)" - NVIM_MINOR="$(echo "$NVIM_VER" | cut -d. -f2)" - if [[ "${NVIM_MAJOR:-0}" -lt 1 || ("$NVIM_MAJOR" -eq 0 && "${NVIM_MINOR:-0}" -lt 9) ]]; then - log "installed neovim $NVIM_VER too old — replacing with latest from GitHub ($ARCH)" - sudo apt-get remove -y neovim || true +# Neovim — install via pacstall on debian (auto-updated by topgrade via +# built-in pacstall step). Falls back to GitHub tarball if pacstall isn't +# available for some reason. +if command -v pacstall >/dev/null 2>&1; then + if ! command -v nvim >/dev/null 2>&1; then + log "installing neovim via pacstall" + sudo pacstall -I neovim else - log "neovim $NVIM_VER from apt is recent enough — keeping it" - NVIM_TARBALL="" + log "neovim already installed: $(nvim --version | head -1)" fi -fi +else + log "pacstall not installed — falling back to GitHub tarball" + ARCH="$(uname -m)" + case "$ARCH" in + x86_64) NVIM_TARBALL="nvim-linux64.tar.gz" ;; + aarch64|arm64) NVIM_TARBALL="nvim-linux-arm64.tar.gz" ;; + *) + die "unsupported arch for neovim tarball: $ARCH" + ;; + esac -if [[ -n "$NVIM_TARBALL" ]]; then - log "downloading neovim from GitHub ($NVIM_TARBALL)" - cd /tmp - NVIM_LATEST="$(curl -fsSL https://api.github.com/repos/neovim/neovim/releases/latest | grep tag_name | cut -d'"' -f4)" - curl -fL "https://github.com/neovim/neovim/releases/download/${NVIM_LATEST}/${NVIM_TARBALL}" -o nvim.tar.gz - sudo rm -rf /opt/nvim-linux* /usr/local/bin/nvim - sudo tar -xzf nvim.tar.gz -C /opt/ - # The arm64 tarball extracts to nvim-linux-arm64, x86_64 to nvim-linux64. - sudo ln -sf "/opt/$(basename nvim.tar.gz .tar.gz)/bin/nvim" /usr/local/bin/nvim - rm -f nvim.tar.gz + if command -v nvim >/dev/null 2>&1; then + NVIM_VER="$(nvim --version | head -1 | awk '{print $2}' | tr -d 'v')" + NVIM_MAJOR="$(echo "$NVIM_VER" | cut -d. -f1)" + NVIM_MINOR="$(echo "$NVIM_VER" | cut -d. -f2)" + if [[ "${NVIM_MAJOR:-0}" -lt 1 || ("$NVIM_MAJOR" -eq 0 && "${NVIM_MINOR:-0}" -lt 9) ]]; then + log "installed neovim $NVIM_VER too old — replacing with latest from GitHub ($ARCH)" + sudo apt-get remove -y neovim || true + else + log "neovim $NVIM_VER from apt is recent enough — keeping it" + NVIM_TARBALL="" + fi + fi + + if [[ -n "$NVIM_TARBALL" ]]; then + log "downloading neovim from GitHub ($NVIM_TARBALL)" + cd /tmp + NVIM_LATEST="$(curl -fsSL https://api.github.com/repos/neovim/neovim/releases/latest | grep tag_name | cut -d'"' -f4)" + curl -fL "https://github.com/neovim/neovim/releases/download/${NVIM_LATEST}/${NVIM_TARBALL}" -o nvim.tar.gz + sudo rm -rf /opt/nvim-linux* /usr/local/bin/nvim + sudo tar -xzf nvim.tar.gz -C /opt/ + sudo ln -sf "/opt/$(basename nvim.tar.gz .tar.gz)/bin/nvim" /usr/local/bin/nvim + rm -f nvim.tar.gz + fi fi # Verify neovim is reachable (PATH may need /usr/local/bin explicitly for this run)