#!/usr/bin/env bash
# `git worktree prune` is repo-wide. Racing a concurrent `worktree add`, a bare
# prune deletes the new worktree's admin entry while leaving its files behind:
# the session loses its registration mid-work, commits fail with "not a git
# repository", and no salvage ref is ever written because nothing was reaped.
set -uo pipefail

REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)"
fail=0
t() { if [ "$2" = "$3" ]; then printf 'ok    %s\n' "$1"; else printf 'FAIL  %s: expected %s, got %s\n' "$1" "$2" "$3"; fail=$((fail + 1)); fi; }

# 1. Behavioral: a freshly registered worktree must survive a prune even when its
#    directory is momentarily absent, which is what an in-flight `add` looks like.
work="$(mktemp -d)"; trap 'rm -rf "$work"' EXIT
export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t
git init --quiet "$work/repo"
git -C "$work/repo" commit --quiet --allow-empty -m init
git -C "$work/repo" worktree add --quiet --detach "$work/repo/.worktrees/fresh" >/dev/null 2>&1
mv "$work/repo/.worktrees/fresh" "$work/inflight"

git -C "$work/repo" worktree prune --expire=1.hour.ago 2>/dev/null
t "a time-gated prune keeps a seconds-old registration" \
  "present" "$([ -d "$work/repo/.git/worktrees/fresh" ] && echo present || echo gone)"

git -C "$work/repo" worktree prune 2>/dev/null
t "a bare prune is what destroys it (the defect this guards)" \
  "gone" "$([ -d "$work/repo/.git/worktrees/fresh" ] && echo present || echo gone)"

# 2. Source guard: no shipped caller may use the bare form again.
# Quoted text is stripped first: the phrase also appears inside error messages,
# which are not invocations.
offenders=$(grep -rn 'worktree prune' \
  --include='*.sh' --include='*.mjs' --include='*.py' \
  "$REPO/modules" "$REPO/lib" "$REPO/packaging" 2>/dev/null \
  | grep -v '/tests\?/' \
  | sed 's/"[^"]*"//g; s/'"'"'[^'"'"']*'"'"'//g' \
  | grep 'worktree prune' \
  | grep -v -- '--expire' || true)
if [ -n "$offenders" ]; then
  printf 'FAIL  a shipped caller still prunes without --expire:\n%s\n' "$offenders"
  fail=$((fail + 1))
else
  printf 'ok    every shipped prune caller is time-gated\n'
fi

[ "$fail" = 0 ] || { printf '\n%d failed\n' "$fail"; exit 1; }
printf '\nall passed\n'
