#!/bin/sh
# Smoke test for the release-channel clean-repo gate in build.sh.
#
# Why this exists: the gate only runs on BUILD_CHANNEL=release, so `sh -n`,
# prettier, and dev builds never exercise it — a broken gate ships green. This
# test pins the two properties we depend on:
#   1. assert_clean_repo fails a tree with untracked OR modified files, and
#      passes a clean tree (the porcelain check, not diff-only).
#   2. check_release_gate is invoked AFTER it is defined in build.sh (guards the
#      call-before-definition regression that aborts release builds with exit 127).
#
# Run: sh scripts/test-release-gate.sh
set -eu

SCRIPT_DIR=$(cd "$(dirname "$0")/.." && pwd)
BUILD_SH="${SCRIPT_DIR}/build.sh"
PROJECT_TMP="${SCRIPT_DIR}/tmp"
mkdir -p "${PROJECT_TMP}"
TMP=$(mktemp -d "${PROJECT_TMP}/release-gate-test.XXXXXX")
trap 'rm -rf "${TMP}"' EXIT
fail=0
check() { if [ "$1" = "$2" ]; then echo "ok   - $3"; else echo "FAIL - $3 (want '$2', got '$1')"; fail=1; fi; }

# --- property 2: definition precedes invocation -------------------------------
_def=$(grep -n '^check_release_gate() {' "${BUILD_SH}" | head -1 | cut -d: -f1)
_call=$(grep -n '^[[:space:]]*check_release_gate$' "${BUILD_SH}" | head -1 | cut -d: -f1)
if [ -n "${_def}" ] && [ -n "${_call}" ] && [ "${_call}" -gt "${_def}" ]; then
    echo "ok   - check_release_gate invoked after its definition (def ${_def}, call ${_call})"
else
    echo "FAIL - check_release_gate call/definition order (def '${_def}', call '${_call}')"; fail=1
fi

# --- property 1: assert_clean_repo semantics ----------------------------------
# Extract the helper from build.sh and exercise it against real temp git repos.
sed -n '/^assert_clean_repo() {/,/^}/p' "${BUILD_SH}" > "${TMP}/fn.sh"
. "${TMP}/fn.sh"

mkrepo() { d="${TMP}/$1"; mkdir -p "$d"; git -C "$d" init -q; git -C "$d" config user.email t@t; git -C "$d" config user.name t;
    echo base > "$d/file"; git -C "$d" add file; git -C "$d" commit -qm init; printf '%s' "$d"; }

clean=$(mkrepo clean)
_release_errors=0; assert_clean_repo clean "${clean}"; check "${_release_errors}" 0 "clean repo passes"

untracked=$(mkrepo untracked); : > "${untracked}/stray.txt"
_release_errors=0; assert_clean_repo untracked "${untracked}"; check "${_release_errors}" 1 "untracked file fails (porcelain catches it)"

modified=$(mkrepo modified); echo changed > "${modified}/file"
_release_errors=0; assert_clean_repo modified "${modified}"; check "${_release_errors}" 1 "modified tracked file fails"

_release_errors=0; assert_clean_repo nogit "${TMP}/does-not-exist"; check "${_release_errors}" 0 "non-git path is skipped"

[ "${fail}" -eq 0 ] && echo "PASS: release gate self-test" || { echo "FAILED"; exit 1; }
