mirror of
https://github.com/Homebrew/BrewUI.git
synced 2026-10-14 04:39:20 +08:00
`.swiftlint.yml` had `included: Brew`, so `swiftlint lint --strict` skipped the app targets entirely; it now lists `Homebrew` and `HomebrewUpgradeHelper`. `pr_build_test.yml` filtered on `Brew/**` and `Brew.entitlements`, so an app-only change could skip Build and Test. No entitlements file exists anywhere in the tree, so that entry is dropped rather than repointed. BrewUILint's glob reached `Homebrew` but not `HomebrewUpgradeHelper`, leaving 2 files unlinted; CI, `scripts/pre-commit` and AGENTS.md now agree on `find Homebrew HomebrewUpgradeHelper Sources`. CONVENTIONS.md and two Cursor rules pointed at `Brew/Models/HomebrewPackageReference.swift` and `Brew/PreviewSupport/AppPreviewSupport.swift`, neither of which exists under any prefix; they now point at `Sources/BrewCore/Models/HomebrewPackageID.swift` and `Sources/BrewRepositoryInterfaces/PreviewSupport/PreviewSupport.swift`.
129 lines
4.1 KiB
Bash
Executable File
129 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# pre-commit — format and lint staged Swift files before commit.
|
|
# Refreshes the index only for fully staged files; partially staged files must be re-staged manually.
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
if [[ -z "${ROOT_DIR}" ]]; then
|
|
echo "pre-commit: could not determine git repository root."
|
|
exit 1
|
|
fi
|
|
cd "${ROOT_DIR}"
|
|
|
|
if ! command -v mint >/dev/null 2>&1; then
|
|
echo "pre-commit: mint is not installed."
|
|
echo "Run ./scripts/bootstrap (recommended) or: brew install mint && mint bootstrap"
|
|
exit 1
|
|
fi
|
|
|
|
# BrewUILint runs over the WHOLE tree (Homebrew + Sources), not just the staged files. Its
|
|
# nonisolated-extension rule needs to see every `nonisolated` type declaration to flag a bad
|
|
# extension on it, and that declaration may live in an unstaged file in another package. Tests
|
|
# (Tests/) are intentionally excluded. Builds the tool first (cached in Tools/BrewUILint/.build).
|
|
echo "pre-commit: running BrewUILint (whole tree)..."
|
|
if ! xcrun swift build --package-path Tools/BrewUILint -c release >/dev/null 2>&1; then
|
|
echo "pre-commit: failed to build BrewUILint (Tools/BrewUILint) — fix the toolchain/build and retry."
|
|
exit 1
|
|
fi
|
|
brewuilint_bin="$(xcrun swift build --package-path Tools/BrewUILint -c release --show-bin-path)/BrewUILint"
|
|
set +e
|
|
brewuilint_output="$(find Homebrew HomebrewUpgradeHelper Sources -name '*.swift' -print0 | xargs -0 "${brewuilint_bin}" 2>&1)"
|
|
brewuilint_status=$?
|
|
set -e
|
|
if [[ ${brewuilint_status} -ne 0 ]]; then
|
|
echo ""
|
|
echo "pre-commit: commit blocked due to BrewUILint violations:"
|
|
echo ""
|
|
echo "${brewuilint_output}"
|
|
exit 1
|
|
fi
|
|
|
|
swift_files=()
|
|
while IFS= read -r -d '' file; do
|
|
if [[ "${file}" == *.swift ]]; then
|
|
swift_files+=("${file}")
|
|
fi
|
|
done < <(git diff --cached --name-only --diff-filter=ACMR -z)
|
|
|
|
if [[ ${#swift_files[@]} -eq 0 ]]; then
|
|
echo "pre-commit: no staged Swift files, skipping format/lint checks."
|
|
exit 0
|
|
fi
|
|
|
|
# Files with unstaged hunks must not be blanket `git add`ed — that would defeat selective staging.
|
|
partially_staged_files=()
|
|
worktree_hashes_before=()
|
|
for file in "${swift_files[@]}"; do
|
|
if ! git diff --quiet -- "${file}"; then
|
|
partially_staged_files+=("${file}")
|
|
fi
|
|
worktree_hashes_before+=("$(git hash-object -w "${file}")")
|
|
done
|
|
|
|
echo "pre-commit: formatting staged Swift files (mint run swiftformat)..."
|
|
mint run swiftformat "${swift_files[@]}"
|
|
|
|
echo "pre-commit: applying auto-fixes (mint run swiftlint --fix)..."
|
|
set +e
|
|
mint run swiftlint lint --fix --quiet "${swift_files[@]}"
|
|
fix_status=$?
|
|
set -e
|
|
|
|
if [[ ${fix_status} -ne 0 ]]; then
|
|
echo "pre-commit: swiftlint auto-fix reported unresolved issues; running final validation."
|
|
fi
|
|
|
|
files_needing_manual_stage=()
|
|
for index in "${!swift_files[@]}"; do
|
|
file="${swift_files[index]}"
|
|
worktree_hash_before="${worktree_hashes_before[index]}"
|
|
worktree_hash_after="$(git hash-object -w "${file}")"
|
|
if [[ "${worktree_hash_before}" == "${worktree_hash_after}" ]]; then
|
|
continue
|
|
fi
|
|
|
|
is_partial=false
|
|
if ((${#partially_staged_files[@]} > 0)); then
|
|
for partial in "${partially_staged_files[@]}"; do
|
|
if [[ "${file}" == "${partial}" ]]; then
|
|
is_partial=true
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [[ "${is_partial}" == true ]]; then
|
|
files_needing_manual_stage+=("${file}")
|
|
else
|
|
git add -- "${file}"
|
|
fi
|
|
done
|
|
|
|
if [[ ${#files_needing_manual_stage[@]} -gt 0 ]]; then
|
|
echo ""
|
|
echo "pre-commit: formatter/linter updated partially staged file(s)."
|
|
echo "Re-stage your intended changes (e.g. git add -p) and commit again:"
|
|
printf ' - %s\n' "${files_needing_manual_stage[@]}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "pre-commit: validating lint status..."
|
|
set +e
|
|
lint_output="$(mint run swiftlint lint --strict --quiet "${swift_files[@]}" 2>&1)"
|
|
lint_status=$?
|
|
set -e
|
|
|
|
if [[ ${lint_status} -ne 0 ]]; then
|
|
echo ""
|
|
echo "pre-commit: commit blocked due to unresolved SwiftLint violations."
|
|
echo "Fix the issues below, stage changes, and commit again:"
|
|
echo ""
|
|
echo "${lint_output}"
|
|
exit 1
|
|
fi
|
|
|
|
echo "pre-commit: checks passed."
|
|
exit 0
|