#!/bin/bash # test/probe_stow.sh # # Verifies that each package the Makefile stows actually resolves and that # stow can create all symlinks into the target without conflicts. # # This is a DRY RUN: it uses `stow --simulate` and creates no real symlinks. # It catches bugs like `stow nvim` for a non-existent `nvim/` package. # # Usage: # bash test/probe_stow.sh # probe every stow-able package # bash test/probe_stow.sh ... # probe specific packages set -uo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$REPO_ROOT" || exit 1 # A stow-able package is any tracked top-level directory that contains a # dot-prefixed config subtree (or a dot-prefixed top-level file/dir). tracked_basenames() { git ls-files | awk -F/ 'NF>1 {print $1}' | sort -u } is_stowable() { local pkg="$1" [[ -d "$REPO_ROOT/$pkg" ]] || return 1 # stow needs at least one dot-prefixed entry at the package root git ls-files "$pkg/" | grep -qE "^$pkg/\." || return 1 } # Determine which packages to probe. PACKAGES=() if [[ $# -eq 0 ]]; then while IFS= read -r b; do [[ -z "$b" ]] && continue is_stowable "$b" && PACKAGES+=("$b") done < <(tracked_basenames) else PACKAGES=("$@") fi if [[ ${#PACKAGES[@]} -eq 0 ]]; then echo "probe_stow.sh: no stow-able packages found" >&2 exit 1 fi echo "== Probing stow packages: ${PACKAGES[*]} ==" FAIL=0 ERR_LOG="$(mktemp -t probe_stow.XXXXXX)" cleanup() { rm -f "$ERR_LOG"; } trap cleanup EXIT for pkg in "${PACKAGES[@]}"; do echo "--- stow --simulate: $pkg ---" if stow --simulate --verbose=1 --dir="$REPO_ROOT" --target="$REPO_ROOT" "$pkg" >/dev/null 2>"$ERR_LOG"; then echo "ok: stow --simulate '$pkg' resolved without conflicts" else echo "FAIL: stow --simulate '$pkg'" sed 's/^/ /' "$ERR_LOG" FAIL=$((FAIL+1)) fi done # Cross-check: does the Makefile stow anything that is NOT in our package set? echo "== Checking Makefile stow targets against stow-able packages ==" make_pkgs="$(grep -P '^\t' Makefile | grep -oE 'stow [A-Za-z0-9_-]+' | awk '{print $2}' | sort -u)" for mp in $make_pkgs; do if is_stowable "$mp"; then echo "ok: Makefile 'stow $mp' matches a stow-able package" else echo "FAIL: Makefile 'stow $mp' does not match a stow-able package" FAIL=$((FAIL+1)) fi done echo echo "==============================================" echo "probe_stow.sh: $(( ${#PACKAGES[@]} + $(printf '%s\n' $make_pkgs | grep -c . || true) )) checks, $FAIL failed" echo "==============================================" [[ $FAIL -eq 0 ]]