#!/bin/bash #This script was un-gracefully hacked out of http://cvs.sourceforge.net/viewcvs.py/emc/emc_HAL/farm_scripts/run_farm?rev=1.3&view=auto # This script reads the file "trees" in the current directory. It # cd's into each subdirectory listed there, does a cvs up, and if # any files have changed, it calls "build" in that directory, logging # its output to "build_log" # This function is used to log messages to farm_log function MSG { if [ "$TREE" != "" ] ; then date -u "+%D %T $TREE $1" >>farm_log else date -u "+%D %T $1" >>farm_log fi } # This function attempts to do a "cvs up", saving the results in # cvs_log. It does not interpret the results. It returns 0 if # the cvs command completes successfully, and 1 if it fails or # times out. # function TRY_CVS { rm -f cvs_log # invoke the command in the background if cvs -q up -dP 1>>cvs_log 2>>cvs_log; then echo "CVS_SUCCESS" >>cvs_log fi & # save the PID of the "if" block above BLKPID=$! # find the PID of the actual command (not the entire block) # (look for parent pid = BLKPID and command = "cvs" ) CMDPID=`ps o ppid,pid,cmd | awk -- "\\$1 ~ /$BLKPID/ && \\$3 ~ /cvs/ {print \\$2}"` # loop until the command ends, if it takes too long, kill it TIMEOUT=60 while ps -p $BLKPID &>/dev/null ; do # check for timeout if [ $TIMEOUT -eq 0 ] ; then # find pids of any children of the command CHILDPID=`ps -A o ppid,pid | awk -- "\\$1 ~ /\$CMDPID/ { print \\$2 }"` # stop the command kill $CMDPID &>/dev/null # stop any children for CHILDPID in $CHILDPID ; do kill $CHILDPID &>/dev/null done # wait for the "if" block to finish wait $BLKPID &>/dev/null # log the timeout echo "CVS_TIMEOUT" >>cvs_log else # wait a bit sleep 1 # decrement TIMEOUT TIMEOUT=$((${TIMEOUT}-1)) fi done if grep -q CVS_SUCCESS cvs_log ; then return 0 ; else return 1 ; fi } # This function calls TRY_CVS, retrying several # times on timeouts or errors. # function DO_CVS { MSG "cvs up" # first remove any old cvs_log file that is laying around rm -f cvs_log # then try to do a cvs up if TRY_CVS ; then return 0 fi RETRY=1 LIMIT=5 while [ $RETRY -lt $LIMIT ] ; do MSG "cvs up retry $RETRY" if TRY_CVS ; then return 0 fi RETRY=$((${RETRY}+1)) done MSG "cvs up failed ($LIMIT retries)" return 1 } # this function is given the name of a directory tree and # attempts to do a cvs up and if neccessary a build in that tree function TEST_CVS { # attempt to do CVS update, if it fails, we're done if ! DO_CVS ; then # save the cvs logfile for troubleshooting date +"%D %T" >>cvs_log_fail cat cvs_log >>cvs_log_fail return 1 fi # parse the file looking for "U" or "P" that indicates modified # files. also look for "A", "R", "M", or "C" that indicates local # changes that shouldn't happen. RESULT=`cat cvs_log | awk -- \ 'BEGIN { errors=0 ; updates=0 } \ $1 ~ /^[ARMC]$/ { errors++ } \ $1 ~ /^[UP]$/ { updates++ } \ END { result="NOTHING" ; \ if ( updates > 0 ) { result="UPDATE" } ; \ if ( errors > 0 ) { result="ERROR" } ; \ printf ( "%s\n", result ) }'` # decide what is do be done if [ "$RESULT" = "ERROR" ] ; then MSG "local repository has been modified, something is wrong" # save cvs log file for troubleshooting date +"%D %T" >cvs_log_fail cat cvs_log >>cvs_log_fail return 1 fi if [ "$RESULT" = "NOTHING" ] ; then MSG "no changes" return 0 fi # if we get here, we need to attempt a build MSG "starting build" # make a header for the build log echo >build_log date -u +"make tgz started at %D %T" >>build_log echo >>build_log # make the tarball if $(cd emc2/src/ ; make tgz) 1>>build_log 2>>build_log; then # succeeded echo >>build_log date -u +"make tgz completed successfully at %D %T" >>build_log echo >>build_log MSG "make tgz succeeded" STAMP=`date -u +" %D %T "` STATUS=PASSED else # failed echo >>build_log date -u +"make tgz failed at %D %T" >>build_log echo >>build_log MSG "build failed" STAMP=`date -u +" %D %T "` STATUS=FAILED fi # append an entry to the history log echo "`date -u +" %D %T "`${STATUS}" >>history_log return 0 } #now we actually do something TREE=./emc2/ cd $TREE TEST_CVS