chore: gate complexity only on functions touched by the change

Whole-tree radon blocking let 16 legacy C+ functions block every commit,
including docs-only ones. Touched functions still block; legacy debt is
reported as a warning.
This commit is contained in:
2026-10-14 22:32:52 -04:00
parent 22609c90d6
commit 5d2ad40336
+28 -3
View File
@@ -41,10 +41,35 @@ for CODE_DIR in "${CODE_DIRS[@]}"; do
fi
fi
# 复杂度只对"本次改动触及的函数"硬拦: 全量拦截会让存量债务挡住一切提交
# (含纯文档提交),久之只剩绕过一条路;存量 ≥C 函数降为告警,随触及随还。
# 用 HEAD 对比工作区+暂存区: 钩子在 `git add && git commit` 同一命令里先于 add 运行
if command -v radon &> /dev/null; then
RADON_OUTPUT=$(radon cc "$CODE_DIR" -n C -s 2>&1 || true)
if echo "$RADON_OUTPUT" | grep -qE '^\s+[FMC]\s'; then
ERRORS+="[radon] 存在圈复杂度 ≥ C 的函数:\n$RADON_OUTPUT\n"
mapfile -t CHANGED_PY < <(git diff HEAD --name-only --diff-filter=AM -- "$CODE_DIR" | grep '\.py$' || true)
if [[ ${#CHANGED_PY[@]} -gt 0 ]]; then
TOUCHED=$(git diff HEAD -U0 -- "${CHANGED_PY[@]}" | python3 -c '
import json, re, subprocess, sys
hunks, path = {}, None
for line in sys.stdin:
if line.startswith("+++ "):
path = line[6:].strip() if line.startswith("+++ b/") else None
m = re.match(r"@@ -\S+ \+(\d+)(?:,(\d+))? @@", line)
if m and path:
start, count = int(m.group(1)), int(m.group(2) or 1)
hunks.setdefault(path, []).append((start, start + max(count, 1) - 1))
data = json.loads(subprocess.run(["radon", "cc", "-j", "-n", "C", *hunks], capture_output=True, text=True).stdout or "{}")
for path, blocks in data.items():
for b in blocks if isinstance(blocks, list) else []:
if any(s <= b["endline"] and e >= b["lineno"] for s, e in hunks.get(path, [])):
print("%s:%s %s - %s (%s)" % (path, b["lineno"], b["name"], b["rank"], b["complexity"]))
' 2>&1 || true)
if [[ -n "$TOUCHED" ]]; then
ERRORS+="[radon] 本次改动触及的函数圈复杂度 ≥ C:\n$TOUCHED\n"
fi
fi
LEGACY_COUNT=$(radon cc "$CODE_DIR" -n C 2>/dev/null | grep -cE '^\s+[FMC]\s' || true)
if [[ "$LEGACY_COUNT" -gt 0 ]]; then
WARNINGS+="[radon] $CODE_DIR/ 存量 ${LEGACY_COUNT} 个函数圈复杂度 ≥ C(未被本次改动触及,不阻塞)。\n"
fi
fi