mostlysoftware

Software development, the ups and the downs

Archive for the tag “autotest”

Autotest-a-like for bash

I’ve been programming a bit of Ruby and Python in the past few months and one of the things I’ve found most useful is autotest. This is a Ruby tool that detects when you’ve changed a test file or source file and runs the tests for you. This is triggered upon save so you don’t have to do anything that edit and save, it’s that easy. Python has sniffer which is also great and does pretty much the same thing.

I mostly program in C++ at work and would love to have a similar tool. Unfortunately much of the auto detection about what tests to rerun is possible thanks to the dynamic nature of these languages, however the idea of running a command when some files change could still be applied to my situation so I wrote the following shell script.

It’s really simple, all it does is take three arguments; a delay in seconds between checking for changes, a command (quote it if you have a compound or multi-word command) and a list of directories within which to check for changed files since the last time the command was run. The command will be run at the start of the script is run and is then only triggered by file changes.

You can find the script on github here or you can be lazy and see the source code for the current version below – but be warned this might be out of date with the github code!

#!/bin/bash

trap ctrl_c INT

ctrl_c() {
    rm ${watchFile}
    exit 0
}

run_command() {
    touch -t `date +%m%d%H%M.%S` ${watchFile};
    echo "Running '${command}'";
    eval ${command}
}

usage() {
    echo "Usage: watchAndRun.sh <check period in seconds> <command to run on change> <list of directories to watch for changes>";
    echo " e.g. watchAndRun.sh 5 \"echo 'yes'\" src . .."
    exit 1;
}

# Arg one is delay in seconds between checking for changes
# Arg two is command to run on change detected
# Arg three* is list of directories to watch for changes

if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then
    usage
fi

delay=$1
command="$2"
directory_list=

shift; shift; # Remove first two args to leave $@ containing only directories
while (( "$#" )); do
    directory_list="${directory_list} $1"
    shift
done

parentPID=`ps -fp $$ | tail -1 | awk '{print $3}'`
watchFile=/tmp/watch${parentPID}

while [ 1 ]; do

    if [ ! -e ${watchFile} ]; then
        echo "Created watch timestamp file '${watchFile}'"
        run_command
        echo "Waiting for changes..."
    fi

    if [ `find ${directory_list} -type f -newer ${watchFile} | wc -l` != "0" ]; then
        run_command
        echo "Waiting for changes..."
    fi

    # echo "Sleeping for $delay seconds"
    sleep ${delay}
done

Post Navigation