-
Notifications
You must be signed in to change notification settings - Fork 13
/
pre-commit
executable file
·149 lines (132 loc) · 4.73 KB
/
pre-commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/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