Git hooks

\(\DeclareMathOperator{\Spec}{Spec}\) \(\DeclareMathOperator{\Proj}{Proj}\) \(\DeclareMathOperator{\dom}{dom}\) \(\DeclareMathOperator{\ran}{ran}\) \(\DeclareMathOperator{\ar}{ar}\) \(\DeclareMathOperator{\var}{var}\) \(\DeclareMathOperator{\pred}{Pred(V,\mathcal{R})}\) \(\DeclareMathOperator{\encode}{encode}\) \(\DeclareMathOperator{\decode}{decode}\) \(\DeclareMathOperator{\supp}{supp}\) \(\DeclareMathOperator{\lcm}{lcm}\) \(\DeclareMathOperator{\seq}{seq}\) \(\DeclareMathOperator{\var}{var}\)

1. Pre-commit hooks

Some quick pre-commit hooks that I have found useful.

You can drop scripts like the ones below under .git/hooks/pre-commit for example; it should have the executable bit set with chmod +x .git/hooks/pre-commit.

1.1. Format Python with black

This script will run the black source code formatter on the git diffs of Python files only. It seems overly complicated because I tried to avoid certain issues 1

#!/bin/sh

if ! command -v black > /dev/null 2>&1; then
    printf "black is not installed. See <%s>." \
           "https://black.readthedocs.io/en/stable/" 2>&1
    exit 1
fi
unset -v GIT_LITERAL_PATHSPECS
staged=$(git diff -z --name-only --staged -- '*.py' | base64)
printf "%s" "$staged" | base64 -d | xargs -0 black -q
modified=$(git diff -z --name-only --diff-filter=M -- '*.py' | base64)
printf "%s" "$staged" | base64 -d \
    | (printf "%s" "$modified" | base64 -d && cat) \
    | sort -z | uniq -z -d \
    | xargs -0 git add

1.2. Format C and C++ with clang-format

This script will run clang-format on the git diffs of C and C++ files (source and header) only. It doesn't work for tricky filenames that contain newlines, so do not use it with untrusted repositories.

#!/bin/sh

if ! command -v clang-format > /dev/null 2>&1; then
  printf "clang-format is not installed. See <%s>." \
         "https://clang.llvm.org/docs/ClangFormat.html" 2>&1
  exit 1
fi
git clang-format --staged \
  | tail -n +2 \
  | xargs git add

Footnotes:

1

See the article Filenames and Pathnames in Shell: How to do it Correctly by David A. Wheeler.