+ minimal redo implementation
This commit is contained in:
parent
1d81fb5618
commit
462b2e584a
1 changed files with 178 additions and 0 deletions
178
do
Normal file
178
do
Normal file
|
@ -0,0 +1,178 @@
|
|||
#!/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"}
|
||||
}
|
||||
|
||||
dirname()
|
||||
(
|
||||
_dirsplit "$1"
|
||||
dir=${dir%/}
|
||||
echo "${dir:-.}"
|
||||
)
|
||||
|
||||
_dirsplit "$0"
|
||||
export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
|
||||
|
||||
DO_TOP=
|
||||
if [ -z "$DO_BUILT" ]; then
|
||||
DO_TOP=1
|
||||
[ -n "$*" ] || set all # only toplevel redo has a default target
|
||||
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
|
||||
printf '#!/bin/sh\n' > "$DO_PATH/$d";
|
||||
chmod a+x "$DO_PATH/$d";
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
_find_dofile_pwd()
|
||||
{
|
||||
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}
|
||||
}
|
||||
|
||||
|
||||
_find_dofile()
|
||||
{
|
||||
local prefix=
|
||||
while :; do
|
||||
_find_dofile_pwd "$1"
|
||||
[ -e "$dofile" ] && break
|
||||
[ "$PWD" = "/" ] && break
|
||||
target=${PWD##*/}/"$target"
|
||||
tmp=${PWD##*/}/"$tmp"
|
||||
prefix=${PWD##*/}/"$prefix"
|
||||
cd ..
|
||||
done
|
||||
base="$prefix""$base"
|
||||
}
|
||||
|
||||
|
||||
_run_dofile()
|
||||
{
|
||||
export DO_DEPTH="$DO_DEPTH "
|
||||
export REDO_TARGET="$PWD"/"$target"
|
||||
local line1
|
||||
set -e
|
||||
read line1 <"$PWD/$dofile" || true
|
||||
cmd=${line1#"#!/"}
|
||||
if [ "$cmd" != "$line1" ]; then
|
||||
/$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2"
|
||||
else
|
||||
:; . "$PWD/$dofile" >"$tmp.tmp2"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
_do()
|
||||
{
|
||||
local dir="$1" target="$2" tmp="$3"
|
||||
if [ ! -e "$target" ] || [ -d "$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
|
||||
[ ! -e "$DO_BUILT" ] || [ ! -d "$(dirname "$target")" ] ||
|
||||
: >>"$target.did"
|
||||
( _run_dofile "$target" "$base" "$tmp.tmp" )
|
||||
rv="$?"
|
||||
if [ $rv != 0 ]; then
|
||||
printf "do: %s%s\n" "$DO_DEPTH" \
|
||||
"$dir$target: got exit code $rv" >&2
|
||||
rm -f "$tmp.tmp" "$tmp.tmp2" "$DO_BUILT"
|
||||
return "$rv"
|
||||
fi
|
||||
mv "$tmp.tmp" "$target" 2>/dev/null ||
|
||||
! test -s "$tmp.tmp2" ||
|
||||
mv "$tmp.tmp2" "$target" 2>/dev/null
|
||||
rm -f "$tmp.tmp2"
|
||||
else
|
||||
echo "do $DO_DEPTH$target exists." >&2
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Make corrections for directories that don't actually exist yet.
|
||||
_dir_shovel()
|
||||
{
|
||||
local dir base
|
||||
xdir="$1" xbase="$2" xbasetmp="$2"
|
||||
while [ ! -d "$xdir" -a -n "$xdir" ]; do
|
||||
_dirsplit "${xdir%/}"
|
||||
xbasetmp=${base}__"$xbase"
|
||||
xdir="$dir" xbase="$base"/"$xbase"
|
||||
echo "xbasetmp='$xbasetmp'" >&2
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
_redo()
|
||||
{
|
||||
set +e
|
||||
for i in "$@"; do
|
||||
_dirsplit "$i"
|
||||
_dir_shovel "$dir" "$base"
|
||||
dir="$xdir" base="$xbase" basetmp="$xbasetmp"
|
||||
( cd "$dir" && _do "$dir" "$base" "$basetmp" )
|
||||
[ "$?" = 0 ] || return 1
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
_redo "$@"
|
||||
[ "$?" = 0 ] || exit 1
|
||||
|
||||
if [ -n "$DO_TOP" ]; then
|
||||
echo "Removing stamp files..." >&2
|
||||
[ ! -e "$DO_BUILT" ] ||
|
||||
while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
|
||||
xargs -0 rm -f 2>/dev/null
|
||||
fi
|
Loading…
Reference in a new issue