Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 150 lines (132 sloc) 4.73 KB
#!/usr/bin/env bash
#
# A Git pre-commit hook that checks for syntax errors
# for: Ruby, JavaScript, Python, Bash, Go, (Cake)PHP, and HTML
# based on the extensions of staged files in Git.
# Can be 'installed globally' as of Git 1.7.1 using init.templatedir
#
# Copyright 2013, kvz (http://twitter.com/kvz)
set -o pipefail
set -o errexit
set -o nounset
# set -o xtrace
__DIR__="$(cd "$(dirname "${0}")"; echo $(pwd))"
__BASE__="$(basename "${0}")"
__FILE__="${__DIR__}/${__BASE__}"
if [ -x "${__DIR__}/pre-ochtra" ]; then
echo "Running pre-ochtra"
if ! ${__DIR__}/pre-ochtra; then
echo "pre-ochtra failed"
exit 1
fi
fi
# Takes a command as arguments and paints both it's STDOUT & STDERR in
# colors specified in first and second arguments. Use 'purge' to skip printing
# at all
function paint() (
set -o pipefail;
green=$'s,.*,\x1B[32m&\x1B[m,'
red=$'s,.*,\x1B[31m&\x1B[m,'
gray=$'s,.*,\x1B[37m&\x1B[m,'
purge="/.*/d"
stdout="${!1}"
stderr="${!2}"
("${@:3}" 2>&1>&3 |sed ${stderr} >&2) 3>&1 \
|sed ${stdout}
)
# Necessary check for initial commit
against="4b825dc642cb6eb9a060e54bf8d69288fbee4904"
git rev-parse --verify HEAD >/dev/null 2>&1 && against="HEAD"
# Only run when we're on a branch (to avoid rebase hell)
# http://git-blame.blogspot.nl/2013/06/checking-current-branch-programatically.html
# --short is not supported on older git versions so using awk here
if branch=$(git symbolic-ref -q HEAD |awk -F/ '{print $NF}'); then
echo on branch $branch
else
echo not on any branch
exit 0
fi
# (A)dded (C)opied or (M)odified
git diff-index --cached --full-index --diff-filter=ACM $against |while read -r line; do
mod="$(echo ${line} |cut -d' ' -f2)"
sha="$(echo ${line} |cut -d' ' -f4)"
sts="$(echo ${line} |cut -d' ' -f5)"
pth="$(echo ${line} |cut -d' ' -f6-)"
ext="${pth##*.}"
she=""
# only check shebang on normal and executable files
if [ "${mod}" = "100644" ] || [ "${mod}" = "100664" ] || [ "${mod}" = "100455" ]; then
she="$(head -n1 ${pth} |awk -F/ '/^#\!/ {print $NF}' |sed 's/^env //g')"
fi
out="purge"
err="red"
cmd=""
tmp=""
# Select linting tool based on extension or shebang
if [ "${ext}" = "rb" ] || [ "${ext}" = "erb" ] || [ "${she}" = "ruby" ]; then
cmd="ruby -c -"
elif [ "${ext}" = "js" ] || [ "${she}" = "node" ]; then
# jshint unfortunately uses STDOUT for errors, so paint all red
cmd="jshint -"
out="red"
elif [ "${ext}" = "es6" ] || [ "${she}" = "node" ]; then
# eslint need to be in localfolder, for example using npm install peasant
# if use global installed eslint not works with .eslintrc
# cmd="node_modules/.bin/eslint --stdin"
# or use global without .eslintrc
cmd="eslint --stdin --no-eslintrc"
out="red"
elif [ "${ext}" = "ts" ] ; then
tmp="${TMPDIR:-/tmp}/${$}.${ext}"
cmd="tslint ${tmp}"
elif [ "${ext}" = "coffee" ] || [ "${she}" = "coffee" ]; then
# coffeelint unfortunately uses STDOUT for errors, so paint all red
cmd="coffeelint --quiet --stdin"
out="red"
elif [ "${ext}" = "py" ] || [ "${she}" = "python" ]; then
tmp="${TMPDIR:-/tmp}/${$}.${ext}"
cmd="pylint --errors-only ${tmp}"
out="red"
elif [ "${ext}" = "go" ]; then
cmd="gofmt -e"
elif [ "${she}" = "sh" ]; then
cmd="sh -n"
elif [ "${ext}" = "php" ] || [ "${ext}" = "ctp" ] || [ "${she}" = "php" ]; then
cmd="php -n -l -ddisplay_errors=1 -derror_reporting=E_ALL -dlog_errors=0"
elif [ "${ext}" = "pl" ] || [ "${she}" = "perl" ]; then
cmd="perl -wc -"
elif [ "${ext}" = "xml" ] || [ "${ext}" = "xsl" ] || [ "${ext}" = "xslt" ]; then
cmd="xmllint --noout -"
elif [ "${ext}" = "json" ]; then
cmd="jsonlint"
elif [ "${ext}" = "yaml" ] || [ "${ext}" = "yml" ]; then
tmp="${TMPDIR:-/tmp}/${$}.${ext}"
cmd="js-yaml ${tmp}"
elif [ "${ext}" = "html" ] || [ "${ext}" = "htm" ] || [ "${ext}" = "shtml" ]; then
cmd="htmlhint stdin"
out="red"
elif [ "${she}" = "bash" ]; then
cmd="bash -n"
fi
if [ -n "${cmd}" ]; then
tool="$(echo "${cmd}" |cut -d' ' -f1)"
paint "gray" "red" echo "--> ${tool} syntax checking for ${pth}"
else
paint "gray" "red" echo "--> No syntax checking for ${pth}"
continue
fi
# require linting tool
if ! which "${tool}" >/dev/null 2>&1; then
paint "red" "red" echo "Please install ${tool} for pre-commit syntax checking. "
exit 1
fi
# execute on staged buffer
[ -n "${tmp}" ] && git cat-file -p ${sha} > "${tmp}"
if ! git cat-file -p ${sha} |paint ${out} ${err} ${cmd}; then
paint "red" "red" echo "Please fix ${tool} syntax errors and type 'git add ${pth}'"
[ -n "${tmp}" ] && rm -f "${tmp}"
exit 1
fi
[ -n "${tmp}" ] && rm -f "${tmp}"
paint "green" "red" echo "No ${tool} syntax errors detected in '${pth}'"
done