#!/usr/bin/env bash
# Format staged Go files with gofmt and re-stage them.
# Enable once per clone: git config core.hooksPath .githooks
set -euo pipefail

# macOS ships bash 3.2 which lacks mapfile; use NUL-delimited read instead.
files=()
while IFS= read -r -d '' f; do
  files+=("$f")
done < <(git diff --cached --name-only --diff-filter=ACM -z -- '*.go')
[ ${#files[@]} -eq 0 ] && exit 0

unformatted=()
while IFS= read -r line; do
  [ -n "$line" ] && unformatted+=("$line")
done < <(gofmt -l "${files[@]}")
[ ${#unformatted[@]} -eq 0 ] && exit 0

# If a file has unstaged changes, gofmt+git add would silently fold them into
# this commit. Refuse and let the user resolve it explicitly.
dirty=()
for f in "${unformatted[@]}"; do
  if ! git diff --quiet -- "$f"; then
    dirty+=("$f")
  fi
done
if [ ${#dirty[@]} -gt 0 ]; then
  echo "pre-commit: these files need gofmt but also have unstaged changes:" >&2
  printf '  %s\n' "${dirty[@]}" >&2
  echo "Stash or stage the unstaged changes, then commit again." >&2
  exit 1
fi

gofmt -w "${unformatted[@]}"
git add -- "${unformatted[@]}"
echo "pre-commit: gofmt re-staged:"
printf '  %s\n' "${unformatted[@]}"
