122 lines
3.4 KiB
Bash
Executable File
122 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
print_usage() {
|
|
echo "Usage:"
|
|
echo " $0"
|
|
echo " $0 <commit-hash>"
|
|
echo " $0 --message \"<commit-message>\""
|
|
echo " $0 --message-file <file-path>"
|
|
}
|
|
|
|
load_commit_message() {
|
|
if [ $# -eq 0 ]; then
|
|
local commit_ref="HEAD"
|
|
echo "Checking latest commit..." >&2
|
|
git log -1 --pretty=format:"%s%n%b" "$commit_ref"
|
|
return
|
|
fi
|
|
|
|
case "$1" in
|
|
-h|--help)
|
|
print_usage
|
|
exit 0
|
|
;;
|
|
--message)
|
|
shift
|
|
if [ $# -eq 0 ]; then
|
|
echo "[FAIL] --message option requires a commit message"
|
|
print_usage
|
|
exit 1
|
|
fi
|
|
echo "Checking provided commit message..." >&2
|
|
printf '%s' "$*"
|
|
;;
|
|
--message-file)
|
|
shift
|
|
if [ $# -ne 1 ]; then
|
|
echo "[FAIL] --message-file option requires a file path"
|
|
print_usage
|
|
exit 1
|
|
fi
|
|
if [ ! -f "$1" ]; then
|
|
echo "[FAIL] Commit message file not found: $1"
|
|
exit 1
|
|
fi
|
|
echo "Checking commit message file: $1" >&2
|
|
cat "$1"
|
|
;;
|
|
*)
|
|
if [ $# -ne 1 ]; then
|
|
echo "[FAIL] Invalid arguments"
|
|
print_usage
|
|
exit 1
|
|
fi
|
|
|
|
local commit_ref="$1"
|
|
if ! git rev-parse --verify "$commit_ref^{commit}" >/dev/null 2>&1; then
|
|
echo "[FAIL] Invalid commit reference: $commit_ref"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Checking commit: $commit_ref" >&2
|
|
git log -1 --pretty=format:"%s%n%b" "$commit_ref"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
commit_message=$(load_commit_message "$@")
|
|
subject=$(printf '%s\n' "$commit_message" | head -n1)
|
|
body=$(printf '%s\n' "$commit_message" | tail -n +2)
|
|
|
|
echo "Checking commit message format..."
|
|
echo "Subject: $subject"
|
|
|
|
exit_code=0
|
|
|
|
if [ -z "$subject" ]; then
|
|
echo "[FAIL] Subject must not be empty"
|
|
exit 1
|
|
fi
|
|
|
|
subject_pattern='^([a-z]+)(\([a-z0-9._/-]+\))?(!)?: (.+)$'
|
|
if [[ "$subject" =~ $subject_pattern ]]; then
|
|
type="${BASH_REMATCH[1]}"
|
|
description="${BASH_REMATCH[4]}"
|
|
|
|
echo "[PASS] Subject follows Conventional Commit format"
|
|
echo "[PASS] Type is lowercase: $type"
|
|
|
|
if printf '%s\n' "$description" | grep -Eq '[가-힣]'; then
|
|
echo "[PASS] Description contains Korean text"
|
|
else
|
|
echo "[FAIL] Description must contain Korean text"
|
|
exit_code=1
|
|
fi
|
|
else
|
|
echo "[FAIL] Subject must match: <type>(scope): <description>"
|
|
echo " scope is optional, example: feat: 기능을 추가한다"
|
|
exit_code=1
|
|
fi
|
|
|
|
if [ -n "$body" ] && printf '%s\n' "$body" | grep -Eq '^Refs:'; then
|
|
while IFS= read -r refs_line; do
|
|
if ! printf '%s\n' "$refs_line" | grep -Eq '^Refs: #[0-9]+(, #[0-9]+)*$'; then
|
|
echo "[FAIL] Refs footer format is invalid: $refs_line"
|
|
echo " expected format: Refs: #123 or Refs: #123, #456"
|
|
exit_code=1
|
|
fi
|
|
done < <(printf '%s\n' "$body" | grep -E '^Refs:')
|
|
|
|
if [ $exit_code -eq 0 ]; then
|
|
echo "[PASS] Refs footer format is valid"
|
|
fi
|
|
fi
|
|
|
|
if [ $exit_code -eq 0 ]; then
|
|
echo "[PASS] Commit message follows AGENTS.md rules"
|
|
else
|
|
echo "[FAIL] Commit message violates AGENTS.md rules"
|
|
fi
|
|
|
|
exit $exit_code
|