From 0286cc6db6e41b04e3e1f694d0036e95ec265387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Wed, 12 Aug 2026 20:54:59 +0000 Subject: [PATCH] port the Neovim section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kept as it worked — upstream tarball, symlink, a config repo cloned into the account's ~/.config/nvim — with the defects fixed rather than the design changed. The one that mattered: the asset name. Neovim publishes nvim-linux-x86_64.tar.gz and nvim-linux-arm64.tar.gz. The original mapped aarch64 to "aarch64", which is not a name Neovim has ever published, so on an arm machine it downloaded a 404 and handed the HTML error page to tar. Verified against the release API — same class of bug as lazygit's hardcoded x86_64, and the second one this port has found in an arch mapping. The tarball is now checked with `tar -tzf` before anything is removed, so a bad download says what is wrong instead of failing inside tar. The rest: The tarball went to the working directory, via `curl -LO`, and stayed there if tar failed. It goes to /tmp and is cleaned up. The old /opt install was removed before the new one was known to be good. The download and its sanity check now come first, so a failed fetch leaves the working copy alone. The custom-repo option defaulted to git@gogs:andrepadez/nvim-config.git — a private repository nobody else can clone, and the same mistake as defaulting the login server to a personal headscale. No default now. git clone runs from /, for the reason git config does: the script's working directory is usually under the invoking user's home at 0750, which the target account cannot stat. The ~/.config/nvim/.git removal is now conditional on it being the starter. That is a template and dropping its history is right; a config of the user's own is something they will want to keep pulling. An existing config is left alone and said so, rather than moved to a .bak that silently overwrote the previous .bak. The PATH line the original appended to .zshrc is gone. /usr/local/bin/nvim is symlinked and already on PATH, so it was doing nothing except growing the file on every run. Verified on this host (already current, existing config left alone) and against a fresh account (LazyVim starter cloned, owned correctly, .git dropped). Co-Authored-By: Claude Opus 5 (1M context) --- scripts/setup/machine-setup/lib/dev.sh | 71 ++++++++++++++ scripts/setup/machine-setup/machine-setup.sh | 98 +++++++++++++++++++- 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/scripts/setup/machine-setup/lib/dev.sh b/scripts/setup/machine-setup/lib/dev.sh index 22f5f61c..bb375f2d 100644 --- a/scripts/setup/machine-setup/lib/dev.sh +++ b/scripts/setup/machine-setup/lib/dev.sh @@ -99,3 +99,74 @@ set_login_shell() { grep -qxF "$shell" /etc/shells || echo "$shell" >>/etc/shells chsh -s "$shell" "$USERNAME" } + +# ----------------------------------------------------------------------------- +# Neovim +# ----------------------------------------------------------------------------- +# +# From the upstream tarball rather than the distribution, which ships Neovim +# years behind — Ubuntu 24.04 has 0.9 where upstream is on 0.12, and LazyVim +# requires 0.9+ with most plugins wanting newer. +# +# The asset names are x86_64 and arm64. The original mapped aarch64 to +# "aarch64", which is not a name Neovim publishes: on an arm machine it +# downloaded a 404 and tar failed on the HTML error page. +nvim_asset() { + case "$ARCH" in + amd64) echo x86_64 ;; + arm64) echo arm64 ;; + esac +} + +nvim_installed_version() { nvim --version 2>/dev/null | awk 'NR == 1 { print $2 }'; } + +nvim_latest_version() { + curl -fsSL https://api.github.com/repos/neovim/neovim/releases/latest 2>/dev/null | + jq -r '.tag_name // empty' +} + +# Downloaded to /tmp, not to whatever directory the script was launched from — +# the original used `curl -LO`, which drops the tarball beside the script and +# leaves it there if tar fails. +# +# The old install is removed only after the download has succeeded, so a failed +# fetch leaves the working copy alone. +nvim_install() { + local asset tarball dest + asset="$(nvim_asset)" + tarball="/tmp/nvim-linux-${asset}.tar.gz" + dest="/opt/nvim-linux-${asset}" + + curl -fsSL -o "$tarball" \ + "https://github.com/neovim/neovim/releases/latest/download/nvim-linux-${asset}.tar.gz" || return 1 + + # A 404 comes back as an HTML page, and tar's failure on it is unhelpful. + # Checking here names the real problem. + tar -tzf "$tarball" >/dev/null 2>&1 || { + rm -f "$tarball" + warn "the download is not a tarball — the release asset may have been renamed" + return 1 + } + + rm -rf "$dest" + tar -C /opt -xzf "$tarball" + rm -f "$tarball" + ln -sf "${dest}/bin/nvim" /usr/local/bin/nvim +} + +# Clone a Neovim config into the account's ~/.config/nvim. +# +# From `cd /` for the same reason git config does: the script's working directory +# is usually under the invoking user's home at 0750, which the target account +# cannot stat, and git fails there before it does anything useful. +nvim_clone_config() { + local repo="$1" dest="${USER_HOME}/.config/nvim" + + install -d -m 0755 -o "$USERNAME" -g "$USERNAME" "${USER_HOME}/.config" + (cd / && sudo -H -u "$USERNAME" git clone --depth 1 "$repo" "$dest" >/dev/null 2>&1) || return 1 + + # The starter is a template, not something to track. Left in place for a + # config of the user's own, which they will want to keep pulling. + [[ "$repo" == *LazyVim/starter* ]] && sudo -u "$USERNAME" rm -rf "${dest}/.git" + return 0 +} diff --git a/scripts/setup/machine-setup/machine-setup.sh b/scripts/setup/machine-setup/machine-setup.sh index 6f07fb36..673ebd23 100755 --- a/scripts/setup/machine-setup/machine-setup.sh +++ b/scripts/setup/machine-setup/machine-setup.sh @@ -1853,13 +1853,109 @@ EOF step_ok fi +# ============================================================================= +# 24. Neovim +# ============================================================================= + +step "Neovim" +if ! skip; then + NVIM_NOW="$(nvim_installed_version)" + NVIM_LATEST="$(nvim_latest_version)" + + echo "" + info "Neovim — from upstream, not from the distribution" + echo " installed: ${NVIM_NOW:-not installed}" + echo " latest: ${NVIM_LATEST:-could not reach github}" + echo " Ubuntu ships a Neovim years behind upstream, and LazyVim wants a" + echo " recent one, so this takes the release tarball." + + if [[ -z "$NVIM_LATEST" ]]; then + warn "cannot reach the release API — leaving Neovim alone" + SUMMARY+=("Neovim: skipped, could not reach github") + elif [[ "$NVIM_NOW" == "$NVIM_LATEST" ]]; then + echo " already on the latest release, nothing to do" + SUMMARY+=("Neovim: already ${NVIM_NOW}") + else + echo "" + if confirm "${NVIM_NOW:+Upgrade}${NVIM_NOW:-Install} Neovim ${NVIM_LATEST}?"; then + if nvim_install; then + ok "neovim $(nvim_installed_version) at /usr/local/bin/nvim" + SUMMARY+=("Neovim: $(nvim_installed_version)") + else + warn "the Neovim install did not complete" + ERRORS+=("Neovim: install failed") + SUMMARY+=("Neovim: install FAILED") + fi + else + warn "skipped by request" + SUMMARY+=("Neovim: SKIPPED by request") + fi + fi + + # ── configuration ── + if command -v nvim &>/dev/null && id "$USERNAME" &>/dev/null; then + NVIM_CONFIG="${USER_HOME}/.config/nvim" + + if [[ -d "$NVIM_CONFIG" ]]; then + echo "" + echo " ${USERNAME} already has a Neovim config at ${NVIM_CONFIG}" + SUMMARY+=("Neovim: existing config left alone") + else + echo "" + info "Neovim configuration for ${USERNAME}" + echo " [1] LazyVim starter — a maintained set of defaults, sensible to" + echo " build on and easy to remove" + echo " [2] a git repository of your own" + echo " [3] nothing — plain Neovim" + echo "" + + NVIM_REPO="" + NVIM_PICK="" + while [[ -z "$NVIM_PICK" ]]; do + if ! read -rp " Which one? (1/2/3) [1]: " NVIM_CHOICE; then + echo "" + fail "No answer." + fi + case "${NVIM_CHOICE:-1}" in + 1) + NVIM_REPO="https://github.com/LazyVim/starter" + NVIM_PICK=config + ;; + 2) + # No default. The original suggested its author's own private repo, + # which nobody else can clone. + read -rp " Repository URL: " NVIM_REPO || fail "No answer." + [[ -n "$NVIM_REPO" ]] && NVIM_PICK=config || warn "A repository URL is needed." + ;; + 3) NVIM_PICK=none ;; + *) warn "Pick 1, 2 or 3." ;; + esac + done + + if [[ "$NVIM_PICK" == config ]]; then + if nvim_clone_config "$NVIM_REPO"; then + ok "config cloned to ${NVIM_CONFIG}" + SUMMARY+=("Neovim: config from ${NVIM_REPO}") + else + warn "could not clone ${NVIM_REPO}" + ERRORS+=("Neovim: cloning ${NVIM_REPO} failed") + SUMMARY+=("Neovim: config clone FAILED") + fi + else + SUMMARY+=("Neovim: no config, plain Neovim") + fi + fi + fi + step_ok +fi + # ============================================================================= # NOT PORTED YET # ============================================================================= # # Sections still to move across from scripts/setup-old/setup-ubuntu.sh, in order: # -# neovim · js runtimes · +# js runtimes · # dev tools · ufw · zshrc # # And one that is new rather than ported, to come last of all: