|
|
|
|
@ -1,126 +0,0 @@
|
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
msg_file="${1:-}"
|
|
|
|
|
|
|
|
|
|
if [[ -z "${msg_file}" || ! -f "${msg_file}" ]]; then
|
|
|
|
|
echo "错误:未找到提交信息文件(commit-msg hook 未收到有效参数)。" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 读取第一条“有效提交信息”(跳过空行与注释行),并兼容 CRLF。
|
|
|
|
|
first_line="$(
|
|
|
|
|
awk '
|
|
|
|
|
{
|
|
|
|
|
sub(/\r$/, "")
|
|
|
|
|
if ($0 ~ /^[[:space:]]*#/) next
|
|
|
|
|
if ($0 ~ /^[[:space:]]*$/) next
|
|
|
|
|
print
|
|
|
|
|
exit
|
|
|
|
|
}
|
|
|
|
|
' "${msg_file}"
|
|
|
|
|
)"
|
|
|
|
|
|
|
|
|
|
allowed_types=(
|
|
|
|
|
feat fix docs style refactor perf test build ci chore revert
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
allowed_scopes=(
|
|
|
|
|
frontend ast sema ir irgen mir backend antlr build test doc dev
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
print_allowed() {
|
|
|
|
|
local IFS="|"
|
|
|
|
|
echo "允许的 type:${allowed_types[*]}" >&2
|
|
|
|
|
echo "允许的 scope:${allowed_scopes[*]}" >&2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fail() {
|
|
|
|
|
local reason="$1"
|
|
|
|
|
local extra="${2:-}"
|
|
|
|
|
|
|
|
|
|
echo "错误:提交信息不符合规范:${reason}" >&2
|
|
|
|
|
echo "" >&2
|
|
|
|
|
echo "当前提交信息:" >&2
|
|
|
|
|
echo " ${first_line}" >&2
|
|
|
|
|
echo "" >&2
|
|
|
|
|
echo "规范格式:" >&2
|
|
|
|
|
echo " <type>(<scope>): <subject>" >&2
|
|
|
|
|
echo "" >&2
|
|
|
|
|
echo "注意:" >&2
|
|
|
|
|
echo " 1) 冒号必须是英文 ':'(不是中文 ':')。" >&2
|
|
|
|
|
echo " 2) 冒号后必须严格跟 1 个空格(': ')。" >&2
|
|
|
|
|
echo "" >&2
|
|
|
|
|
print_allowed
|
|
|
|
|
echo "" >&2
|
|
|
|
|
echo "示例:" >&2
|
|
|
|
|
echo " feat(irgen): add constant folding" >&2
|
|
|
|
|
echo " fix(sema): handle null symbol" >&2
|
|
|
|
|
echo " docs(doc): update build instructions" >&2
|
|
|
|
|
if [[ -n "${extra}" ]]; then
|
|
|
|
|
echo "" >&2
|
|
|
|
|
echo "${extra}" >&2
|
|
|
|
|
fi
|
|
|
|
|
echo "" >&2
|
|
|
|
|
echo "参考文档:doc/Git Commit Message 规范.md" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if [[ -z "${first_line}" ]]; then
|
|
|
|
|
fail "提交信息为空(第一行不能为空)。"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 允许 merge 提交信息(如:git merge 默认生成的 message)。
|
|
|
|
|
if [[ "${first_line}" == "Merge "* ]]; then
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 允许 fixup!/squash!(用于 rebase --autosquash 等流程)。
|
|
|
|
|
if [[ "${first_line}" == "fixup!"* || "${first_line}" == "squash!"* ]]; then
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# 先做一些常见错误的定向提示。
|
|
|
|
|
if [[ "${first_line}" == *":"* ]]; then
|
|
|
|
|
fail "检测到中文冒号 ':'。" "请把中文冒号替换为英文冒号 ':',并确保冒号后有且仅有 1 个空格。"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ "${first_line}" =~ ^[A-Za-z]+\([A-Za-z]+\):[^[:space:]].*$ ]]; then
|
|
|
|
|
fail "冒号后缺少空格。" "正确写法应为 ': '(英文冒号 + 1 个空格)。"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ "${first_line}" =~ ^[A-Za-z]+\([A-Za-z]+\):[[:space:]]{2,}.*$ ]]; then
|
|
|
|
|
fail "冒号后空格数量不正确(多于 1 个空格)。" "请确保冒号后严格是 1 个空格(': ')。"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
type=""
|
|
|
|
|
scope=""
|
|
|
|
|
subject=""
|
|
|
|
|
|
|
|
|
|
if [[ "${first_line}" =~ ^([A-Za-z]+)\(([A-Za-z]+)\):\ (.+)$ ]]; then
|
|
|
|
|
type="${BASH_REMATCH[1]}"
|
|
|
|
|
scope="${BASH_REMATCH[2]}"
|
|
|
|
|
subject="${BASH_REMATCH[3]}"
|
|
|
|
|
else
|
|
|
|
|
fail "格式不正确。" "请按 '<type>(<scope>): <subject>' 格式填写。"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ "${subject}" =~ ^[[:space:]] ]]; then
|
|
|
|
|
fail "冒号后的空格数量不正确(多于 1 个空格)。" "请确保冒号后严格是 1 个空格(': ')。"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
case "${type}" in
|
|
|
|
|
feat | fix | docs | style | refactor | perf | test | build | ci | chore | revert) ;;
|
|
|
|
|
*)
|
|
|
|
|
fail "type 不合法:${type}" "请使用允许的 type(小写)。"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
case "${scope}" in
|
|
|
|
|
frontend | ast | sema | ir | irgen | mir | backend | antlr | build | test | doc | dev) ;;
|
|
|
|
|
*)
|
|
|
|
|
fail "scope 不合法:${scope}" "请使用允许的 scope(严格限制)。"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
exit 0
|