From 700cd2f63bfb80cd77a0587cbbd8f0439b8c9c9f Mon Sep 17 00:00:00 2001
From: Christoph Lehmann <christoph.lehmann@ufz.de>
Date: Mon, 31 Jul 2017 13:09:37 +0200
Subject: [PATCH] code formatting scripts and instructions

---
 .../clang-format-pre-commit-hook/README.md    | 37 +++++++++
 .../clang-format-pre-commit-hook/pre-commit   | 80 +++++++++++++++++++
 .../clang-format-series-of-commits/README.md  | 33 ++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 dev/code-formatting/clang-format-pre-commit-hook/README.md
 create mode 100755 dev/code-formatting/clang-format-pre-commit-hook/pre-commit
 create mode 100644 dev/code-formatting/clang-format-series-of-commits/README.md

diff --git a/dev/code-formatting/clang-format-pre-commit-hook/README.md b/dev/code-formatting/clang-format-pre-commit-hook/README.md
new file mode 100644
index 0000000..11e53d4
--- /dev/null
+++ b/dev/code-formatting/clang-format-pre-commit-hook/README.md
@@ -0,0 +1,37 @@
+# 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).
diff --git a/dev/code-formatting/clang-format-pre-commit-hook/pre-commit b/dev/code-formatting/clang-format-pre-commit-hook/pre-commit
new file mode 100755
index 0000000..bd1502d
--- /dev/null
+++ b/dev/code-formatting/clang-format-pre-commit-hook/pre-commit
@@ -0,0 +1,80 @@
+#!/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 --
diff --git a/dev/code-formatting/clang-format-series-of-commits/README.md b/dev/code-formatting/clang-format-series-of-commits/README.md
new file mode 100644
index 0000000..9122c5d
--- /dev/null
+++ b/dev/code-formatting/clang-format-series-of-commits/README.md
@@ -0,0 +1,33 @@
+# 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"
+```
-- 
GitLab