#!/usr/bin/env bash
# Block a push that would publish internal infrastructure.
#
# This repository is push-mirrored to a public host on every push, on EVERY
# branch. CI runs the same scan, but CI runs AFTER the push -- by which time
# the commit is already public and deleting the branch does not unpublish it.
# This hook is the only check that happens while the leak is still local.
#
# Install (once per clone; git does not install hooks from a repository):
#     git config core.hooksPath tools/ci
#
# Bypass is `git push --no-verify`, and it should be treated as a decision
# rather than a shortcut: everything this catches is permanent once pushed.
set -uo pipefail

repo_root=$(git rev-parse --show-toplevel)
scan="$repo_root/ci/leak-scan.sh"
[ -x "$scan" ] || { echo "pre-push: $scan missing or not executable" >&2; exit 1; }

z=0000000000000000000000000000000000000000
status=0

while read -r _local_ref local_sha _remote_ref remote_sha; do
  [ "$local_sha" = "$z" ] && continue          # branch deletion: nothing to scan

  if [ "$remote_sha" = "$z" ]; then
    # New branch: everything on it that the remote does not already have.
    # Without --not --remotes this walks to the root commit on every new
    # branch, which is slow and floods the output with history that is
    # already published anyway.
    range=$(git rev-list "$local_sha" --not --remotes 2>/dev/null | tail -1)
    [ -n "$range" ] && range="${range}~1..${local_sha}" || range="${local_sha}~1..${local_sha}"
  else
    range="${remote_sha}..${local_sha}"
  fi

  echo "pre-push: scanning $range"
  git rev-list "$range" >/dev/null 2>&1 || { echo "pre-push: cannot resolve $range; refusing" >&2; exit 1; }
  "$scan" --range "$range" || status=1
done

if [ "$status" -ne 0 ]; then
  echo >&2
  echo "pre-push: REFUSED. These commits would be published to the public mirror." >&2
  echo "Rewrite them (git rebase -i / git commit --amend) -- not a follow-up commit:" >&2
  echo "the mirror publishes history, so a later fix leaves the original public." >&2
  exit 1
fi
exit 0
