#!/bin/sh QUIET=false NORUN=false DIE=true FNEW=false _ARGS=true OKFILE=./ok FRFILE=.fr usage(){ exec >&2 cat<&2 exit $ec } procargs(){ $_ARGS || return 1 while getopts hqnxBf:C: OPT do case "$OPT" in (h) usage; exit ;; (q) QUIET=true ;; (x) set -x ;; (n) NORUN=true ;; (B) FNEW=true ;; (f) test -f "$OPTARG" && OKFILE="$OPTARG" || exit 2 ;; (C) cd "$OPTARG" || exit 2 ;; (*) usage; exit 1 ;; esac done } go(){ procargs "$@" && shift $((OPTIND - 1)) DEFAULT="$(sed -n 's/^\([a-z][a-z]*\)().*/\1/p' "$OKFILE"|sed q)" . "$OKFILE" || exit 3 test -z "$1" && "$DEFAULT" for target do if grep -q "$target" "$FRFILE" 2>/dev/null then if buildp "$target" \ "$(grep "$target" "$FRFILE" | cut -f3-)" then eval "$(grep "$target" "$FRFILE" | cut -f2-)" fi else "$target" fi done } dep(){ _ARGS=false go "$@" || exit "$((200 + $?))" } buildp(){ # buildp TARGET DEPENDENCIES... $FNEW && return 0 target="$1"; shift test -e "$target" || return 0 for f do test x-- = "x$f" && continue test "$f" -nt "$target" && return 0 done return 1 } ok(){ # ok COMMAND ARGS.. case "$1" in (-) DIE=false; shift ;; esac $QUIET || printf >&2 '* %s\n' "$*" $NORUN || "$@"; ec="$?" if $DIE && test $ec -ne 0 then die $((100 + $?)) not ok else return $ec fi } quietly(){ "$@" >/dev/null 2>&1; } allfiles(){ while read -r target line do TARGET="$target" eval "$line" done <"$FRFILE" } fr(){ # fr < TARGET JOB DEPS... # recommended: use a heredoc :>"$FRFILE" while read -r target job deps do eval set -- "$deps" printf '%s\tok %s\t%s\n' \ "$target" \ "$job" \ "$(printf '%s\n' "$deps"|sed 's/--.*//')" \ >>"$FRFILE" done } go "$@" && echo ok