From bfa2fc8976ae781fb7c1ff0b543399fe64da3a3f Mon Sep 17 00:00:00 2001 From: Stephen Nicholas Swatman Date: Wed, 27 Nov 2024 15:24:37 +0100 Subject: [PATCH] Move clang-format checks to pre-commit This will make them significantly easier for users to use, as well as easier to migrate to future versions. --- .githooks/README.md | 21 ---------- .githooks/pre-commit | 79 ------------------------------------ .github/check_format.sh | 46 --------------------- .github/workflows/checks.yml | 21 ++++++++-- .pre-commit-config.yaml | 7 ++++ README.md | 19 +++++++++ 6 files changed, 43 insertions(+), 150 deletions(-) delete mode 100644 .githooks/README.md delete mode 100755 .githooks/pre-commit delete mode 100755 .github/check_format.sh create mode 100644 .pre-commit-config.yaml diff --git a/.githooks/README.md b/.githooks/README.md deleted file mode 100644 index f7df095826..0000000000 --- a/.githooks/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# traccc git hooks - -This directory stores some useful hooks for traccc developers. To install one of -these hooks, run the following command (from the repository root): - - ln -s $(pwd)/.githooks/pre-commit .git/hooks - -If you are using a modern version of coreutils and you need relative paths, for -example if your mount points may change, use: - - ln -rs .githooks/pre-commit .git/hooks - -To install all hooks in this repository, you can also run: - - git config --local core.hooksPath .githooks - -## Requirements - -These hooks require clang-format to be installed, and findable. Either -`clang-format` needs to be a binary findable by bash, or the -`CLANG_FORMAT_BINARY` environment variable must be set to a clang-format binary. diff --git a/.githooks/pre-commit b/.githooks/pre-commit deleted file mode 100755 index 7f091a0e06..0000000000 --- a/.githooks/pre-commit +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash - -# TRACCC library, part of the ACTS project (R&D line) -# (c) 2021 CERN for the benefit of the ACTS project -# Mozilla Public License Version 2.0 - -# This pre-commit hook checks the formatting of the code according to the -# .clang-format file present in the repository. To use this hook, you will need -# clang-format installed, and one of the following must be true: -# 1. clang-format is binary that can be located by the shell. -# 2. The CLANG_FORMAT_BINARY environment variable is set. - -# Throughout this script, we cannot afford to have any of our commands fail, so -# we exit immediately if any errors do happen. -set -e - -# Use the portable mktemp command to create a temporary into which we will write -# some of our temporary files. -TMP_DIR=$(mktemp -d) - -# Declare a function that removes the just-created temporary directory. -function finish { - rm -rf "${TMP_DIR}" -} - -# Ensure that the temporary directory is cleared out if the script exits for any -# reason, either through exiting naturally, or if there are any errors. -trap finish EXIT - -# Establish which clang-format binary we want to use. -BINARY=${CLANG_FORMAT_BINARY:-clang-format} - -# Determine which files have changed in the index. -COPY_FILES=$(git diff --name-only --cached) - -# If the index is empty, then we have nothing to do. We will pass control back -# to git itself, so it can handle this strange state from here. -if [[ -z ${COPY_FILES} ]]; then - exit 0 -fi - -# Create a copy of the repository, using only the files that are changed in the -# index, in our temporary directory. -git checkout-index --prefix=${TMP_DIR}/old/ ${COPY_FILES} - -# Make sure our new directory exists. Git will not create the directory if the -# index is empty, so we will need to check for this. -if ! [[ -d "${TMP_DIR}/old/" ]]; then - echo "ERROR: Temporary directory was not created. Empty index?" - exit 1 -fi - -# Make a copy of our new index directory, so we can later compare them. -cp -r ${TMP_DIR}/old/ ${TMP_DIR}/new/ - -# Copy the clang-format configuration from the git repository. -cp $(git rev-parse --show-toplevel)/.clang-format ${TMP_DIR} - -# Find the list of files we would like to check. -CHECK_FILES=$(find ${TMP_DIR}/new/ \( -iname '*.cpp' -or -iname '*.hpp' -or -iname '*.ipp' -or -iname '*.cu' -or -iname '*.cuh' -or -iname '*.hip' -or -iname '*.sycl' \)) - -# If there is not a single file we might want to format, we can just exit. If we -# don't, clang-format will whinge at us and we don't want that, now do we? -if [[ -z ${CHECK_FILES} ]]; then - exit 0 -fi - -# Run clang-format on one of the copies of our index, editing the files -# in-place. Because we have two copies of the index but we are only formatting -# one, we can later compare them to see the differences! -$BINARY -i -style=file ${CHECK_FILES} - -# Establish the difference between the two copies of our index. If there are any -# formatting mistakes, these two directories will differ. If they are the same, -# this will print nothing and return 0. In that case, the script exits naturally -# with a zero error code. If there is a difference, then this will print the -# diff and return a non-zero code. Because we have set the -e flag earlier, this -# will also exit the hook, preventing a commit. -diff -u --color -r ${TMP_DIR}/old/ ${TMP_DIR}/new/ diff --git a/.github/check_format.sh b/.github/check_format.sh deleted file mode 100755 index 46936a445f..0000000000 --- a/.github/check_format.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -# -# check that all code complies w/ the clang-format specification -# -# if all is well, returns w/o errors and does not print anything. -# otherwise, return an error and print offending changes - -set -e # abort on error - -INCLUDE_DIRS=("core device examples io tests performance plugins simulation benchmarks") - -if [ $# -ne 1 ]; then - echo "wrong number of arguments" - echo "" - echo "usage: check_format " - exit 1 -fi - -_binary=${CLANG_FORMAT_BINARY:-clang-format} - -$_binary --version - -cd $1 -$_binary -i -style=file $(find ${INCLUDE_DIRS} \( -iname '*.cpp' -or -iname '*.hpp' -or -iname '*.ipp' -or -iname '*.cu' -or -iname '*.cuh' -or -iname '*.hip' -or -iname '*.sycl' \)) - -if ! [ -z $CI ] || ! [ -z $GITHUB_ACTIONS ]; then - mkdir changed - for f in $(git diff --name-only -- ${INCLUDE_DIRS[@]/#/:/}); do - cp --parents $f changed - done -fi - -echo "clang-format done" - -set +e -git diff --exit-code --stat -- ${INCLUDE_DIRS[@]/#/:/} -result=$? - -if [ "$result" -eq "128" ]; then - echo "Format was successfully applied" - echo "Could not create summary of affected files" - echo "Are you in a submodule?" - -fi - -exit $result diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 840b4c2c69..54bcc09924 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -9,8 +9,21 @@ on: jobs: format: runs-on: ubuntu-latest - container: ghcr.io/acts-project/format10:v11 + env: + PRE_COMMIT_HOME: '/tmp/pre-commit' + steps: - - uses: actions/checkout@v3 - - name: Check - run: .github/check_format.sh . + - name: Checkout + uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - uses: actions/cache@v4 + with: + path: | + ${{ env.PRE_COMMIT_HOME }} + key: ${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }} + - name: Install pre-commit + run: pip install pre-commit + - name: Run pre-commit + run: pre-commit run --all-files --show-diff-on-failure diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..f71a2ef14d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v10.0.1 + hooks: + - id: clang-format + types_or: [file] + files: \.(cpp|hpp|ipp|cu|cuh|sycl|hip)$ diff --git a/README.md b/README.md index e9fa9b8623..8ce890d7a1 100644 --- a/README.md +++ b/README.md @@ -324,6 +324,25 @@ Attaching file performance_track_finding.root as _file0... root [1] finding_trackeff_vs_eta->Draw() ``` +## Contributing + +### Code formatting + +The traccc code is formatted using clang-format; the recommended way to ensure that your code is properly formatted is to use [pre-commit](https://pre-commit.com/). The pre-commit webpage has a useful guide for using the tool, but the simplest way of using it (without installing it as a pre-commit hook) is as follows. First, install the tool with your favourite Python package manager: + +```console +# With pip +$ pip install pre-commit +# With pipx +$ pip install pre-commit +``` + +The install step needs to be executed only once. After that, the code can be easily formatted as follows: + +```console +$ pre-commit run --all-files +``` + ## Continuous benchmark Monitoring the event throughput of track reconstruction with the toy geometry