#!/bin/bash
# cmux pre-commit hook
# Installed by ./scripts/setup.sh as a clone-local copy outside the checkout.
# Normalizes cmux.xcodeproj/project.pbxproj when staged so Xcode's
# nondeterministic section reordering never reaches a commit.
set -euo pipefail

HOOK_DIR="$(cd "${BASH_SOURCE[0]%/*}" && pwd -P)"
PYTHON_PATH_FILE="$HOOK_DIR/python3-path"
if [[ ! -r "$PYTHON_PATH_FILE" ]] || ! IFS= read -r PYTHON3_BIN < "$PYTHON_PATH_FILE" \
    || [[ "$PYTHON3_BIN" != /* ]] || [[ ! -x "$PYTHON3_BIN" ]]; then
    echo "pre-commit: trusted Python interpreter metadata is missing or invalid; rerun scripts/install-git-hooks.sh." >&2
    exit 1
fi
REGISTRY_VALIDATOR="$HOOK_DIR/validate_test_execution_registry.py"
PBX_NORMALIZER="$HOOK_DIR/normalize-pbxproj.py"
if [[ ! -f "$REGISTRY_VALIDATOR" || ! -f "$PBX_NORMALIZER" ]]; then
    echo "pre-commit: trusted helper copies are missing; rerun scripts/install-git-hooks.sh." >&2
    exit 1
fi

REPO_ROOT="$(git rev-parse --show-toplevel)"
PBXPROJ="cmux.xcodeproj/project.pbxproj"

cd "$REPO_ROOT"

# Register new Python tests that a workflow already runs, so adding a test and
# its ci-guards.yml step is all a commit needs. Best effort: CI still validates.
REGISTRY="tests/test-execution.toml"
if git diff --cached --name-only --diff-filter=ACMRT | grep -Eq '^(tests/test_[^/]+\.py|\.github/workflows/.+)$' \
    && git diff --quiet -- "$REGISTRY"; then
    "$PYTHON3_BIN" -I "$REGISTRY_VALIDATOR" --repo-root "$REPO_ROOT" --write >/dev/null 2>&1 || true
    if ! git diff --quiet -- "$REGISTRY"; then
        git add "$REGISTRY"
        echo "pre-commit: registered new tests in $REGISTRY"
    fi
fi

# Only normalize when the pbxproj is part of this commit.
if ! git diff --cached --name-only --diff-filter=ACMRT | grep -Fxq "$PBXPROJ"; then
    exit 0
fi

# Refuse to normalize when the working-tree pbxproj has unstaged changes.
# Otherwise the `git add` at the end would silently stage hunks the
# user deliberately left out of this commit.
if ! git diff --quiet -- "$PBXPROJ"; then
    echo "pre-commit: $PBXPROJ has unstaged changes; cannot safely normalize." >&2
    echo "Either stage the whole file (git add $PBXPROJ) or stash the unstaged hunks before committing." >&2
    exit 1
fi

"$PYTHON3_BIN" -I "$PBX_NORMALIZER" "$PBXPROJ"

# If the normalizer rewrote the file, restage so the commit captures
# the normalized form. (Working tree had no unstaged changes per the
# guard above, so anything that changed is purely from normalization.)
if ! git diff --quiet -- "$PBXPROJ"; then
    git add "$PBXPROJ"
fi
