From 67d0afcda14c02fa1307c7842ffd9316c8e3e1b4 Mon Sep 17 00:00:00 2001 From: Qiu Yuzhou Date: Mon, 5 Oct 2026 20:18:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(hooks):=20=E5=8C=BA=E5=88=86=20SwiftLint=20?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=E5=A4=B1=E8=B4=A5=E4=B8=8E=20error=20?= =?UTF-8?q?=E7=BA=A7=E8=BF=9D=E8=A7=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pre-commit 第 2 关只看 swiftlint 是否非零,把任何非零都报成「SwiftLint 发现 error 级违规」。而 SwiftLint 默认要把缓存 plist 写进 ~/Library/Caches,写不进去时它自己以退出码 1 失败,于是受限环境下每次 提交都被拒绝、并被指向代码,实际原因在工具环境。 两处改动: - 加 --no-cache,直接消灭缓存写入这一失败模式(本关只查几十个暂存文件, 代价可忽略;task lint 本来就是这么调的)。 - 按退出码分派:0 放行(有 warning 则提示后放行)、2 报「发现 error 级 违规」、其余报「执行失败(退出码 N)」并点明是工具错误而非代码违规。 不能改用解析输出文本判断:工具错误信息里同样含 "error:"(配置读不了时 输出 error: Could not read file at path ...),只有退出码可靠。退出码映射 (0 = 干净或仅 warning,2 = error 级违规,1 = 内部错误,134 = 配置读不了) 为 swiftlint 0.65.x 实测。 验证:在 /tmp 最小仓库(真钩子 + 真配置 + core.hooksPath)中不解沙箱跑 五个场景——旧钩子对只含 warning 的文件误报为 error 级违规(复现);新钩子 对同一文件放行并提示 warning;error 级违规正确拒绝且 HEAD 未动;配置读不了 时报「执行失败(退出码 134)」而非违规;复原后放行。 根 README 开发钩子一节同步这一区分。钩子只改第 2 关与头部注释。 --- .githooks/pre-commit | 42 ++++++++++++++++++++++++++++++++++-------- README.md | 2 +- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/.githooks/pre-commit b/.githooks/pre-commit index f7123747..f278ce01 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -6,7 +6,8 @@ # 格式化结果直接写回暂存区(只改暂存区、不动工作区,部分暂存安全); # 2. 再用 SwiftLint 检查暂存内容:error 级违规拒绝提交,warning 仅提示。 # 其余文件(含冻结的 Legacy/)一律跳过;没有 NG2 的 Swift 文件时立即放行。 -# 工具缺失且确有 NG2 Swift 文件待查时,失败而不是放行。 +# 工具缺失且确有 NG2 Swift 文件待查时,失败而不是放行。两关都把「工具没能 +# 执行」与「查出问题」分开报告,不把工具错误说成代码违规。 set -u @@ -71,14 +72,39 @@ while IFS= read -r path; do done < "$STAGED_LIST" # 第 2 关:SwiftLint 静态检查暂存内容(error 拒绝提交,warning 提示但放行) +# +# --no-cache:SwiftLint 默认要把缓存 plist 写进 ~/Library/Caches。写不进去时 +# 它自己以非零退出,若只看「是否非零」就会把「工具没跑起来」误报成「发现 +# error 级违规」(实测:受限环境下每次提交都这样失败)。本关只需要检查几十个 +# 暂存文件,省掉缓存的代价可以忽略。 +# +# 退出码(swiftlint 0.65.x 实测)区分两类失败;注意不能改用解析输出文本来 +# 判断——工具错误信息里同样含 "error:"(配置读不了时输出 +# "error: Could not read file at path ..."): +# 0 = 无 error 级违规(可能含 warning);2 = 发现 error 级违规; +# 其余(1 = 内部错误如缓存写失败;134 = 配置读不了等) = 工具执行失败。 LINT_LOG="${TMP_DIR}/swiftlint.log" -if ! swiftlint lint --config "${NG2_DIR}/.swiftlint.yml" --quiet "${TMP_DIR}" >"${LINT_LOG}" 2>&1; then - echo "pre-commit: SwiftLint 发现 error 级违规,提交被拒绝" >&2 - echo "pre-commit: 报告中的 0001_xxx.swift 是暂存内容的临时副本,序号_ 后为原文件名:" >&2 - cat "${LINT_LOG}" >&2 - echo "pre-commit: 请修复后重新提交;手动检查方式见 ShadowsocksX-NG2/README.md" >&2 - exit 1 -fi +swiftlint lint --config "${NG2_DIR}/.swiftlint.yml" --no-cache --quiet "${TMP_DIR}" \ + >"${LINT_LOG}" 2>&1 +lint_status=$? + +case "$lint_status" in + 0) ;; + 2) + echo "pre-commit: SwiftLint 发现 error 级违规,提交被拒绝" >&2 + echo "pre-commit: 报告中的 0001_xxx.swift 是暂存内容的临时副本,序号_ 后为原文件名:" >&2 + cat "${LINT_LOG}" >&2 + echo "pre-commit: 请修复后重新提交;手动检查方式见 ShadowsocksX-NG2/README.md" >&2 + exit 1 + ;; + *) + echo "pre-commit: SwiftLint 执行失败(退出码 ${lint_status}),提交被拒绝" >&2 + echo "pre-commit: 这是工具错误而非代码违规,请检查配置与工具安装" >&2 + echo "pre-commit:(基线版本见 ShadowsocksX-NG2/README.md):" >&2 + cat "${LINT_LOG}" >&2 + exit 1 + ;; +esac if [ -s "${LINT_LOG}" ]; then echo "pre-commit: SwiftLint warning(不拦截提交):" >&2 diff --git a/README.md b/README.md index 95da5a6b..52e1ddc2 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ git config core.hooksPath .githooks ``` -启用后,`pre-commit` 只检查暂存区中 `ShadowsocksX-NG2/` 下的 `.swift` 文件:`swift format` 的结果写回暂存区、不修改工作区;SwiftLint 的 error 级违规拒绝提交,warning 仅提示。`Legacy/` 和其他文件跳过;没有 NG2 Swift 文件时直接放行。含有 NG2 Swift 文件但缺少工具时,提交检查失败。工具安装与版本见 [`ShadowsocksX-NG2/README.md`](ShadowsocksX-NG2/README.md)。 +启用后,`pre-commit` 只检查暂存区中 `ShadowsocksX-NG2/` 下的 `.swift` 文件:`swift format` 的结果写回暂存区、不修改工作区;SwiftLint 的 error 级违规拒绝提交,warning 仅提示。`Legacy/` 和其他文件跳过;没有 NG2 Swift 文件时直接放行。含有 NG2 Swift 文件但缺少工具时,提交检查失败。两关都把「工具没能执行」与「查出问题」分开报告:看到「执行失败」应查工具与配置环境,而不是去改代码。工具安装与版本见 [`ShadowsocksX-NG2/README.md`](ShadowsocksX-NG2/README.md)。 ## 领域文档语言