#!/bin/sh
# Runs the same checks as CI against the exact clean commit being pushed.

checks_required=0
while read -r local_ref local_sha remote_ref _remote_sha; do
    case "$local_sha" in
        *[!0]*) ;;
        *) continue ;;
    esac

    case "$remote_ref" in
        refs/tags/*) continue ;;
    esac

    checks_required=1
    if ! pushed_commit=$(git rev-parse --verify "${local_sha}^{commit}" 2>/dev/null); then
        echo "pre-push hook: ${local_ref} does not resolve to a commit." >&2
        exit 1
    fi
    if ! head_commit=$(git rev-parse --verify HEAD 2>/dev/null); then
        echo "pre-push hook: could not resolve HEAD." >&2
        exit 1
    fi
    if [ "$pushed_commit" != "$head_commit" ]; then
        echo "pre-push hook: ${local_ref} does not point to the checked HEAD commit." >&2
        echo "  Check out the commit being pushed so just check validates that exact object." >&2
        exit 1
    fi
done

if [ "$checks_required" -eq 0 ]; then
    exit 0
fi

if ! worktree_status=$(git status --porcelain --untracked-files=all); then
    echo "pre-push hook: could not inspect the worktree." >&2
    exit 1
fi
if [ -n "$worktree_status" ]; then
    echo "pre-push hook: the worktree has tracked or untracked changes." >&2
    echo "  Commit, stash, or remove them before pushing so checks match the pushed commit." >&2
    exit 1
fi

if ! command -v just >/dev/null 2>&1; then
    echo "pre-push hook: 'just' is required. Install it with 'brew install just'." >&2
    exit 127
fi

# Git exports GIT_DIR to hooks, as an absolute path from a linked worktree, so
# tools that run git in another repository (SwiftPM checkouts, test fixtures)
# would act on this one. Clear what git clears when it enters another
# repository: its repository-local variables, keeping command-line config.
if ! local_env_vars=$(git rev-parse --local-env-vars); then
    echo "pre-push hook: could not list git's repository-local variables." >&2
    exit 1
fi
for var in $local_env_vars; do
    case "$var" in
        GIT_CONFIG_PARAMETERS | GIT_CONFIG_COUNT) ;;
        *) unset "$var" ;;
    esac
done

just check
