minimal/do: add support for -x -v -d -c options.

-x, -v, and -d are the same as redo.

-c means "continuable", which disables the feature that deletes (and
forgets) all targets at the start of each run.  This is a little risky,
since minimal/do still doesn't understand dependencies, but it allows
you to run minimal/do several times in succession, so that

    minimal/do -c a
    minimal/do -c b
is the same as
    minimal/do a b
This commit is contained in:
Avery Pennarun 2018-10-17 02:57:33 -04:00
commit 0fc2e46708
2 changed files with 47 additions and 15 deletions

View file

@ -33,7 +33,7 @@ If you've ever thought about rewriting GNU make from scratch, the idea of
doing it in 250 lines of shell script probably didn't occur to you. redo is doing it in 250 lines of shell script probably didn't occur to you. redo is
so simple that it's actually possible. For testing, I actually wrote an so simple that it's actually possible. For testing, I actually wrote an
even more minimal version, which always rebuilds everything instead of even more minimal version, which always rebuilds everything instead of
checking dependencies, in 150 lines of shell (about 3 kbytes). checking dependencies, in 210 lines of shell (about 4 kbytes).
The design is simply that good. The design is simply that good.

View file

@ -36,30 +36,56 @@ export REDO=$(cd "${dir:-.}" && echo "$PWD/$base")
if [ "$base" = "redo-ifchange" ]; then ifchange=1; else ifchange=; fi if [ "$base" = "redo-ifchange" ]; then ifchange=1; else ifchange=; fi
DO_TOP= DO_TOP=
if [ -z "$DO_BUILT" ]; then
export _do_opt_debug=
export _do_opt_exec=
export _do_opt_verbose=
export _do_opt_continuable=
fi
while getopts dxvc _opt; do
case $_opt in
d) _do_opt_debug=1 ;;
x) _do_opt_exec=x ;;
v) _do_opt_verbose=v ;;
c) _do_opt_continuable=1 ;;
*) printf "\nusage: $0 [-d] [-x] [-v] [-c] <targets...>\n" >&2
exit 99
;;
esac
done
shift "$((OPTIND - 1))"
_debug() {
[ -z "$_do_opt_debug" ] || echo "$@" >&2
}
if [ -z "$DO_BUILT" ]; then if [ -z "$DO_BUILT" ]; then
DO_TOP=1 DO_TOP=1
[ -n "$*" ] || set all # only toplevel redo has a default target [ "$#" -gt 0 ] || set all # only toplevel redo has a default target
export DO_BUILT=$PWD/.do_built export DO_BUILT=$PWD/.do_built
: >>"$DO_BUILT" : >>"$DO_BUILT"
sort -u "$DO_BUILT" >"$DO_BUILT.new"
if [ -z "$_do_opt_continuable" ]; then
echo "Removing previously built files..." >&2 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 <"$DO_BUILT.new" |
while read f; do printf "%s\0%s.did\0" "$f" "$f"; done |
xargs -0 rm -f 2>/dev/null xargs -0 rm -f 2>/dev/null
fi
mv "$DO_BUILT.new" "$DO_BUILT" mv "$DO_BUILT.new" "$DO_BUILT"
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
ln -s "$REDO" "$DO_PATH/$d"; ln -s "$REDO" "$DO_PATH/$d"
done done
[ -e /bin/true ] && TRUE=/bin/true || TRUE=/usr/bin/true [ -e /bin/true ] && TRUE=/bin/true || TRUE=/usr/bin/true
for d in redo-ifcreate redo-stamp redo-always; do for d in redo-ifcreate redo-stamp redo-always; do
ln -s $TRUE "$DO_PATH/$d"; ln -s $TRUE "$DO_PATH/$d"
done done
fi fi
_find_dofile_pwd() _find_dofile_pwd()
{ {
dofile=default.$1.do dofile=default.$1.do
@ -98,8 +124,10 @@ _run_dofile()
read line1 <"$PWD/$dofile" || true read line1 <"$PWD/$dofile" || true
cmd=${line1#"#!/"} cmd=${line1#"#!/"}
if [ "$cmd" != "$line1" ]; then if [ "$cmd" != "$line1" ]; then
set -$_do_opt_verbose$_do_opt_exec
/$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2" /$cmd "$PWD/$dofile" "$@" >"$tmp.tmp2"
else else
set -$_do_opt_verbose$_do_opt_exec
:; . "$PWD/$dofile" >"$tmp.tmp2" :; . "$PWD/$dofile" >"$tmp.tmp2"
fi fi
} }
@ -108,7 +136,9 @@ _run_dofile()
_do() _do()
{ {
local dir="$1" target="$2" tmp="$3" local dir="$1" target="$2" tmp="$3"
if [ -z "$ifchange" ] || ( [ ! -e "$target" -o -d "$target" ] && [ ! -e "$target.did" ] ); then if [ -z "$ifchange" ] ||
( [ ! -e "$target" -o -d "$target" ] &&
[ ! -e "$target.did" ] ); then
printf '%sdo %s%s%s%s\n' \ printf '%sdo %s%s%s%s\n' \
"$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2 "$green" "$DO_DEPTH" "$bold" "$dir$target" "$plain" >&2
echo "$PWD/$target" >>"$DO_BUILT" echo "$PWD/$target" >>"$DO_BUILT"
@ -135,7 +165,7 @@ _do()
mv "$tmp.tmp2" "$target" 2>/dev/null mv "$tmp.tmp2" "$target" 2>/dev/null
rm -f "$tmp.tmp2" rm -f "$tmp.tmp2"
else else
echo "do $DO_DEPTH$target exists." >&2 _debug "do $DO_DEPTH$target exists." >&2
fi fi
} }
@ -149,7 +179,7 @@ _dir_shovel()
_dirsplit "${xdir%/}" _dirsplit "${xdir%/}"
xbasetmp=${base}__$xbase xbasetmp=${base}__$xbase
xdir=$dir xbase=$base/$xbase xdir=$dir xbase=$base/$xbase
echo "xbasetmp='$xbasetmp'" >&2 _debug "xbasetmp='$xbasetmp'" >&2
done done
} }
@ -171,8 +201,10 @@ _redo "$@"
[ "$?" = 0 ] || exit 1 [ "$?" = 0 ] || exit 1
if [ -n "$DO_TOP" ]; then if [ -n "$DO_TOP" ]; then
if [ -z "$_do_opt_continuable" ]; then
echo "Removing stamp files..." >&2 echo "Removing stamp files..." >&2
[ ! -e "$DO_BUILT" ] || [ ! -e "$DO_BUILT" ] ||
while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" | while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
xargs -0 rm -f 2>/dev/null xargs -0 rm -f 2>/dev/null
fi fi
fi