1
0
Fork 0
gnu-plus-dotfiles/run_once_20-install-user-packages.sh.tmpl
rain 6771aff6a6 Fix run_once_20 neovim install for aarch64 + always-fallback
Two bugs hit on rye:

1. neovim tarball URL hardcoded to nvim-linux64.tar.gz (x86_64 only).
   On aarch64 boxes (rye is arm64), curl would 404 the tarball, the
   unpack would create a binary that won't run, or apt's bundled
   neovim might not even be installed.

2. The 'apt's neovim is too old' branch only ran if apt had
   successfully installed an old neovim. If apt didn't install
   neovim at all (or installed a recent enough version), the
   tarball fallback never triggered. On rye, the script reached
   the final 'nvim --version' verification line and crashed with
   'command not found'.

Fix:
- Detect arch via uname -m, map to correct tarball name
  (x86_64 -> nvim-linux64.tar.gz, aarch64 -> nvim-linux-arm64.tar.gz)
- If command -v nvim returns false at all, skip the version check
  entirely and go straight to the GitHub tarball
- If apt's neovim IS recent enough (>= 0.9), keep it and skip the
  tarball
- Final 'nvim --version' verification preceded by a PATH-ensure
  for /usr/local/bin in case the freshly-installed tarball binary
  isn't yet on PATH for this script's environment

Verified template renders cleanly on arch.
2026-06-21 20:29:09 -04:00

189 lines
No EOL
6.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# =============================================================================
# run_once_20-install-user-packages.sh.tmpl
# Install zsh, tmux, neovim, fastfetch, plus the modern CLI replacements
# the .zshrc aliases depend on (bat, btop, eza, fzf, fd, ripgrep, zoxide,
# starship, lazygit, yt-dlp, etc.)
#
# Also: install oh-my-zsh, zsh-autosuggestions, zsh-syntax-highlighting,
# zsh-history-substring-search.
#
# Runs as the unprivileged user, but uses sudo for system packages.
# =============================================================================
set -euo pipefail
log() { printf '\033[1;34m[packages]\033[0m %s\n' "$*"; }
die() { printf '\033[1;31m[packages ERROR]\033[0m %s\n' "$*" >&2; exit 1; }
USER_HOME="${HOME:-$(eval echo "~$(whoami)")}"
ZSH_CUSTOM="${ZSH_CUSTOM:-$USER_HOME/.oh-my-zsh/custom}"
{{ if eq .os_family "arch" -}}
# ----------------------------- ARCH ---------------------------------------
log "pacman -Syu"
sudo pacman -Syu --noconfirm
PACMAN_PKGS=(
zsh tmux neovim git base-devel
bat btop htop fastfetch
eza fzf fd ripgrep zoxide starship
lazygit yt-dlp jq
unzip p7zip
openssh
)
log "installing pacman packages"
sudo pacman -S --needed --noconfirm "${PACMAN_PKGS[@]}"
{{ else if eq .os_family "debian" -}}
# ----------------------------- DEBIAN --------------------------------------
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update -y
sudo apt-get upgrade -y
APT_PKGS=(
zsh tmux git build-essential
bat btop htop fastfetch
eza fzf fd-find ripgrep zoxide starship
lazygit yt-dlp jq
unzip p7zip
openssh-client
ca-certificates curl wget
)
log "installing apt packages"
sudo apt-get install -y --no-install-recommends "${APT_PKGS[@]}"
# 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
log "symlinking fdfind -> fd in ~/.local/bin"
mkdir -p "$USER_HOME/.local/bin"
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
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/
# 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
fi
# Verify neovim is reachable (PATH may need /usr/local/bin explicitly for this run)
if ! command -v nvim >/dev/null 2>&1 && [[ -x /usr/local/bin/nvim ]]; then
export PATH="/usr/local/bin:$PATH"
fi
{{ else -}}
die "unsupported os_family: {{ .os_family }}"
{{ end -}}
# --------------------------- OH-MY-ZSH -------------------------------------
if [[ ! -d "$USER_HOME/.oh-my-zsh" ]]; then
log "installing oh-my-zsh (unattended)"
RUNZSH=no CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
else
log "oh-my-zsh already installed"
fi
# zsh plugins (loaded by .zshrc)
install_zsh_plugin() {
local repo="$1" target="$2"
if [[ -d "$target" ]]; then
log "plugin already present: $target"
else
log "cloning plugin: $repo"
git clone --depth 1 "https://github.com/$repo.git" "$target"
fi
}
install_zsh_plugin zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
install_zsh_plugin zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
install_zsh_plugin zsh-users/zsh-history-substring-search "$ZSH_CUSTOM/plugins/zsh-history-substring-search"
# --------------------------- TPM (tmux plugin manager) ---------------------
if [[ ! -d "$USER_HOME/.tmux/plugins/tpm" ]]; then
log "cloning tmux plugin manager"
mkdir -p "$USER_HOME/.tmux/plugins"
git clone --depth 1 https://github.com/tmux-plugins/tpm "$USER_HOME/.tmux/plugins/tpm"
else
log "tpm already installed"
fi
# --------------------------- Maple Mono NF font ----------------------------
# nvim init.lua references "Maple Mono NF". Install it so the default font works.
# Pin Maple-font version. Bump manually if a release breaks things.
MAPLE_FONT_VERSION="v7.9"
if fc-list 2>/dev/null | grep -qi "Maple Mono NF"; then
log "Maple Mono NF already installed"
else
{{ if eq .os_family "arch" -}}
log "installing maplemono-nf-cn from AUR (via paru)"
paru -S --needed --noconfirm maplemono-nf-cn
{{ else if eq .os_family "debian" -}}
log "downloading MapleMono-NF.zip from subframe7536/Maple-font $MAPLE_FONT_VERSION"
FONT_DIR="$USER_HOME/.local/share/fonts/maple-mono-nf"
mkdir -p "$FONT_DIR"
TMP_ZIP="$(mktemp /tmp/maple-font.XXXXXX.zip)"
if curl -fL --retry 3 \
"https://github.com/subframe7536/Maple-font/releases/download/${MAPLE_FONT_VERSION}/MapleMono-NF.zip" \
-o "$TMP_ZIP"; then
log "extracting font files"
unzip -q -o "$TMP_ZIP" -d "$FONT_DIR"
rm -f "$TMP_ZIP"
log "running fc-cache"
fc-cache -fv >/dev/null
else
log "WARNING: failed to download Maple Mono NF — nvim will warn about missing font"
log "manual install: https://github.com/subframe7536/Maple-font"
rm -f "$TMP_ZIP"
fi
{{ else -}}
log "WARNING: font install not configured for os_family={{ .os_family }}"
{{ end -}}
fi
# --------------------------- set zsh as default shell ---------------------
USER_SHELL="$(getent passwd "$(whoami)" | cut -d: -f7)"
if [[ "$USER_SHELL" != "$(command -v zsh)" ]]; then
log "changing login shell to zsh"
chsh -s "$(command -v zsh)"
else
log "zsh already the login shell"
fi
log "all user packages installed"
zsh --version
nvim --version | head -1
tmux -V