88 lines
3.0 KiB
Bash
88 lines
3.0 KiB
Bash
#!/bin/bash
|
||
# Git pre-commit hook:analyze 有 error / warning 则拦截提交
|
||
#
|
||
# 只分析包含暂存 .dart 文件的包,不跑全局 analyze,避免其他包的错误阻断无关提交。
|
||
#
|
||
# 安装:bash scripts/setup.sh(setup.sh 自动把本文件复制到 .git/hooks/pre-commit)
|
||
# 手动安装:cp scripts/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
|
||
|
||
set -euo pipefail
|
||
|
||
ROOT_DIR="$(git rev-parse --show-toplevel)"
|
||
DART="$(command -v dart 2>/dev/null || echo "")"
|
||
|
||
if [[ -z "$DART" ]]; then
|
||
echo "[pre-commit] dart not found, skipping checks."
|
||
exit 0
|
||
fi
|
||
|
||
# ── pubspec.lock 保护 ────────────────────────────────────────────────────────
|
||
# flutter run / flutter build 会在未经授权的情况下触发 pub get 并修改 lock。
|
||
# 规则:lock 有未暂存的改动(意外修改)→ 自动还原;
|
||
# 开发者主动 git add pubspec.lock 后(暂存)→ 正常放行。
|
||
LOCK_UNSTAGED=$(git diff --name-only pubspec.lock 2>/dev/null || true)
|
||
LOCK_STAGED=$(git diff --cached --name-only pubspec.lock 2>/dev/null || true)
|
||
|
||
if [[ -n "$LOCK_UNSTAGED" && -z "$LOCK_STAGED" ]]; then
|
||
git checkout HEAD -- pubspec.lock
|
||
echo "[pre-commit] pubspec.lock was auto-modified by flutter, restored to HEAD."
|
||
echo " To intentionally update: run 'flutter pub get' or 'flutter pub upgrade',"
|
||
echo " then 'git add pubspec.lock' before committing."
|
||
fi
|
||
|
||
# ── dart analyze(只分析涉及的包)────────────────────────────────────────────
|
||
STAGED_DART=$(git diff --cached --name-only --diff-filter=ACM | grep '\.dart$' || true)
|
||
|
||
if [[ -z "$STAGED_DART" ]]; then
|
||
exit 0
|
||
fi
|
||
|
||
# 找到每个暂存 .dart 文件所在的包根目录(最近的 pubspec.yaml 所在目录)
|
||
PKG_DIRS_LIST=()
|
||
while IFS= read -r file; do
|
||
dir="$ROOT_DIR/$(dirname "$file")"
|
||
while [[ "$dir" != "$ROOT_DIR" && "$dir" != "/" ]]; do
|
||
if [[ -f "$dir/pubspec.yaml" ]]; then
|
||
PKG_DIRS_LIST+=("$dir")
|
||
break
|
||
fi
|
||
dir="$(dirname "$dir")"
|
||
done
|
||
done <<< "$STAGED_DART"
|
||
|
||
if [[ ${#PKG_DIRS_LIST[@]} -eq 0 ]]; then
|
||
exit 0
|
||
fi
|
||
|
||
# 去重
|
||
UNIQUE_PKGS=$(printf '%s\n' "${PKG_DIRS_LIST[@]}" | sort -u)
|
||
|
||
echo "[pre-commit] running dart analyze on affected packages..."
|
||
|
||
FAILED=0
|
||
while IFS= read -r pkg_dir; do
|
||
pkg_name="$(basename "$pkg_dir")"
|
||
echo "[pre-commit] → $pkg_name"
|
||
ANALYZE_OUTPUT=$(dart analyze "$pkg_dir" 2>&1)
|
||
|
||
if echo "$ANALYZE_OUTPUT" | grep -q "^ error"; then
|
||
echo "[pre-commit] errors in $pkg_name:"
|
||
echo "$ANALYZE_OUTPUT" | grep "^ error"
|
||
FAILED=1
|
||
fi
|
||
|
||
if echo "$ANALYZE_OUTPUT" | grep -q "^ warning"; then
|
||
echo "[pre-commit] warnings in $pkg_name:"
|
||
echo "$ANALYZE_OUTPUT" | grep "^ warning"
|
||
FAILED=1
|
||
fi
|
||
done <<< "$UNIQUE_PKGS"
|
||
|
||
if [[ $FAILED -eq 1 ]]; then
|
||
echo "[pre-commit] commit blocked due to errors/warnings above."
|
||
exit 1
|
||
fi
|
||
|
||
echo "[pre-commit] all checks passed."
|
||
exit 0
|