1# /bin/sh 2# $Id$ 3# vim:et:ft=sh:sts=2:sw=2 4# 5# Copyright 2010 Kate Ward. All Rights Reserved. 6# Author: kate.ward@forestent.com (Kate Ward) 7# 8# Continuous build script for shell library testing. 9# 10# Sample usages: 11# $ blah 12 13# treat unset variables as an error 14set -u 15 16# global constants 17ARGV0=`basename "$0"` 18ARGV0_DIR=`dirname "$0"` 19SHLIB_DIR="${ARGV0_DIR}/../lib" 20 21# load libraries 22. ${SHFLAGS_LIB:-${SHLIB_DIR}/shflags} \ 23 || (echo 'unable to load shflags library' >&2; exit 1) 24. ${VERSIONS_LIB:-${SHLIB_DIR}/versions} \ 25 || (echo 'unable to load versions library' >&2; exit 1) 26 27OUTPUT_FILE="${VERSIONS_OS_NAME}_${VERSIONS_OS_RELEASE}" 28 29# define flags 30DEFINE_string 'command' '' 'the command to start a build' 'c' 31DEFINE_string 'watch' '' 'file to watch for changes' 'w' 32DEFINE_string 'watch_from' '' 'file containing filenames to watch' 'W' 33DEFINE_string 'output' "${OUTPUT_FILE}" 'output file to write to' 'o' 34DEFINE_string 'output_dir' '.' 'directory to write output file' 'O' 35DEFINE_integer 'pause' 60 'pause between successive runs (sec)' 'p' 36 37FLAGS_HELP="USAGE: ${ARGV0} [flags]" 38 39#------------------------------------------------------------------------------ 40# functions 41# 42 43# This function exits the script, optionally printing a message 44# 45# Args: 46# message: string: an error message to be output (optional) 47# Output: 48# string: usable flags 49die() { 50 [ $# -ne 0 ] && echo "$@" >&2 51 flags_help 52 exit 1 53} 54 55# Function to give the current date in ISO format 56# 57# Args: 58# none 59# Output: 60# string: isodate 61isodate() { 62 date -u '+%Y%m%dT%H%M%SZ' 63} 64 65age() { 66 awkScript='' 67 case ${VERSIONS_OS_NAME} in 68 FreeBSD|Solaris) awkScript='{print $6,$7,$8}' ;; 69 Linux) awkScript='{print $6,$7}' ;; 70 *) echo "unrecognized OS name (${VERSIONS_OS_NAME})" >&2 ;; 71 esac 72 ls -l "$1" |awk "${awkScript}" 73} 74 75#------------------------------------------------------------------------------ 76# main 77# 78 79main() 80{ 81 # checks 82 [ -n "${FLAGS_command}" ] || die 'command required' 83 [ -z "${FLAGS_watch}" -a -z "${FLAGS_watch_from}" ] \ 84 && die 'one of watch or watch_from required' 85 [ -n "${FLAGS_watch}" -a -n "${FLAGS_watch_from}" ] \ 86 && die 'only one of watch or watch_from can be specified' 87 [ -r "${FLAGS_watch}" ] || die 'unable to read watch file' 88 [ -w "${FLAGS_output_dir}" ] || die 'unable to write to output directory' 89 90 watchAge=`age "${FLAGS_watch}"` 91 watchAgePrev=${watchAge} 92 93 # build 94 while true; do 95 if [ ! "${watchAge}" == "${watchAgePrev}" ]; then 96 date=`isodate` 97 echo "building ${VERSIONS_OS_NAME}-${VERSIONS_OS_RELEASE} @ ${date}" 98 outputFileDated="${FLAGS_output}-${date}" 99 ${FLAGS_command} >"${FLAGS_output_dir}/${outputFileDated}" 2>&1 100 101 ( cd "${FLAGS_output_dir}"; 102 rm -f "${FLAGS_output}"; 103 ln -s "${outputFileDated}" "${FLAGS_output}"; 104 grep FAIL "${FLAGS_output}"; ) 105 106 watchAgePrev=${watchAge} 107 fi 108 109 watchAge=`age "${FLAGS_watch}"` 110 if [ "${watchAge}" == "${watchAgePrev}" ]; then 111 echo 'sleeping...' 112 while [ "${watchAge}" == "${watchAgePrev}" ]; do 113 sleep ${FLAGS_pause} 114 watchAge=`age "${FLAGS_watch}"` 115 done 116 fi 117 done 118} 119 120# execute main() if this is run in standalone mode (i.e. not in a unit test) 121argv0=`echo "${ARGV0}" |sed 's/_test$//;s/_test\.sh$//'` 122if [ "${ARGV0}" = "${argv0}" ]; then 123 FLAGS "$@" || exit $? 124 eval set -- "${FLAGS_ARGV}" 125 if [ $# -gt 0 ]; then main "$@"; else main; fi 126fi 127