minimal/do: use posix shell features instead of dirname/basename.

This avoids a few forks, and is a good example of how to do some "modern" sh
programming.  Plus we now use fewer lines of code.
This commit is contained in:
Avery Pennarun 2011-01-01 03:14:32 -08:00
commit 41ef15fde2

View file

@ -6,18 +6,25 @@
# The author disclaims copyright to this source file and hereby places it in # The author disclaims copyright to this source file and hereby places it in
# the public domain. (2010 12 14) # the public domain. (2010 12 14)
# #
export REDO="$(cd "$(dirname "$0")" && echo "$PWD/$(basename "$0")")" _dirsplit()
{
base=${1##*/}
dir=${1%$base}
}
_dirsplit "$0"
export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
if [ -z "$DO_BUILT" ]; then if [ -z "$DO_BUILT" ]; then
export DO_BUILT="$PWD/.do_built" export DO_BUILT=$PWD/.do_built
if [ -e "$DO_BUILT" ]; then if [ -e "$DO_BUILT" ]; then
echo "Removing previously built files..." >&2 echo "Removing previously built files..." >&2
sort -u "$DO_BUILT" | tee "$DO_BUILT.new" | sort -u "$DO_BUILT" | tee "$DO_BUILT.new" |
while read f; do rm -f "$f"; done while read f; do rm -f "$f" 2>/dev/null; done
mv "$DO_BUILT.new" "$DO_BUILT" mv "$DO_BUILT.new" "$DO_BUILT"
fi fi
DO_PATH="$DO_BUILT.dir" DO_PATH=$DO_BUILT.dir
export PATH="$DO_PATH:$PATH" export PATH=$DO_PATH:$PATH
rm -rf "$DO_PATH" rm -rf "$DO_PATH"
mkdir "$DO_PATH" mkdir "$DO_PATH"
for d in redo redo-ifchange; do for d in redo redo-ifchange; do
@ -30,56 +37,53 @@ if [ -z "$DO_BUILT" ]; then
fi fi
_dirsplit() _find_dofile()
{ {
OLDIFS="$IFS" DOFILE=default.$1.do
IFS=/ while :; do
set -- $1 DOFILE=default.${DOFILE#default.*.}
IFS="$OLDIFS" [ -e "$DOFILE" -o "$DOFILE" = default.do ] && break
dir=""
while [ $# -gt 1 ]; do
dir="$dir$1/"
shift
done done
base="$1" 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.tmp"
} }
_do() _do()
{ {
DIR="$1" DIR=$1
TARGET="$2" TARGET=$2
if [ ! -e "$TARGET" ]; then if [ ! -e "$TARGET" ]; then
printf '\033[32mdo %s\033[1m%s\033[m\n' \ printf '\033[32mdo %s\033[1m%s\033[m\n' \
"$DO_DEPTH" "$DIR$TARGET" >&2 "$DO_DEPTH" "$DIR$TARGET" >&2
echo "$PWD/$TARGET" >>"$DO_BUILT" echo "$PWD/$TARGET" >>"$DO_BUILT"
dof=".$TARGET" DOFILE=$TARGET.do
DOFILE="$TARGET.do" BASE=$TARGET
BASE="$TARGET" EXT=
EXT="" [ -e "$TARGET.do" ] || _find_dofile "$TARGET"
while [ ! -e "$DOFILE" ]; do if [ ! -e "$DOFILE" ]; then
dof2=$(echo "$dof" | sed 's/\.[^\.]*//') echo "do: $TARGET: no .do file" >&2
[ "$dof" = "$dof2" ] && break return 1
dof="$dof2" fi
DOFILE="default$dof.do" ( _run_dofile "$BASE" "$EXT" "$TARGET.tmp" )
BASE="$(basename "$TARGET" "$dof")" RV=$?
EXT="$dof" if [ $RV != 0 ]; then
done
set "$BASE" "$EXT" "$TARGET.tmp"
RV=
(
export DO_DEPTH="$DO_DEPTH "
export REDO_TARGET="$PWD/$TARGET"
set -e
. "$PWD/$DOFILE" >"$TARGET.tmp"
) || RV="$?"
[ -z "$RV" ] && mv "$TARGET.tmp" "$TARGET" 2>/dev/null
: >>"$TARGET"
if [ -n "$RV" ]; then
printf "do: %s%s\n" "$DO_DEPTH" \ printf "do: %s%s\n" "$DO_DEPTH" \
"$DIR$TARGET: got exit code $RV" >&2 "$DIR$TARGET: got exit code $RV" >&2
return $RV return $RV
fi fi
mv "$TARGET.tmp" "$TARGET" 2>/dev/null
: >>"$TARGET"
else else
echo "do $DO_DEPTH$TARGET exists." >&2 echo "do $DO_DEPTH$TARGET exists." >&2
fi fi