Apparently emacs sets TERM=dumb in its tty simulator, so even though isatty() returns true, we shouldn't use colour codes. (emacs is therefore lame. But we knew that.)
137 lines
2.8 KiB
Bash
Executable file
137 lines
2.8 KiB
Bash
Executable file
#!/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)
|
|
#
|
|
|
|
# By default, no output coloring.
|
|
GREEN=""
|
|
BOLD=""
|
|
PLAIN=""
|
|
|
|
if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then
|
|
GREEN="$(printf '\033[32m')"
|
|
BOLD="$(printf '\033[1m')"
|
|
PLAIN="$(printf '\033[m')"
|
|
fi
|
|
|
|
_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
|
|
: >>"$DO_BUILT"
|
|
echo "Removing previously built files..." >&2
|
|
sort -u "$DO_BUILT" | tee "$DO_BUILT.new" |
|
|
while read f; do printf "%s\0%s.did\0" "$f" "$f"; done |
|
|
xargs -0 rm -f 2>/dev/null
|
|
mv "$DO_BUILT.new" "$DO_BUILT"
|
|
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
|
|
read line1 <"$PWD/$DOFILE"
|
|
cmd=${line1#"#!/"}
|
|
if [ "$cmd" != "$line1" ]; then
|
|
/$cmd "$PWD/$DOFILE" "$@" >"$TARGET.tmp2"
|
|
else
|
|
. "$PWD/$DOFILE" >"$TARGET.tmp2"
|
|
fi
|
|
}
|
|
|
|
|
|
_do()
|
|
{
|
|
DIR=$1
|
|
TARGET=$2
|
|
if [ ! -e "$TARGET" ] || [ -e "$TARGET/." -a ! -e "$TARGET.did" ]; then
|
|
printf '%sdo %s%s%s%s\n' \
|
|
"$GREEN" "$DO_DEPTH" "$BOLD" "$DIR$TARGET" "$PLAIN" >&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 printf "%s.did\0" "$f"; done <"$DO_BUILT" |
|
|
xargs -0 rm -f 2>/dev/null
|
|
fi
|