Why would my SVN pre-commit hook work locally, but not on commit?
#!/bin/env bash REPOS="$1" TXN="$2" ECHO=/bin/echo GREP=/bin/grep SED=/bin/sed SVN=/usr/bin/svn SVNLOOK=/usr/bin/svnlook FILES_CHANGED=`$SVNLOOK changed -r$TXN $REPOS | $SED -e "s/^....//g"` JSL=/usr/local/bin/jsl JSL_CONF=/usr/local/etc/jsl.conf for FILE in $FILES_CHANGED do if $ECHO $FILE | $GREP "\.js$" then $SVN cat -r$TXN file://$REPOS/$FILE | $JSL -conf $JSL_CONF -stdin 1>&2 JSL_ERROR_CODE=$? if [ $JSL_ERROR_CODE != 0 ] then exit $JSL_ERROR_CODE fi fi done # If we got here, nothing is wrong. exit 0
This code works locally as follows: ./pre-commit /my/svn/repo/location 6781 # the number is the transaction number
BUT it doesn't error correctly on svn commit.
I have already accounted for:
- There being no $PATH, I explicitly set all command paths.
- I am catching the correct error code from the jsl command for exit.
- I am pushing STDOUT to STDERR for the jsl command so it will be displayed in the commit fail.
What am I missing?
It is possible that one of the programs you're running expect some environment variables to be set.
For security reasons, the Subversion repository executes hook scripts with an empty environment—that is, no environment variables are set at all, not even $PATH or %PATH%. Because of this, a lot of administrators are baffled when their hook script runs fine by hand, but doesn't work when run by Subversion. Be sure to explicitly set environment variables in your hook and/or use absolute paths to programs.
Try to execute them locally without any environment variables set and see if that works.
I usually end up importing all my environment in the first line of my hook scripts:
I discovered the answer after a long and winding road. Basically, in my script above I am using -r in my svn commands, but in a pre-commit hook you must use -t, not -r. The complete script is below:
#!/bin/sh REPOS="$1" TXN="$2" ECHO=/bin/echo GREP=/bin/grep SED=/bin/sed SVNLOOK=/usr/bin/svnlook FILES_CHANGED=`$SVNLOOK changed -t$TXN $REPOS | $SED -e "s/^....//g"` JSL=/usr/local/bin/jsl JSL_CONF=/usr/local/etc/jsl.default.conf for FILE in $FILES_CHANGED do if $ECHO $FILE | $GREP "\.js$" then $SVNLOOK cat -t$TXN $REPOS $FILE | $JSL -conf $JSL_CONF -stdin -nologo 1>&2 JSL_ERROR_CODE=$? if [ $JSL_ERROR_CODE != 0 ] then exit $JSL_ERROR_CODE fi fi done # If we got here, nothing is wrong. exit 0