Skip to content

Instantly share code, notes, and snippets.

@MBoldyrev
Last active February 4, 2020 09:49
Show Gist options
  • Save MBoldyrev/2f7a123fcfa278ec86b204b0c33d6cc9 to your computer and use it in GitHub Desktop.
Save MBoldyrev/2f7a123fcfa278ec86b204b0c33d6cc9 to your computer and use it in GitHub Desktop.
git hook to check c++ formatting
#!/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.
prompt_confirm() {
while true; do
read -r -n 1 -p "${1:-Continue?} [y/n]: " REPLY
case $REPLY in
[yY]) echo ; return 0 ;;
[nN]) echo ; return 1 ;;
*) printf " \033[31m %s \n\033[0m" "invalid input"
esac
done
}
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(git hash-object -t tree /dev/null)
fi
# Redirect output to stderr and input from console
exec 1>&2 < /dev/tty
set -a unformatted_files
FORMATTER=clang-format-7
while IFS= read -r -d '' fn; do
diff=$(diff <(git show :"$fn") <(git show :"$fn" | ${FORMATTER}))
if [[ ! -z "$diff" ]]; then
#if git show :${fn} | ${FORMATTER} -output-replacements-xml | grep -q '</replacement>'; then
unformatted_files+=("$fn")
echo
echo Need to format ${fn}:
echo "$diff"
fi
done < <(git diff --cached --name-only --diff-filter=ACMR -z $against -- '*.[ch]pp')
if [ ${#unformatted_files[@]} -ne 0 ]; then
echo
echo "There are unformatted files:"
printf '%s\n' "${unformatted_files[@]}"
unstaged_changes_in_unformatted_files=$(comm -12 <(git diff --name-only) <(printf '%s\n' "${unformatted_files[@]}"))
if [[ ! -z $unstaged_changes_in_unformatted_files ]]; then
echo
echo Can not run formatting because there are unstaged changes in unformatted files:
echo "$unstaged_changes_in_unformatted_files"
echo
exit 1
fi
format_command="${FORMATTER} -i ${unformatted_files[@]}"
echo
if prompt_confirm "Apply formatting?"; then
echo Applying formatting:
echo $format_command
$format_command
git add ${unformatted_files[@]}
if git diff --cached --name-only '*.[ch]pp' | sed 's/^/:/' | xargs git show | ${FORMATTER} -output-replacements-xml | grep -q '</replacement>'; then
echo Aw, there are still some unformatted files. Please check manually.
exit 1
fi
else
echo You can still apply it manually with:
echo $format_command
exit 1
fi
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment