-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathpre-commit
executable file
·283 lines (224 loc) · 7.76 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#!/bin/bash
#
# PHP CodeSniffer pre-commit hook for Git
# See README.md for the Drupal-Code Sniffer configuration/setup instructions.
#
# Author: Gerald Z. Villorente
# Co-author: Nikolaos Dimopoulos
# Co-author: Engr. Ranel O. Padon
# Co-Author: Dan Helyar
#
# This project is made possible also through the collaborative support of the CNN Travel team:
# Senior Web Development Manager:
# Brent A. Deverman
#
# Senior Software Engineer:
# Adrian Christopher B. Cruz
#
# Senior QA Analyst:
# Jonathan A. Jacinto
#
# Special Credits to: Nikolaos Dimopoulos for his great work: http://www.niden.net/2011/11/git-pre-commit-another-check-to-ensure.html
# Define a function to exit which can reset $IFS.
clean_exit(){
IFS=$IFSBACK
exit 1
}
echo
echo "************************************************************************"
echo "* *"
echo "* GIT PRE-COMMIT HOOK FOR DRUPAL *"
echo "* *"
echo "* In order to commit your changes, it must pass the four filters: *"
echo "* I. Syntax checking using PHP Linter *"
echo "* II. Coding standards checking using PHP Code Sniffer *"
echo "* III. Blacklisted functions checking/validation. *"
echo "* IV. Check Javascript syntax. *"
echo "* *"
echo "************************************************************************"
echo
# Get hook directory
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Build the list of PHP blacklisted functions
checks=("\<var_dump(" "\<print_r(" "\<die(")
# Blacklist Drupal's built-in debugging function
checks+=("\<debug(")
# Blacklist Devel's debugging functions
checks+=("\<dpm(" "\<krumo(" "\<dpr(" "\<dsm(" "\<dd(" "\<ddebug_backtrace(" "\<dpq(" "\<dprint_r(" "\<drupal_debug(" "\<dsm(" "\<dvm(" "\<dvr(" "\<kpr(" "\<kprint_r(" "\<kdevel_print_object(" "\<kdevel_print_object(")
# Blacklist code conflicts resulting from Git merge.
checks+=("<<<<<<<" ">>>>>>>")
# Blacklist Javascript debugging functions
checks+=("\<console.log(" "\<alert(")
# Get the total number of blacklisted functions.
element_count=${#checks[@]}
ROOT_DIR="$(pwd)/"
# Exclude Features-generated files because they should not be modified.
# Exclude contribs modules because they should not be modified.
# Exclude devel module because they contain debugging functions
# Exclude libraries because they should not be modified
filters_exclude=('features' 'contrib' 'devel' 'libraries' 'development' 'scripts' 'featurized' 'vendor')
# Exclude extensions we know should not be checked.
filters_exclude+=('\.md$' '\.png$' '\.gif$' '\.jpg$' '\.ico$' '\.patch$' '\.ad$' '\.htaccess$' '\.sh$' '\.ttf$' '\.woff$' '\.eot$' '\.svg$' '\.xml$' '\.json$' '\.yml$' '\.gitignore$' '\.lock$' '/settings.php$' '\.min\.js$' '\.make$' '\.md$')
# Join filters_exclude array into a single string for grep -v
# We use egrep for the exclude since it combines better with -v.
sep="|"
egrep_exclude=$(printf "${sep}%s" "${filters_exclude[@]}")
# Remove the separator from the start of the string
egrep_exclude=${egrep_exclude:${#sep}}
egrep_exclude=".*\($egrep_exclude\)"
LIST=$( git diff --name-only --cached --diff-filter=ACM | egrep -v "$egrep_exclude" )
# Display the list of files to be processed, for overview purposes.
echo
echo "File(s) to be processed/validated:"
echo
i=1
# IFS is a bash internal defines the separator for looping over a string.
IFSBACK=$IFS
IFS=$'\n'
for file in $LIST
do
# Display the path of the file.
# % 3 == 0 is used since the path of the file is outputted every 3rd token/line.
echo $file
done
# This counter is used by the Code Sniffer for tracking errors.
sniffer_error_count=0
ERRORS_BUFFER=""
# PHP syntax-error free code
NO_SYNTAX_ERROR=0
# PHP syntax error code
SYNTAX_ERROR=255
# Code Sniffer error code
PHPCS_FAILED=1
# Code Sniffer success code
PHPCS_PASSED=0
for file in $LIST
do
##################################
# Check for syntax error.
##################################
echo
echo
echo
echo "Validating: $file..."
echo
echo "I. Running the PHP Linter..."
echo
php -l $file >&2
SYNTAX_CODE=$?
if [ "$SYNTAX_CODE" -eq "$NO_SYNTAX_ERROR" ];then
#################################
# Run Drupal code sniffer
#################################
# Get the PHP Codesniffer bin path
if [ -d vendor/bin ]
then
PATH=vendor/bin:$PATH
fi
PHPCS_BIN=$(which phpcs)
# Default PHP error code
PHP_CODE=0
echo
echo
echo "II. Running the PHP Code Sniffer..."
# Run the PHP Codesniffer validation
$PHPCS_BIN --standard=Drupal $file >&2
# Default PHPCS error code
PHPCS_CODE=$?
if [ "$PHPCS_CODE" == "$PHPCS_PASSED" ]; then
echo
echo "No formatting errors detected."
elif [ "$PHPCS_CODE" == "$PHPCS_FAILED" ]; then
let "sniffer_error_count += 1"
echo "You have coding standard problem in your code. Please fix and commit your changes again."
clean_exit
else
echo
echo "Invalid operation."
echo
clean_exit
fi
elif [ "$SYNTAX_CODE" == "$SYNTAX_ERROR" ]; then
echo
echo "You have syntax error in your code. Please fix and commit your changes again."
echo
clean_exit
else
echo
echo "Invalid operation."
echo
clean_exit
fi
#################################
# Check for debugging functions
#################################
# Define allowed/possible file extensions that might contain debugging functions.
EXTENSION=$(echo "$file" | egrep "\.install$|\.test$|\.inc$|\.module$|\.php$")
if [ "$EXTENSION" != "" ]; then
index=1
while [ "$index" -lt "$element_count" ]
do
# Find the blacklisted functions in the current file.
ERRORS=$(grep "${checks[$index]}" $ROOT_DIR$file >&1)
if [ "$ERRORS" != "" ]; then
if [ "$ERRORS_BUFFER" != "" ]; then
ERRORS_BUFFER+="\n${checks[$index]} found in file: $file "
else
ERRORS_BUFFER="\n${checks[$index]} found in file: $file "
fi
fi
let "index += 1"
done
fi
done
if [ "$sniffer_error_count" -gt "0" ]; then
echo "Your commits failed to pass the PHP code sniffer validation."
echo "Kindly fix the code sniffer notices."
echo
clean_exit
fi
echo
echo
echo "III. Running the checker/validator for blacklisted functions..."
if [ "$ERRORS_BUFFER" != "" ]; then
echo
echo "These errors were found in try-to-commit files: "
echo -e $ERRORS_BUFFER
echo
echo "Can't commit your changes, fix the generated errors first."
echo
clean_exit
else
echo
echo "No backlisted function(s) detected."
echo
fi
########################################
# Execute Esprima js validation.
########################################
echo
echo "IV. Check Javascript syntax."
echo
files=$(git diff-index --name-only HEAD | grep -e '\.js$')
if [ ${#files[@]} = 0 ]; then
echo "No JS files found."
echo
else
hash esvalidate 2>/dev/null
if [ $? -eq 1 ]; then
echo "Unable to check Javascript syntax: esvalidate is not available."
echo
echo "Please install esvalidate to validate JS files."
echo
clean_exit
fi
for file in $files; do
esvalidate $file
if [ $? -eq 1 ]; then
echo "Syntax error: $file"
clean_exit
fi
done
fi
echo "Congratulations! You have passed all the filters, your code has now been committed."
echo