Created
December 17, 2013 15:54
-
-
Save kvz/8007150 to your computer and use it in GitHub Desktop.
Continuing development here https://github.com/kvz/dotfiles/blob/master/.gittemplate/hooks/pre-commit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# A Git pre-commit hook that checks for syntax errors | |
# for: Ruby, JavaScript, Python, Bash, and (Cake)PHP | |
# 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) | |
# | |
# Some common caveats have been taken care of: | |
# - Works with files that contain spaces | |
# - Works on initial commits | |
# - Will skip files that are about to be deleted | |
# - Uses file as staged in git, not how it currently is in your working dir | |
# | |
# Focussed on not committing syntax errors to repositories | |
# and should not have strong opinions on coding style, though | |
# could be modified to have them. | |
# | |
# Some language checks are very basic still. I'm welcoming improvements on | |
# https://github.com/kvz/dotfiles/blob/master/.gittemplate/hooks/pre-commit | |
# | |
# To install standalone (without the spaceship that is my dotfiles/install.sh) | |
# type: | |
# $ mkdir -p ~/.gittemplate/hooks | |
# $ curl https://raw.github.com/kvz/dotfiles/master/.gittemplate/hooks/pre-commit -ko ~/.gittemplate/hooks/pre-commit && chmod 755 $_ | |
# $ git config --global init.templatedir '~/.gittemplate' | |
# | |
# Now in new (or existing) repos, type | |
# $ git init | |
# | |
# To reset all hooks by template in an existing repo type | |
# $ rm .git/hooks/* && git init | |
# | |
# This will copy any non-existing files in ~/.gittemplate into your | |
# new/current repo's .git dir. This only works from git 1.7.1 and up | |
# | |
# Warnings | |
# - Assumes BASH in case of *.sh files. If you are into Dash you | |
# should change that | |
# | |
# Prior Art | |
# - http://mark-story.com/posts/view/using-git-commit-hooks-to-prevent-stupid-mistakes | |
# - http://stackoverflow.com/a/8842663/151666 | |
# - https://github.com/phpbb/phpbb/blob/develop-olympus/git-tools/hooks/pre-commit | |
# Necessary check for initial commit | |
against="4b825dc642cb6eb9a060e54bf8d69288fbee4904" | |
git rev-parse --verify HEAD > /dev/null 2>&1 && against="HEAD" | |
function i_can_haz() { | |
which "${1}" > /dev/null 2>&1 || emergency "Please install ${1} for pre-commit syntax checking. " | |
} | |
function stdcolors() ( | |
set -o pipefail; | |
("$@" 2>&1>&3 | sed $'s,.*,\e[31m&\e[m,' >&2) 3>&1 \ | |
| sed $'s,.*,\e[32m&\e[m,' | |
) | |
function info() { | |
echo -e "\x1B[32m${@}\x1B[0m" | |
} | |
function debug() { | |
echo -e "\x1B[37m${@}\x1B[0m" | |
} | |
function error() { | |
echo -e "\x1B[31m${@}\x1B[0m" | |
} | |
function emergency() { | |
error "${@}" | |
exit 1 | |
} | |
# (A)dded (C)opied or (M)odified | |
git diff-index --cached --full-index --diff-filter=ACM $against | while read -r line; do | |
sha1="$(echo ${line} | cut -d' ' -f4)" | |
stat="$(echo ${line} | cut -d' ' -f5)" | |
file="$(echo ${line} | cut -d' ' -f6-)" | |
# debug "--> Syntax check for ${stat}:${file}=${sha1}, " | |
case "${file}" in | |
*.rb|*.erb) | |
i_can_haz ruby | |
git cat-file -p ${sha1} \ | |
| (stdcolors ruby -c > /dev/null \ | |
&& info "No syntax errors detected in ${file}") \ | |
|| emergency "Please fix errors, type 'git add ${file}', and try again. " | |
;; | |
*.js) | |
i_can_haz jshint | |
git cat-file -p ${sha1} \ | |
| (stdcolors jshint - > /dev/null \ | |
&& info "No syntax errors detected in ${file}") \ | |
|| emergency "Please fix errors, type 'git add ${file}', and try again. " | |
;; | |
*.coffee) | |
i_can_haz coffeelint | |
# coffeelint unfortunately uses STDOUT for errors, so no coloring | |
git cat-file -p ${sha1} \ | |
| (coffeelint --stdin \ | |
&& info "No syntax errors detected in ${file}") \ | |
|| emergency "Please fix errors, type 'git add ${file}', and try again. " | |
;; | |
*.py) | |
i_can_haz pylint | |
git cat-file -p ${sha1} \ | |
| (stdcolors pylint - > /dev/null \ | |
&& info "No syntax errors detected in ${file}") \ | |
|| emergency "Please fix errors, type 'git add ${file}', and try again. " | |
;; | |
*.bash|*.sh) | |
i_can_haz bash | |
git cat-file -p ${sha1} \ | |
| (stdcolors bash -n - > /dev/null \ | |
&& info "No syntax errors detected in ${file}") \ | |
|| emergency "Please fix errors, type 'git add ${file}', and try again. " | |
;; | |
*.ctp|*.php) | |
i_can_haz php | |
git cat-file -p ${sha1} \ | |
| (stdcolors php -n -l -ddisplay_errors=1 -derror_reporting=E_ALL -dlog_errrors=0 > /dev/null \ | |
&& info "No syntax errors detected in ${file}") \ | |
|| emergency "Please fix errors, type 'git add ${file}', and try again. " | |
;; | |
*) | |
# debug "Skipped as there is no handler for this extension" | |
;; | |
esac | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment