Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

set -euo pipefail

repo_root="$(git rev-parse --show-toplevel)"
"${repo_root}/bin/format-staged-files.sh"
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ Tips for git management are found on the corresponding [wiki page](https://githu

Tips for code formatting are found on the corresponding [wiki page](https://github.com/JETSCAPE/X-SCAPE/wiki/Doc.Policy.CodeFormatting).

### Optional Local git Hooks

Enable a local formatter hook that runs on staged files before commit.
This is useful for catching formatting issues early, but remains optional.

Setup:
```
./bin/setup-hooks.sh
```

Notes:
- The setup-hooks script only needs to be run once per clone.
- The hook formats CMake files and C++ files in `src/` and `examples/`.
- The hook only checks staged files.
- Requires `clang-format` (v14) and `cmake-format` (v0.6.13) on PATH.
- Ubuntu / Debian: `sudo apt install clang-format-14 cmake-format`
- Package manager commands for other distributions may differ.
- `pip3 install clang-format==14.0.6 cmakelang` can be used.
- If using pip3, add the pip bin directory to the PATH, e.g. `export PATH="$HOME/.local/bin:$PATH"`.
- Skip hooks for one commit with `git commit --no-verify`.
- To disable permanently, unset hooks with `git config --unset core.hooksPath`.

## Unit Tests

Please also see the [Unit Tests](https://github.com/JETSCAPE/X-SCAPE/wiki/Doc.Policy.UnitTests) page for details about writing unit tests to accompany your code contributions.
Expand Down
14 changes: 4 additions & 10 deletions bin/codebase-format-helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,11 @@ function look_for_files_to_format()
)
elif [[ ${language} = 'CMake' ]]; then
FILES_TO_FORMAT=(
"${base_dir}"/**/CMakeLists.txt
"${base_dir}"/**/*.cmake
"${base_dir}"/CMakeLists.txt
"${base_dir}"/{src,examples}/**/CMakeLists.txt
"${base_dir}"/{src,examples}/**/*.cmake
"${base_dir}"/cmakemodules/**/*.cmake
)
for index in "${!FILES_TO_FORMAT[@]}"; do
if [[ ${FILES_TO_FORMAT[index]} =~ ^${base_dir}/3rdparty/(Cuba[^/]*/|CMakeLists.txt$) ]]; then
continue
elif [[ ${FILES_TO_FORMAT[index]} =~ ^${base_dir}/(3rdparty|build[^/]*)/ ]]; then
unset -v 'FILES_TO_FORMAT[index]'
fi
done
FILES_TO_FORMAT=("${FILES_TO_FORMAT[@]}")
fi
}

Expand Down
64 changes: 64 additions & 0 deletions bin/format-staged-files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash

set -euo pipefail

if ! command -v clang-format >/dev/null 2>&1 || ! command -v cmake-format >/dev/null 2>&1; then
cat >&2 <<'EOF'
Formatter tools not found. Install them:
Ubuntu/Debian: sudo apt install clang-format-14 cmake-format
EOF
exit 1
fi

repo_root="$(git rev-parse --show-toplevel)"
cd "${repo_root}"

mapfile -t staged_files < <(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null || true)
if [[ ${#staged_files[@]} -eq 0 ]]; then
exit 0
fi

cpp_ext='(h|hpp|c|cc|cpp)$'
cmake_re='(^|/)CMakeLists\.txt$|\.cmake$'

selected_files=()
for f in "${staged_files[@]}"; do
# Skip build folder and external packages
if [[ "${f}" == build/* || "${f}" == external_packages/* ]]; then
continue
fi

# Include files matching CMakeLists.txt or .cmake
if [[ "${f}" =~ ${cmake_re} ]]; then
selected_files+=("${f}")
continue
fi

# Include source files from src/ and examples/
if [[ "${f}" =~ \.${cpp_ext} ]] && [[ "${f}" == src/* || "${f}" == examples/* ]]; then
selected_files+=("${f}")
fi
done

if [[ ${#selected_files[@]} -eq 0 ]]; then
exit 0
fi

# format the selected files
for f in "${selected_files[@]}"; do
if [[ "${f}" =~ ${cmake_re} ]]; then
cmake-format -i "${f}"
else
clang-format -i -style=file "${f}"
fi
done

# restage if changed
if ! git diff --quiet -- "${selected_files[@]}"; then
git add -- "${selected_files[@]}"
cat >&2 <<'EOF'
Formatting hook changed and restaged files.
EOF
fi

exit 0
32 changes: 32 additions & 0 deletions bin/setup-hooks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ ! -d .git ]]; then
echo "Error: Run this script from the repository's root directory." >&2
exit 1
fi

if [[ ! -x .githooks/pre-commit ]]; then
echo "Error: Expected hook .githooks/pre-commit not found." >&2
exit 1
fi

git config core.hooksPath .githooks
echo "Installed optional formatting hook."

if ! command -v clang-format >/dev/null 2>&1 || ! command -v cmake-format >/dev/null 2>&1; then
cat >&2 <<'EOF'
Warning: Formatter utilities not found. Install them with your package manager:
Ubuntu / Debian:
sudo apt install clang-format-14 cmake-format
Package manager commands for other distributions may differ.
pip3 install clang-format==14.0.6 cmakelang can be used.
If using pip3, add the pip bin directory to the PATH, e.g. export PATH="$HOME/.local/bin:$PATH".
After installing the formatter utilities, re-run this setup script.
EOF
exit 1
fi

echo "clang-format and cmake-format are installed."

Loading