mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-10-30 22:23:43 +00:00
chore(hooks): adopt pre-commit framework
This commit is contained in:
@@ -1,114 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Pre-commit 检查(启用:git config core.hooksPath .githooks,
|
||||
# 行为约定见仓库根目录 README.md,工具安装与版本见 ShadowsocksX-NG2/README.md):
|
||||
# 1. 对暂存的 ShadowsocksX-NG2/ 下 .swift 文件先 `swift format` 格式化,
|
||||
# 格式化结果直接写回暂存区(只改暂存区、不动工作区,部分暂存安全);
|
||||
# 2. 再用 SwiftLint 检查暂存内容:error 级违规拒绝提交,warning 仅提示。
|
||||
# 其余文件一律跳过;没有 NG2 的 Swift 文件时立即放行。
|
||||
# 工具缺失且确有 NG2 Swift 文件待查时,失败而不是放行。两关都把「工具没能
|
||||
# 执行」与「查出问题」分开报告,不把工具错误说成代码违规。
|
||||
|
||||
set -u
|
||||
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)" || exit 1
|
||||
NG2_DIR="$REPO_ROOT/ShadowsocksX-NG2"
|
||||
|
||||
[ -d "$NG2_DIR" ] || exit 0
|
||||
|
||||
TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/ng2-pre-commit.XXXXXX")" || exit 1
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
# 暂存的新增/修改文件中只取 NG2 下的 .swift(删除的文件无需处理);
|
||||
# 关闭 quotePath,非 ASCII 文件名按原文输出
|
||||
STAGED_LIST="${TMP_DIR}/staged.txt"
|
||||
git -c core.quotePath=false diff --cached --name-only --diff-filter=ACMR |
|
||||
while IFS= read -r path; do
|
||||
case "$path" in
|
||||
ShadowsocksX-NG2/*.swift) printf '%s\n' "$path" ;;
|
||||
esac
|
||||
done > "$STAGED_LIST"
|
||||
|
||||
[ -s "$STAGED_LIST" ] || exit 0
|
||||
|
||||
for tool in swift swiftlint; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
echo "pre-commit: 缺少 ${tool},无法执行提交检查(安装步骤见 ShadowsocksX-NG2/README.md)" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# 暂存内容的临时副本路径:序号前缀避免不同目录同名文件冲突
|
||||
tmp_name() {
|
||||
printf '%s/%04d_%s' "${TMP_DIR}" "$1" "$(basename "$2")"
|
||||
}
|
||||
|
||||
# 取暂存内容到临时目录处理,与工作区解耦
|
||||
i=0
|
||||
while IFS= read -r path; do
|
||||
i=$((i + 1))
|
||||
git show ":${path}" > "$(tmp_name "$i" "${path}")" || exit 1
|
||||
done < "$STAGED_LIST"
|
||||
|
||||
# 第 1 关:swift format 格式化(显式传配置路径);语法解析失败等工具错误即拒绝
|
||||
if ! swift format format --in-place --configuration "${NG2_DIR}/.swift-format" \
|
||||
"${TMP_DIR}"/[0-9]*.swift 2>"${TMP_DIR}/format.err"; then
|
||||
echo "pre-commit: swift format 执行失败,提交被拒绝:" >&2
|
||||
cat "${TMP_DIR}/format.err" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 格式化结果写回暂存区
|
||||
i=0
|
||||
while IFS= read -r path; do
|
||||
i=$((i + 1))
|
||||
tmp_file="$(tmp_name "$i" "${path}")"
|
||||
staged_hash="$(git show ":${path}" | git hash-object --stdin)"
|
||||
formatted_hash="$(git hash-object -w "${tmp_file}")"
|
||||
if [ "$staged_hash" != "$formatted_hash" ]; then
|
||||
git update-index --cacheinfo "100644,${formatted_hash},${path}" || exit 1
|
||||
echo "pre-commit: swift format 已重新格式化 ${path} (格式化结果已入提交)"
|
||||
fi
|
||||
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"
|
||||
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
|
||||
cat "${LINT_LOG}" >&2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,19 @@
|
||||
minimum_pre_commit_version: "3.2.0"
|
||||
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: ng2-swift-format
|
||||
name: Format staged NG2 Swift files
|
||||
entry: swift format format --in-place --configuration ShadowsocksX-NG2/.swift-format
|
||||
language: system
|
||||
files: ^ShadowsocksX-NG2/.*\.swift$
|
||||
stages: [pre-commit]
|
||||
|
||||
- id: ng2-swiftlint
|
||||
name: Lint staged NG2 Swift files
|
||||
entry: swiftlint lint --config ShadowsocksX-NG2/.swiftlint.yml --no-cache --quiet
|
||||
language: system
|
||||
files: ^ShadowsocksX-NG2/.*\.swift$
|
||||
stages: [pre-commit]
|
||||
verbose: true
|
||||
+13
-5
@@ -61,20 +61,28 @@ You can build and run unit tests without a certificate: the Debug baseline uses
|
||||
|
||||
## Code style tools
|
||||
|
||||
- `swift format` is included with the Xcode/Swift toolchain and does not need a separate installation (baseline: Apple Swift 6.4). Install SwiftLint with `brew install swiftlint` (baseline: 0.65.0). If either tool is missing, the pre-commit hook rejects a commit that contains Swift files under the project directory instead of allowing it.
|
||||
- `swift format` is included with the Xcode/Swift toolchain and does not need a separate installation (baseline: Apple Swift 6.4). Install SwiftLint with `brew install swiftlint` (baseline: 0.65.0), and install the hook manager with `brew install pre-commit`. If a required tool is missing, pre-commit rejects a commit that contains NG2 Swift files.
|
||||
- `.swift-format` is a snapshot of the Swift 6.4 toolchain's default rules, checked in so the rules do not drift on toolchain upgrades. `.swiftlint.yml` starts with the default rules and declares only exclusions and individual opt-outs that conflict with the format baseline; comments in the file show triggering examples.
|
||||
- See [Development hooks](#development-hooks) for how to enable the repository-level `pre-commit` hook and what it checks.
|
||||
- The repository-level hook configuration is `.pre-commit-config.yaml`. See [Development hooks](#development-hooks) for how to install it and what it checks.
|
||||
- Adjust rules only to address concrete problems. A PR that changes `.swift-format` or `.swiftlint.yml` must include a triggering example and update the baseline versions in this section.
|
||||
|
||||
## Development hooks
|
||||
|
||||
After cloning, enable Git hooks from the repository root:
|
||||
After cloning, install the hooks from the repository root:
|
||||
|
||||
```bash
|
||||
git config core.hooksPath .githooks
|
||||
brew install pre-commit # Skip if already installed.
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
Once enabled, `pre-commit` checks only staged `.swift` files under `ShadowsocksX-NG2/`. `swift format` writes its result back to the index without changing the working tree. SwiftLint errors reject the commit; warnings are informational. Other files are skipped. If there are no NG2 Swift files, the hook passes. If NG2 Swift files are present and a required tool is missing, the check fails. Both checks distinguish “tool execution failed” from “issues found”: when you see “execution failed,” investigate the tool or configuration environment instead of changing code. See [Code style tools](#code-style-tools) for installation and versions.
|
||||
If you previously enabled the old `.githooks` setup, remove its local Git setting before installing the new hook:
|
||||
|
||||
```bash
|
||||
git config --local --unset core.hooksPath
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
The configuration checks only staged `.swift` files under `ShadowsocksX-NG2/`; other files are skipped. `swift format` formats those files in the working tree, and pre-commit stops that commit when formatting changes them. Review and stage the formatting changes, then commit again. SwiftLint errors reject the commit; warnings are shown but do not block it. If there are no NG2 Swift files, both hooks are skipped. If NG2 Swift files are staged and a required tool is missing, the corresponding hook fails. See [Code style tools](#code-style-tools) for tool installation and versions.
|
||||
|
||||
## Language of domain documents
|
||||
|
||||
|
||||
+13
-5
@@ -62,20 +62,28 @@ ACL 路由与插件监管),不在默认 `task test` 内,由独立 scheme
|
||||
|
||||
## 代码风格工具
|
||||
|
||||
- `swift format` 随 Xcode/Swift 工具链提供,无需单独安装(基线:Apple Swift 6.4);SwiftLint 需 `brew install swiftlint`(基线 0.65.0)。工具缺失时,含工程目录 Swift 文件的提交会被 pre-commit 钩子拒绝而不是放行。
|
||||
- `swift format` 随 Xcode/Swift 工具链提供,无需单独安装(基线:Apple Swift 6.4);SwiftLint 需 `brew install swiftlint`(基线 0.65.0),钩子管理器需 `brew install pre-commit`。缺少必需工具时,暂存了 NG2 Swift 文件的提交会被拒绝。
|
||||
- 配置文件:`.swift-format` 是 Swift 6.4 工具链默认规则的快照(固定成文件,工具链升级不漂移);`.swiftlint.yml` 默认规则起步,只声明排除项与个别和 format 基线冲突的关闭项(文件内有触发案例注释)。
|
||||
- 仓库级 `pre-commit` 钩子的启用方式和检查范围见下节「开发钩子」。
|
||||
- 仓库级 hook 配置位于 `.pre-commit-config.yaml`;安装方式和检查范围见下节「开发钩子」。
|
||||
- 调整规则只针对实际痛点:修改 `.swift-format` / `.swiftlint.yml` 的 PR 须给出触发案例,并同步更新本节中的基线版本。
|
||||
|
||||
## 开发钩子
|
||||
|
||||
新 clone 后,在仓库根目录启用 Git hooks:
|
||||
新 clone 后,在仓库根目录安装 hooks:
|
||||
|
||||
```bash
|
||||
git config core.hooksPath .githooks
|
||||
brew install pre-commit # 已安装时跳过
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
启用后,`pre-commit` 只检查暂存区中 `ShadowsocksX-NG2/` 下的 `.swift` 文件:`swift format` 的结果写回暂存区、不修改工作区;SwiftLint 的 error 级违规拒绝提交,warning 仅提示。其他文件跳过;没有 NG2 Swift 文件时直接放行。含有 NG2 Swift 文件但缺少工具时,提交检查失败。两关都把「工具没能执行」与「查出问题」分开报告:看到「执行失败」应查工具与配置环境,而不是去改代码。工具安装与版本见上节「代码风格工具」。
|
||||
如果之前启用过旧版 `.githooks`,先清除本地 Git 设置,再安装新 hook:
|
||||
|
||||
```bash
|
||||
git config --local --unset core.hooksPath
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
配置只检查暂存区中 `ShadowsocksX-NG2/` 下的 `.swift` 文件,其他文件跳过。`swift format` 会在工作区格式化这些文件;格式发生变化时,本次提交会被 pre-commit 拦下。检查并暂存格式化结果后再提交。SwiftLint 的 error 级违规拒绝提交,warning 会显示但不阻止提交。没有 NG2 Swift 文件时两个 hook 都跳过;暂存了 NG2 Swift 文件但缺少必需工具时,对应 hook 会失败。工具安装与版本见上节「代码风格工具」。
|
||||
|
||||
## 领域文档语言
|
||||
|
||||
|
||||
Reference in New Issue
Block a user