pre-push
a pre-push git hook that examines files being pushed and aborts by exitting non-zero if necessary
#!/usr/bin/env bash
# A local hook script to detect if a rendered jekyll draft is about to be pushed.
#
# Called by "git push" after it has checked the remote status, but before anything
# has been pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
#
# print meta data
meta_name_value_pairs() {
local f="$1" elem val IFS=$' \t\n>/'
while read -d '<' elem val; do
test "$elem" == '/head' && return
test "$elem" == 'meta' && {
echo $val # echo without quotes to strip $IFS characters
}
done < "$f"
}
# look for name="jekyll-type" draft in the meta content
jekyll_draft_found() {
local file content
if [ $# -gt 0 ]; then # process args on the commandline
while [ $# -gt 0 ]; do
file="$1"
shift
while read content; do
[[ "$content" =~ ^name\s*=\s*\"jekyll-type\" ]] && {
content="${content##*=}"
content="${content//\"/}"
test "$content" == 'draft' && \
echo "$file is a draft" && return 0
}
done < <(meta_name_value_pairs "$file")
done
fi
return 1
}
while read local_ref local_oid remote_ref remote_oid; do
declare -A tags
declare -a missing_tag_files
while read -r file; do
case "$file" in
_site/*.html)
# check for rendered drafts that are about to be pushed
jekyll_draft_found "$file" && {
echo -n 'Continue to push rendered draft(s)? '
read answer < /dev/tty
[[ "$answer" = [Nn]* ]] && exit 1 || echo 'Pushing drafts'
}
;;
*.md)
# collect all tags from front matter and store as
# a slugified key in the bash associative array
while read -r tag; do
tags["$tag"]=1
done < <(collections/_bin/_get-tags "$file")
;;
esac
done < <(git diff --name-only $local_oid $remote_oid)
# make sure each tag has a tags/ page
for tag in "${!tags[@]}"; do
test -e "collections/_tag/$tag.md" || missing_tag_files+=("$tag")
done
test ${#missing_tag_files[@]} -gt 0 && {
echo -n 'missing tag file'
test ${#missing_tag_files[@]} -gt 1 && echo -n 's'
echo ':'
for tag in "${missing_tag_files[@]}"; do
echo -e "\ttags/$tag/index.html"
done
echo -n 'Create missing tag file'
test ${#missing_tag_files[@]} -gt 1 && echo -n 's'
echo -n '? '
read answer < /dev/tty
[[ "$answer" = [Yy]* ]] && collections/_bin/_gen-tags "${missing_tag_files[@]}"
exit 1
}
done
exit 0