174 lines
6.1 KiB
Bash
Executable File
174 lines
6.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
|
|
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
|
|
|
|
TEMP_HOME="$(mktemp -d)"
|
|
trap 'rm -rf "$TEMP_HOME"' EXIT
|
|
|
|
echo "Running install.sh..."
|
|
HOME="$TEMP_HOME" bash "$REPO_ROOT/scripts/install.sh" > /dev/null
|
|
|
|
echo ""
|
|
echo "--- providers/claude-code/ → ~/.claude/ ---"
|
|
while IFS= read -r -d '' src; do
|
|
rel="${src#"$REPO_ROOT/providers/claude-code/"}"
|
|
# provider-manifest.sh is sourced by install.sh, not deployed to ~/.claude/
|
|
[[ "$rel" == "provider-manifest.sh" ]] && continue
|
|
dest="$TEMP_HOME/.claude/$rel"
|
|
if diff -q "$src" "$dest" > /dev/null 2>&1; then
|
|
pass "$rel deployed and matches source"
|
|
else
|
|
fail "$rel — missing or differs from source"
|
|
fi
|
|
done < <(find "$REPO_ROOT/providers/claude-code" -type f -print0)
|
|
|
|
echo ""
|
|
echo "--- core/ → ~/.claude/core/ ---"
|
|
while IFS= read -r -d '' src; do
|
|
rel="${src#"$REPO_ROOT/core/"}"
|
|
dest="$TEMP_HOME/.claude/core/$rel"
|
|
if diff -q "$src" "$dest" > /dev/null 2>&1; then
|
|
pass "$rel deployed and matches source"
|
|
else
|
|
fail "$rel — missing or differs from source"
|
|
fi
|
|
done < <(find "$REPO_ROOT/core" -type f -print0)
|
|
|
|
echo ""
|
|
echo "--- no orphaned files in core/ ---"
|
|
while IFS= read -r -d '' deployed; do
|
|
rel="${deployed#"$TEMP_HOME/.claude/core/"}"
|
|
src="$REPO_ROOT/core/$rel"
|
|
if [[ -f "$src" ]]; then
|
|
pass "core/$rel has a source file"
|
|
else
|
|
fail "core/$rel is orphaned — deleted from source but still deployed"
|
|
fi
|
|
done < <(find "$TEMP_HOME/.claude/core" -type f -print0)
|
|
|
|
echo ""
|
|
echo "--- skills deployed to ~/.agents/skills/ ---"
|
|
while IFS= read -r -d '' src_skill; do
|
|
skill_name="$(basename "$src_skill")"
|
|
dest_skill="$TEMP_HOME/.agents/skills/$skill_name"
|
|
if [[ -d "$dest_skill" ]]; then
|
|
pass "$skill_name deployed to ~/.agents/skills/"
|
|
else
|
|
fail "$skill_name missing from ~/.agents/skills/"
|
|
fi
|
|
done < <(find "$REPO_ROOT/.agents/skills" -mindepth 1 -maxdepth 1 -type d -print0)
|
|
|
|
echo ""
|
|
echo "--- skill files match source ---"
|
|
while IFS= read -r -d '' src; do
|
|
rel="${src#"$REPO_ROOT/.agents/skills/"}"
|
|
dest="$TEMP_HOME/.agents/skills/$rel"
|
|
if diff -q "$src" "$dest" > /dev/null 2>&1; then
|
|
pass "skills/$rel matches source"
|
|
else
|
|
fail "skills/$rel — missing or differs from source"
|
|
fi
|
|
done < <(find "$REPO_ROOT/.agents/skills" -type f -print0)
|
|
|
|
echo ""
|
|
echo "--- provider adapter: ~/.claude/skills/ is a symlink to ~/.agents/skills/ ---"
|
|
adapter="$TEMP_HOME/.claude/skills"
|
|
skills_canonical="$TEMP_HOME/.agents/skills"
|
|
if [[ -L "$adapter" ]]; then
|
|
resolved="$(readlink "$adapter")"
|
|
if [[ "$resolved" == "$skills_canonical" ]]; then
|
|
pass "~/.claude/skills → ~/.agents/skills (correct target)"
|
|
else
|
|
fail "~/.claude/skills symlink points to wrong target: $resolved"
|
|
fi
|
|
else
|
|
fail "~/.claude/skills is not a symlink"
|
|
fi
|
|
|
|
echo ""
|
|
echo "--- skills correctly replaced on second install (no double-nesting) ---"
|
|
skill_name="$(basename "$(find "$REPO_ROOT/.agents/skills" -mindepth 1 -maxdepth 1 -type d | head -1)")"
|
|
nested="$TEMP_HOME/.agents/skills/$skill_name/$skill_name"
|
|
if [[ -d "$nested" ]]; then
|
|
fail "$skill_name/$skill_name exists — skill was nested instead of replaced"
|
|
else
|
|
pass "$skill_name not double-nested after second install"
|
|
fi
|
|
|
|
echo ""
|
|
echo "--- user skills preserved after install (merge, not wipe) ---"
|
|
TEMP_HOME2="$(mktemp -d)"
|
|
trap 'rm -rf "$TEMP_HOME2"' EXIT
|
|
# Pre-create a user skill not in the source
|
|
mkdir -p "$TEMP_HOME2/.agents/skills/my-custom-skill"
|
|
echo "custom" > "$TEMP_HOME2/.agents/skills/my-custom-skill/SKILL.md"
|
|
HOME="$TEMP_HOME2" bash "$REPO_ROOT/scripts/install.sh" > /dev/null
|
|
if [[ -f "$TEMP_HOME2/.agents/skills/my-custom-skill/SKILL.md" ]]; then
|
|
pass "pre-existing user skill preserved after install"
|
|
else
|
|
fail "pre-existing user skill was wiped by install"
|
|
fi
|
|
|
|
echo ""
|
|
echo "--- warning emitted when adapter target is a real directory ---"
|
|
TEMP_HOME3="$(mktemp -d)"
|
|
trap 'rm -rf "$TEMP_HOME3"' EXIT
|
|
mkdir -p "$TEMP_HOME3/.claude/skills/some-user-skill"
|
|
output="$(HOME="$TEMP_HOME3" bash "$REPO_ROOT/scripts/install.sh" 2>&1)"
|
|
if echo "$output" | grep -q "Warning"; then
|
|
pass "warning emitted when ~/.claude/skills exists as real directory"
|
|
else
|
|
fail "no warning when ~/.claude/skills is a real directory"
|
|
fi
|
|
if [[ -d "$TEMP_HOME3/.claude/skills/some-user-skill" ]]; then
|
|
pass "real directory left intact when warning emitted"
|
|
else
|
|
fail "real directory was destroyed despite warning"
|
|
fi
|
|
|
|
echo ""
|
|
echo "--- idempotency: second run state is correct ---"
|
|
HOME="$TEMP_HOME" bash "$REPO_ROOT/scripts/install.sh" > /dev/null 2>&1 \
|
|
&& pass "second run exits zero" \
|
|
|| fail "second run failed"
|
|
|
|
# skill files still match source after second run
|
|
while IFS= read -r -d '' src; do
|
|
rel="${src#"$REPO_ROOT/.agents/skills/"}"
|
|
dest="$TEMP_HOME/.agents/skills/$rel"
|
|
if diff -q "$src" "$dest" > /dev/null 2>&1; then
|
|
pass "idempotent: skills/$rel correct after second install"
|
|
else
|
|
fail "idempotent: skills/$rel corrupted after second install"
|
|
fi
|
|
done < <(find "$REPO_ROOT/.agents/skills" -type f -print0)
|
|
|
|
# no double-nesting after second run
|
|
while IFS= read -r -d '' skill_dir; do
|
|
skill_name="$(basename "$skill_dir")"
|
|
nested="$TEMP_HOME/.agents/skills/$skill_name/$skill_name"
|
|
if [[ -d "$nested" ]]; then
|
|
fail "idempotent: $skill_name double-nested after second install"
|
|
else
|
|
pass "idempotent: $skill_name not double-nested after second install"
|
|
fi
|
|
done < <(find "$REPO_ROOT/.agents/skills" -mindepth 1 -maxdepth 1 -type d -print0)
|
|
|
|
# symlink still correct after second run
|
|
adapter="$TEMP_HOME/.claude/skills"
|
|
if [[ -L "$adapter" ]] && [[ "$(readlink "$adapter")" == "$TEMP_HOME/.agents/skills" ]]; then
|
|
pass "idempotent: ~/.claude/skills symlink intact after second install"
|
|
else
|
|
fail "idempotent: ~/.claude/skills symlink broken after second install"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Results: $PASS passed, $FAIL failed"
|
|
[[ $FAIL -eq 0 ]]
|