3 # SVN Syntax Check Hook Script
4 # Copyright (c) 2007, Lucas Nealan <lucas@sizzo.org>, Facebook Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 # --------------------------------------------------------------------
23 # This script provides language independant syntax checking
24 # functionality intended to be invoked from a subversion pre-commit
27 # Invocation: /path/to/syntax-check $1 $2
28 # or: source syntax-check
30 # Requires bash 3.x or higher.
33 FPATTERN
="\.\(php\|phpt\)$"
37 # address to email notifications of syntax errors
38 NOTIFY_SYNTAX
="user@domain.tld"
39 # adderss to notify for syntax script failures
40 NOTIFY_ERROR
="user@domain.tld"
41 # log of syntax errors, must be writable by svn server users
42 SYNTAX_LOG
="/tmp/syntax.log"
43 BYPASSPW
="change_this_syntax_bypass_password_please"
45 [ -z "$REPOS" ] && REPOS
="$1"
46 [ -z "$TXN" ] && TXN
="$2"
47 [ -z "$MODE" ] && if [ -n "$3" ]; then MODE
="$3"; else MODE
="-t"; fi
48 [ -z "$SVNLOOK" ] && SVNLOOK
=svnlook
49 [ -z "$LOG" ] && LOG
=`$SVNLOOK log $MODE "$TXN" "$REPOS"`
50 [ -z "$DIFF" ] && DIFF
=`$SVNLOOK diff $MODE "$TXN" "$REPOS"`
51 [ -z "$AUTHOR" ] && AUTHOR
=`$SVNLOOK author $MODE "$TXN" "$REPOS"`
52 [ -z "$CHANGEDFILES" ] && CHANGEDFILES
=`$SVNLOOK changed $MODE "$TXN" "$REPOS"`
53 [ -n "$SYNTAXENABLED" ] && SYNTAXENABLED
="1"
56 [ -d $1 ] && rm -rf $1
60 echo $1 >> /dev
/stderr
61 echo $1 >> $SYNTAX_LOG
63 # save working dir and debug files
64 if [ -d $WORKING ]; then
65 [ -n "$DIFF" ] && echo $
"$DIFF" > $WORKING/patch
66 [ -n "$LOG" ] && echo $
"$LOG" > $WORKING/svnlog
67 [ -n "$CHANGED" ] && echo $
"$CHANGED" > $WORKING/changed
68 mv $WORKING $WORKING.failed
71 [ -n "$NOTIFY_ERROR" ] && echo "$1 ($WORKING.failed)" |
mail -s "syntax commit failed" $NOTIFY_ERROR
73 # clean working dir if specified
74 [ -n $2 ] && syntaxclean
$2
84 echo "$STR""`printf '%'$D's'| tr \ \"$CHAR\"`"
87 function errormessage
() {
89 HEADER
=`strlpad "Error" "-" 76`
90 echo "|--$HEADER|" >&2
91 SPACES
="`strlpad '' ' ' 78`"
93 ERROR
=`strlpad "$1" " " 77`
96 LINE
=`strlpad "" "-" 78`
101 if [ "$SYNTAXENABLED" == "1" ]; then
102 # allow selective bypass of syntax check for commits
103 [[ "$LOG" =~
"$BYPASSPW" ]] && return;
105 # get changed file list and count
107 if [ -n "$CHANGEDFILES" ]; then
108 MATCHCHANGED
=`echo $"$CHANGEDFILES" | grep "$FPATTERN"`
109 [ -n "$MATCHCHANGED" ] && NUMMATCHCHANGED
=`echo $"$MATCHCHANGED" | wc -l`
112 # make sure matched files were changed
113 if [ $NUMMATCHCHANGED -gt 0 ]; then
114 # create temporary working directory
115 WORKING
=/tmp
/$
(basename $0).$$
116 [ -d $WORKING ] && rm -rf $WORKING
117 mkdir
$WORKING || syntaxexit
"failed to create temp dir for syntax check: $WORKING"
120 # export changed files (no dirs) from local repo (speed)
122 for LINE
in $MATCHCHANGED; do
128 # only export modified and deleted files. new files wont exist in repo yet
129 if [ "$FSTATUS" == "U" ] ||
[ "$FSTATUS" == "UU" ] ||
[ "$FSTATUS" == "A" ]; then
130 TMPFNAME
=${FNAME//\//.}
131 $SVNLOOK cat $MODE "$TXN" "$REPOS" $FNAME > $TMPFNAME
133 file `which $SYNTAX_CMD` || syntaxexit
"unablet to find systax command binary: $SYNTAX_CMD"
134 SYNTAXERROR
=`$SYNTAX_CMD $SYNTAX_ARGS $TMPFNAME 2> $WORKING/$TMPFNAME.STDERR`
136 [ -s "$WORKING/$TMPFNAME.STDERR" ] && SYNTAXWARNING
=`cat $WORKING/$TMPFNAME.STDERR`
138 if [ "$SYNTAXRETURN" -ne 0 ] ||
[ -n "$SYNTAXWARNING" ]; then
139 [ -n "$SYNTAXWARNING" ] && SYNTAXERROR
=$SYNTAXWARNING
141 # cleanup HTML out of PHP parse error so a human can read it
142 if [ "$FLANG" == "PHP" ]; then
143 SYNTAXERROR
=`echo $SYNTAXERROR | sed -e 's/<[^<]*>//g' | cut -d',' -f 2`
144 SYNTAXERROR
=`echo $SYNTAXERROR | sed -e 's/\(on line [0-9]* \)/\1\n/g'`
147 # sloppy email notification
148 ETMP
=$WORKING/sloppy.txt
149 echo "$FLANG Syntax Error: $SYNTAXERROR" > $ETMP
151 echo Log
: $LOG >> $ETMP
153 echo $
"$DIFF" >> $ETMP
154 cat $ETMP |
mail -s "SVN SYNTAX ERROR: $AUTHOR" $NOTIFY_SYNTAX
157 echo "$AUTHOR: $FLANG Syntax Error: $SYNTAXERROR" >> $SYNTAX_LOG
158 errormessage
"$FLANG Syntax Error: $SYNTAXERROR"
164 # exit within a loop only sets the return value of the loop itself, check this to exit
165 [ $?
-ne 0 ] && exit 1