Files
WSL/tools/hooks/pre-commit.in
Ben Hillis b7735bba18 Replace pre-commit hook with CMake-generated clang-format check (#40136)
* Replace pre-commit hook with CMake-generated clang-format check

Replace the old pre-commit hook that shelled out to PowerShell and
never blocked commits (-NoFail) with a CMake-generated hook that
calls clang-format directly on staged C/C++ files.

- Add tools/hooks/pre-commit.in as a CMake template
- CMake resolves the clang-format path at configure time via
  LLVM_INSTALL_DIR, matching the existing FormatSource.ps1.in pattern
- Hook blocks commits on formatting errors, skips gracefully if
  clang-format is not available (cmake not yet run)
- ~5x faster than the old PowerShell approach (~0.5s vs ~2.6s)

* Make pre-commit hook behavior configurable via WSL_PRE_COMMIT_MODE

Add WSL_PRE_COMMIT_MODE CMake cache variable with three modes:
- warn (default): report formatting issues without blocking commit
- error: block commit when formatting issues are found
- fix: auto-format files and re-stage them

Also addresses PR feedback:
- Generate hook into build tree, copy to source tree for out-of-source builds
- Use repo-local tools/clang-format.exe instead of LLVM_INSTALL_DIR path
- Use @ONLY in configure_file to avoid shell variable substitution issues
- Document modes in dev-loop.md and UserConfig.cmake.sample

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-09 13:31:21 -07:00

58 lines
1.9 KiB
Bash

#!/bin/sh
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE in the project root for license information.
#
# Pre-commit hook: validates clang-format on staged C/C++ files.
# Generated by CMake from tools/hooks/pre-commit.in
# Install with: tools\SetupClangFormat.bat
#
# Mode: @WSL_PRE_COMMIT_MODE@ (set WSL_PRE_COMMIT_MODE in UserConfig.cmake)
# warn - report formatting issues without blocking the commit (default)
# error - block the commit when formatting issues are found
# fix - automatically fix formatting and re-stage files
MODE="@WSL_PRE_COMMIT_MODE@"
REPO_ROOT="$(git rev-parse --show-toplevel)"
CLANG_FORMAT="$REPO_ROOT/tools/clang-format.exe"
# --- Collect staged C/C++ source files ---
STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(c|cpp|cxx|h|hpp|hxx)$')
if [ -z "$STAGED" ]; then
exit 0
fi
# --- Verify clang-format is available ---
if [ ! -f "$CLANG_FORMAT" ]; then
echo "[pre-commit] clang-format not found, skipping. Run 'cmake .' to set up."
exit 0
fi
# --- fix mode: format in-place and re-stage ---
if [ "$MODE" = "fix" ]; then
echo "[pre-commit] Fixing formatting..."
echo "$STAGED" | while IFS= read -r file; do
"$CLANG_FORMAT" --style=file -i "$REPO_ROOT/$file"
git add "$REPO_ROOT/$file"
done
echo "[pre-commit] Formatting applied and files re-staged."
exit 0
fi
# --- warn / error mode: check formatting ---
echo "[pre-commit] Checking formatting (mode: $MODE)..."
FILES=$(echo "$STAGED" | sed "s|^|$REPO_ROOT/|")
echo "$FILES" | xargs "$CLANG_FORMAT" --style=file -Werror --dry-run 2>&1
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo ""
echo "[pre-commit] Formatting errors found. Run to fix:"
echo " powershell FormatSource.ps1 -Staged \$true"
if [ "$MODE" = "error" ]; then
exit 1
fi
echo "[pre-commit] Continuing commit (mode: warn)."
else
echo "[pre-commit] All checks passed."
fi