Skip to content
Snippets Groups Projects
Commit 700cd2f6 authored by Christoph Lehmann's avatar Christoph Lehmann
Browse files

code formatting scripts and instructions

parent acb4e974
No related branches found
No related tags found
No related merge requests found
# code formatting
This page describes how to set up a pre-commit hook that checks code formatting.
# Disclaimer
No warranty is given that the presented pre-commit hook works as expected and that it does not destroy anything. Use at your own risk!
# Operating system
This should work on Linux.
# Prerequisites
* `git-clang-format` installed somewhere in the `$PATH`. `git-clang-format` might be shipped with `clang` in your distro and is also available from [here](https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git-clang-format).
# Setup
* Save the script `pre-commit` as `.git/hooks/pre-commit` and make it executable
* In order to use format shipped with OGS, you have to execute the following command, which sets up the right settings: `git config --local clangFormat.style file`.
* Now whenever you commit something, its formatting will get checked and the commit is aborted if the formatting does now comply.
# Error message generated by the pre-commit hook
In case reformatting of your code is needed, the pre-commit hook will print the following error message and the commit will be aborted:
```
$ git commit
The code you want to commit needs to be reformatted.
Run the following, then commit:
git add NumLib/Extrapolation/ExtrapolatableElementCollection.h NumLib/Extrapolation/LocalLinearLeastSquaresExtrapolator.cpp && \
git clang-format NumLib/Extrapolation/ExtrapolatableElementCollection.h NumLib/Extrapolation/LocalLinearLeastSquaresExtrapolator.cpp
```
In most cases the last two lines of the error message can be readily copied to your terminal and executed right away. They will fix the code formatting (Note: They won't stage—i.e., `git add`–the changes `clang-format` makes). Afterwards you can commit.
# References
This is based on the pre-commit hook shipped with git and on https://dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html (retrieved 2017-07-24).
#!/bin/bash
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# git diff-index --cached --diff-filter=ACMR --name-only "$against"
# changed_files="`git diff-index --cached --name-only "$against"`"
# echo "$changed_files" | xargs git add --
# Abort if not formatted correctly
# Cf. https://dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html
check_clang_format_diff() {
bad_files=""
while read -r -d '' path; do
diff="`git clang-format --diff -- "$path"`"
case "$diff" in
'no modified files to format') ;;
'clang-format did not modify any files') ;;
*)
bad_files="$bad_files $path"
esac
done
if [ -n "$bad_files" ]; then
cat >&2 <<EOF
The code you want to commit needs to be reformatted.
Run the following, then commit:
git add$bad_files && \\
git clang-format$bad_files
EOF
exit 1
fi
}
git diff-index --cached -z --name-only "$against" \
| check_clang_format_diff \
|| exit 1
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
# Disclaimer
No warranty is given that the presented method works as expected and that it does not destroy anything. Use at your own risk!
# Prerequisites
* `git-clang-format` installed somewhere in the `$PATH`. `git-clang-format` might be shipped with `clang` in your distro and is also available from [here](https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git-clang-format).
# Operating system
This should work on Linux.
# How to apply clang-format to a series of commits?
The following ingredients are needed:
* `git rebase` can execute a command after each commit
* We use that feature (`-x`) to execute `git clang-format` after each commit, which will reformat only the files that changed in that commit.
* Afterwards `git diff` shows the changes introduced by `git clang-format`
* The user is prompted to hit enter, making it possible to examine small diffs, where `git diff` immediately returns.
* Finally the formatting changes are added to the preceding commit
Since `clang-format` changes the formatting after each original commit, it is very likely that it introduces conflicts with the subsequent commits. Since we know that these conflicts are due to (i) changes in formatting in the already rebased commits (ii) more profound changes in the subsequent commits, it is a sensible setting, to just take the changes from the new commits in each conflicting case. This is accomplished by choosing the merge strategy `-X theirs`. :warning: This strategy automatically resolves conflicts, but if the changes in both code and formatting are too complex for the algorithm, it might generate wrong results! Therefore it is recommended to always double-check that the reformatting did not mess anything up!
:warning: If you use the command given below, make sure you have a backup, at least of the branch that you are going to rebase! If you don't understand (even after the explanation) what this command does, you better do not use it!
```{sh}
git rebase -i COMMIT_ONTO_WHICH_TO_REBASE \
-X theirs \
-x "git clang-format HEAD^ \
&& git diff \
&& read -r -p 'Hit enter to continue' \
&& git commit --all --amend --no-edit"
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment