#!/bin/sh # # A minimal alternative to djb redo that doesn't support incremental builds. # For the full version, visit http://github.com/apenwarr/redo # # The author disclaims copyright to this source file and hereby places it in # the public domain. (2010 12 14) # _dirsplit() { base=${1##*/} dir=${1%$base} } _dirsplit "$0" export REDO=$(cd "${dir:-.}" && echo "$PWD/$base") DO_TOP= if [ -z "$DO_BUILT" ]; then DO_TOP=1 export DO_BUILT=$PWD/.do_built if [ -e "$DO_BUILT" ]; then echo "Removing previously built files..." >&2 sort -u "$DO_BUILT" | tee "$DO_BUILT.new" | while read f; do rm -f "$f" "$f.did" 2>/dev/null; done mv "$DO_BUILT.new" "$DO_BUILT" fi DO_PATH=$DO_BUILT.dir export PATH=$DO_PATH:$PATH rm -rf "$DO_PATH" mkdir "$DO_PATH" for d in redo redo-ifchange; do ln -s "$REDO" "$DO_PATH/$d"; done [ -e /bin/true ] && TRUE=/bin/true || TRUE=/usr/bin/true for d in redo-ifcreate redo-stamp redo-always; do ln -s $TRUE "$DO_PATH/$d"; done fi _find_dofile() { DOFILE=default.$1.do while :; do DOFILE=default.${DOFILE#default.*.} [ -e "$DOFILE" -o "$DOFILE" = default.do ] && break done EXT=${DOFILE#default} EXT=${EXT%.do} BASE=${1%$EXT} } _run_dofile() { export DO_DEPTH="$DO_DEPTH " export REDO_TARGET=$PWD/$TARGET set -e . "$PWD/$DOFILE" >"$TARGET.tmp2" } _do() { DIR=$1 TARGET=$2 if [ ! -e "$TARGET" ] || [ -e "$TARGET/." -a ! -e "$TARGET.did" ]; then printf '\033[32mdo %s\033[1m%s\033[m\n' \ "$DO_DEPTH" "$DIR$TARGET" >&2 echo "$PWD/$TARGET" >>"$DO_BUILT" DOFILE=$TARGET.do BASE=$TARGET EXT= [ -e "$TARGET.do" ] || _find_dofile "$TARGET" if [ ! -e "$DOFILE" ]; then echo "do: $TARGET: no .do file" >&2 return 1 fi : >>"$TARGET.did" ( _run_dofile "$BASE" "$EXT" "$TARGET.tmp" ) RV=$? if [ $RV != 0 ]; then printf "do: %s%s\n" "$DO_DEPTH" \ "$DIR$TARGET: got exit code $RV" >&2 rm -f "$TARGET.tmp" "$TARGET.tmp2" return $RV fi mv "$TARGET.tmp" "$TARGET" 2>/dev/null || ! test -s "$TARGET.tmp2" || mv "$TARGET.tmp2" "$TARGET" 2>/dev/null rm -f "$TARGET.tmp2" else echo "do $DO_DEPTH$TARGET exists." >&2 fi } redo() { for i in "$@"; do _dirsplit "$i" ( cd "$dir" && _do "$dir" "$base" ) || return 1 done } set -e if [ -n "$*" ]; then redo "$@" else redo all fi if [ -n "$DO_TOP" ]; then echo "Removing stamp files..." >&2 while read f; do rm -f "$f.did" 2>/dev/null; done <"$DO_BUILT" fi