# Checks the subject line of the commit message. This cannot be done in
# `pre-commit`: at that point the message does not exist yet — the editor opens
# AFTER pre-commit returns. Git passes the path of the message file as $1.
#
# To bypass: `HUSKY=0 git commit` or `git commit --no-verify`.

set -e

PREFIXES='chore|feat|hotfix|bugfix|reconcile|fix|docs|refactor|test|perf|ci'

MSG_FILE="$1"
if [ -z "$MSG_FILE" ] || [ ! -f "$MSG_FILE" ]; then
  echo "✖ commit-msg: no message file was passed" >&2
  exit 1
fi

# The subject line only. Git's template comments (`#`) are on later lines.
SUBJECT="$(sed -n '1p' "$MSG_FILE")"

# Messages git generates itself are exempt from the rule — forbidding merge,
# revert and autosquash markers would break `git merge` and `rebase -i` on
# messages the user never wrote.
case "$SUBJECT" in
  Merge\ *|Revert\ *|Reapply\ *|fixup!*|squash!*|amend!*) exit 0 ;;
esac

# Git aborts an empty message on its own; passing it through here keeps the
# error from naming the wrong cause.
if [ -z "$SUBJECT" ]; then
  exit 0
fi

# `feat: …`, `fix(select): …`, `feat(tokens)!: …` — the scope and the breaking
# `!` are optional.
if ! echo "$SUBJECT" | grep -qE "^($PREFIXES)(\([a-z0-9._/-]+\))?!?: .+"; then
  echo "" >&2
  echo "✖ Commit message does not follow the convention:" >&2
  echo "    $SUBJECT" >&2
  echo "" >&2
  echo "  Format:   <prefix>[(scope)][!]: <description>" >&2
  echo "  Prefixes: chore feat hotfix bugfix reconcile fix" >&2
  echo "            docs refactor test perf ci" >&2
  echo "" >&2
  echo "  Examples: feat: add a ProgressCircle component" >&2
  echo "            fix(select): keep focus when the value is cleared" >&2
  echo "            feat(tokens)!: rename the third palette to tertiary" >&2
  echo "" >&2
  exit 1
fi
