#!/usr/bin/env bash

set -euo pipefail

repo_root="$(git rev-parse --show-toplevel)"
cd "$repo_root"

if ! command -v clang-format >/dev/null 2>&1; then
  echo "pre-commit: clang-format not found in PATH" >&2
  exit 1
fi

if ! git clang-format -h >/dev/null 2>&1; then
  echo "pre-commit: git clang-format is not available" >&2
  exit 1
fi

mapfile -d '' staged_files < <(
  git diff --cached --name-only --diff-filter=ACMR -z -- \
    '*.c' '*.h' '*.cc' '*.cpp' '*.cxx' '*.hh' '*.hpp' '*.hxx'
)

if ((${#staged_files[@]} == 0)); then
  exit 0
fi

if git rev-parse --verify HEAD >/dev/null 2>&1; then
  base_commit=HEAD
else
  empty_tree="$(git hash-object -t tree /dev/null)"
  base_commit="$(
    printf 'pre-commit empty base\n' | \
      GIT_AUTHOR_NAME=pre-commit \
      GIT_AUTHOR_EMAIL=pre-commit@example.invalid \
      GIT_COMMITTER_NAME=pre-commit \
      GIT_COMMITTER_EMAIL=pre-commit@example.invalid \
      git commit-tree "$empty_tree"
  )"
fi

set +e
git clang-format --staged --binary clang-format --quiet "$base_commit" -- \
  "${staged_files[@]}"
status=$?
set -e

if [[ $status -ne 0 && $status -ne 1 ]]; then
  exit "$status"
fi

git add -- "${staged_files[@]}"
