#!/usr/bin/env bash
# The whole gate, once: build, typecheck, lint, every package's tests, the
# owner scripts' tests, and the packaging suites. A green run
# on a clean tree is remembered by that tree's hash, so the pre-push hook can
# skip a suite that already passed on exactly what is being pushed.
#
#   pnpm verify        run the gate (what CI runs), remember a green clean tree
#   .githooks/verify --check [commit]   exit 0 only if that commit's tree
#                      (default HEAD) is remembered green
set -euo pipefail
cd -- "$(git rev-parse --show-toplevel)"

gitdir="$(git rev-parse --git-dir)"
marker="$gitdir/ghost-verified-tree"
tree="$(git rev-parse 'HEAD^{tree}')"

if [[ "${1:-}" == --check ]]; then
  checked="$(git rev-parse "${2:-HEAD}^{tree}")"
  [[ -f "$marker" && "$(cat "$marker")" == "$checked" ]]
  exit
fi

# Save this run's output for the next failure diagnosis. `--check` stays
# above this line so a probe never truncates the log.
exec > >(tee "$gitdir/ghost-verify-last.log") 2>&1

# The daemon's tsc output is what a checkout's dev launcher runs; a build
# break fails the gate here rather than on the owner's machine.
pnpm build
pnpm typecheck
pnpm lint
pnpm test
# Owner scripts outside the workspace packages.
bun test scripts
# What the gate checks beyond the workspace: the packaging scripts
# (they diff packaging/arch/.SRCINFO against a fresh makepkg render and chain
# the other packaging suites, including the installer this repository
# publishes).
bash packaging/arch/test-check-dependencies.sh

# A dirty tree was not what the suite proved, and neither is a HEAD a peer
# moved mid-run; only the clean tree the run started on earns the marker.
if [[ -z "$(git status --porcelain)" && "$(git rev-parse 'HEAD^{tree}')" == "$tree" ]]; then
  printf '%s\n' "$tree" > "$marker"
else
  rm -f "$marker"
  printf 'verify: green, but the working tree is dirty, so HEAD is not marked verified\n' >&2
fi
