#!/bin/bash # Git pre-commit hook:提交前自动 format,analyze 有 error 则拦截提交 # # 安装: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 'dart pub get' or 'dart pub upgrade'," echo " then 'git add pubspec.lock' before committing." fi # ── dart format + analyze ──────────────────────────────────────────────────── STAGED_DART=$(git diff --cached --name-only --diff-filter=ACM | grep '\.dart$' || true) if [[ -z "$STAGED_DART" ]]; then exit 0 fi echo "[pre-commit] formatting staged dart files..." echo "$STAGED_DART" | xargs dart format --line-length=80 echo "$STAGED_DART" | xargs git add echo "[pre-commit] running dart analyze..." cd "$ROOT_DIR" ANALYZE_OUTPUT=$(dart analyze 2>&1) if echo "$ANALYZE_OUTPUT" | grep -q "^ error"; then echo "[pre-commit] dart analyze found errors, commit blocked." echo "$ANALYZE_OUTPUT" | grep "^ error" exit 1 fi if echo "$ANALYZE_OUTPUT" | grep -q "^ warning"; then echo "[pre-commit] dart analyze found warnings, commit blocked." echo "$ANALYZE_OUTPUT" | grep "^ warning" exit 1 fi echo "[pre-commit] all checks passed." exit 0