#!/bin/sh
# @author Klemens Böswirth <k.boeswirth+git@gmail.com>
# @brief Pre-commit hook that checks formatting
# @date 29.03.2019
# @tags reformat

# HOW TO USE
#
# If this is the only pre-commit hook you want to use,
# you can simply use a symlink:
#
# ln -s ../../scripts/pre-commit-check-formatting .git/hooks/pre-commit
#
# If you want to use multiple pre-commit hooks, you have
# to use a script, that calls all of your hooks, including this one.

DATE=$(date +%s)
SRC_ROOT=$(git rev-parse --show-toplevel)

# check for unstaged changes
UNSTAGED=$(git diff --name-only)
if [ -n "$UNSTAGED" ]; then
	# create temporary commit for staged changes
	git commit --no-verify --message "WIP" --quiet

	# stash away unstaged changes and remember stash id
	echo "$UNSTAGED" | xargs git add
	git stash push -q -m "pre-commit-$DATE"
	UNSTAGED_STASH=$(git rev-parse -q --verify refs/stash)

	# undo temporary commit
	git reset --quiet --soft HEAD^
fi

# ensure that all unstaged changes are gone
if ! git diff --quiet; then
	printf >&2 "Couldn't stash away unstaged changes, aborting!\n"
	exit 1
fi

# get changed files
STAGED_FILES="$(git diff --cached --name-only --diff-filter=ACMR)"

# run reformat script
echo "$STAGED_FILES" | xargs "$SRC_ROOT/scripts/dev/reformat-all" > /dev/null

# get files changed by reformatting
UNFORMATTED_FILES="$(git diff --name-only)"

# create patch
PATCH_FILE="/tmp/elektra-$DATE-reformat.patch"
git diff > "$PATCH_FILE"

# undo formatting
echo "$UNFORMATTED_FILES" | xargs git checkout --quiet --

if [ -n "$UNSTAGED" ]; then
	# convert stash hash to stash ref
	STASH_REF=$(git reflog stash --format='%H %gd' | awk -v h="$UNSTAGED_STASH" '$1 == h { print $2 }')

	# restore unstaged changes
	git stash pop --quiet "$STASH_REF"
fi

if [ -n "$UNFORMATTED_FILES" ]; then
	echo "The following files are not correctly formatted:"
	printf "%s\n" "$UNFORMATTED_FILES"

	echo "A diff of the formatting changes is stored at:"
	echo "$PATCH_FILE"

	PATCH_SCRIPT="/tmp/elektra-$DATE-reformat.patch.sh"
	echo 'OLD_DIR=$(pwd)' > "$PATCH_SCRIPT"
	echo "cd $SRC_ROOT" >> "$PATCH_SCRIPT"
	echo "git apply $PATCH_FILE" >> "$PATCH_SCRIPT"
	echo 'cd $OLD_DIR' >> "$PATCH_SCRIPT"

	echo "You can try to apply it with, but unstaged changes may cause conflicts:"
	echo "sh $PATCH_SCRIPT"

	exit 1
fi
