From 6c4e946e27954dd5dfc36feeebc50833ae2c3c20 Mon Sep 17 00:00:00 2001 From: Arthur Tazhitdinov Date: Wed, 22 Apr 2026 23:20:03 +0300 Subject: [PATCH] chore: git pre-commit hook for format fix (#1730) ## Summary * Adds pre-commit git hook that automatically runs ./bin/clang-format-fix --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**< YES >**_ --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .githooks/pre-commit | 26 +++++++++++++++++++++++ bin/clang-format-fix | 7 ++++++ docs/contributing/development-workflow.md | 1 + docs/contributing/getting-started.md | 7 ++++++ 4 files changed, 41 insertions(+) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 000000000..6943ec361 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Run formatter from repository root regardless of current directory. +REPO_ROOT="$(git rev-parse --show-toplevel)" +cd "${REPO_ROOT}" + +# Capture the files already staged for commit so we only re-stage those +# paths after formatting. +staged_files=() +while IFS= read -r -d '' file; do + staged_files+=("${file}") +done < <(git diff --cached --name-only -z --diff-filter=ACMR) + +# Intentionally format all currently modified tracked C/C++ files. +# The helper handles no-op cases and exits 0 when nothing matches. +echo "Running clang-format fix before commit..." +./bin/clang-format-fix + +# Ensure formatting changes are included in the pending commit without +# staging unrelated tracked modifications from other files in the +# working tree. +if ((${#staged_files[@]})); then + git add -- "${staged_files[@]}" +fi \ No newline at end of file diff --git a/bin/clang-format-fix b/bin/clang-format-fix index d4902eb8d..aea136fee 100755 --- a/bin/clang-format-fix +++ b/bin/clang-format-fix @@ -14,6 +14,7 @@ fi set -euo pipefail GIT_LS_FILES_FLAGS="" +# -g scopes formatting to tracked files currently modified in git status. if [[ "${1:-}" == "-g" ]]; then GIT_LS_FILES_FLAGS="--modified" fi @@ -21,6 +22,7 @@ fi CLANG_FORMAT_VERSION_RAW="$(${CLANG_FORMAT_BIN} --version)" CLANG_FORMAT_MAJOR="$(printf '%s\n' "${CLANG_FORMAT_VERSION_RAW}" | grep -oE '[0-9]+' | head -n1)" +# Guard against local binaries older than the repo formatting config. if [[ -z "${CLANG_FORMAT_MAJOR}" || "${CLANG_FORMAT_MAJOR}" -lt 21 ]]; then echo "Error: ${CLANG_FORMAT_BIN} is too old: ${CLANG_FORMAT_VERSION_RAW}" echo "This repository's .clang-format requires clang-format 21 or newer." @@ -37,9 +39,14 @@ fi # --exclude-standard: ignores files in .gitignore # Additionally exclude files in 'lib/EpdFont/builtinFonts/' as they are script-generated. # Also exclude files in 'lib/Epub/Epub/hyphenation/generated/' as they are script-generated. +# Keep the no-match case non-fatal: grep returns 1 when no files match, +# which is expected when there are no modified C/C++ files. +set +o pipefail git ls-files --exclude-standard ${GIT_LS_FILES_FLAGS} \ | grep -E '\.(c|cpp|h|hpp)$' \ | grep -v -E '^lib/EpdFont/builtinFonts/' \ | grep -v -E '^lib/Epub/Epub/hyphenation/generated/' \ | grep -v -E '^lib/uzlib/' \ | xargs -r "${CLANG_FORMAT_BIN}" -style=file -i +# Restore strict pipeline failure handling for the rest of the script. +set -o pipefail diff --git a/docs/contributing/development-workflow.md b/docs/contributing/development-workflow.md index 66a18917d..ab7d64f83 100644 --- a/docs/contributing/development-workflow.md +++ b/docs/contributing/development-workflow.md @@ -6,6 +6,7 @@ This page defines the expected local workflow before opening a pull request. - Fork the repository to your own GitHub account - Clone your fork locally and add the upstream repository if needed +- Enable repo hooks once per clone: `git config core.hooksPath .githooks && chmod +x .githooks/pre-commit` - Branch from `master` - Keep each PR focused on one fix or feature area diff --git a/docs/contributing/getting-started.md b/docs/contributing/getting-started.md index 715ab18a4..299a23a1d 100644 --- a/docs/contributing/getting-started.md +++ b/docs/contributing/getting-started.md @@ -53,6 +53,13 @@ If you already cloned without submodules: git submodule update --init --recursive ``` +Enable the repository-managed Git hooks (required once per clone): + +```sh +git config core.hooksPath .githooks +chmod +x .githooks/pre-commit +``` + ## Build ```sh