From ec72beb343b888eb52fc979ac7a95faffff82a4c Mon Sep 17 00:00:00 2001 From: Avery Pennarun Date: Fri, 2 Nov 2018 03:48:25 -0400 Subject: [PATCH] minimal/do: don't create a .did file until after a file is actually built. With the new "continue" feature on by default, it turned out that ctrl-c during a build, or a .do file returning an error, would mark a target as "built" even though it hadn't been. This would prevent retrying it when you started minimal/do again. Use a temp file instead. It's a little tricky: to prevent accidental recursion, we want to create a file *before* building, but clean up that file when starting the next session. And we rename that file to the actual .did file *after* building successfully. --- .gitignore | 4 ++-- minimal/do | 20 ++++++++++++-------- t/201-fail/.gitignore | 2 ++ t/201-fail/all.do | 12 +++++++++++- t/201-fail/clean.do | 2 +- t/201-fail/maybe-fail.do | 2 ++ t/360-symlinks/.gitignore | 2 +- t/360-symlinks/a.do | 2 +- t/360-symlinks/all.do | 10 +++++----- t/360-symlinks/b.do | 2 +- t/360-symlinks/clean.do | 2 +- 11 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 t/201-fail/maybe-fail.do diff --git a/.gitignore b/.gitignore index af04dc8..07cf226 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ /.redo +/.do_built +/.do_built.dir *~ *.pyc *.tmp /redo-sh *.did -.do_built -.do_built.dir diff --git a/minimal/do b/minimal/do index 2050c12..a586786 100755 --- a/minimal/do +++ b/minimal/do @@ -78,11 +78,12 @@ if [ -z "$DO_BUILT" -a "$_cmd" != "redo-whichdo" ]; then export DO_BUILT=$PWD/.do_built : >>"$DO_BUILT" sort -u "$DO_BUILT" >"$DO_BUILT.new" - if [ -n "$_do_opt_clean" ]; then - echo "Removing previously built files..." >&2 - while read f; do printf "%s\0%s.did\0" "$f" "$f"; done <"$DO_BUILT.new" | - xargs -0 rm -f 2>/dev/null - fi + echo "Cleaning up from previous run..." >&2 + while read f; do + [ -n "$_do_opt_clean" ] && printf "%s\0%s.did\0" "$f" "$f" + printf "%s.did.tmp\0" "$f" + done <"$DO_BUILT.new" | + xargs -0 rm -f 2>/dev/null mv "$DO_BUILT.new" "$DO_BUILT" DO_PATH=$DO_BUILT.dir export PATH=$DO_PATH:$PATH @@ -276,7 +277,6 @@ _do() echo "do: $target: no .do file ($PWD)" >&2 return 1 fi - echo "$PWD/$target" >>"$DO_BUILT" _dirsplit "$dopath" dodir=$_dirsplit_dir dofile=$_dirsplit_base if _startswith "$dofile" "default."; then @@ -292,18 +292,22 @@ _do() tmp=$(_relpath "$tmp") || return 97 base=${target%$ext} [ ! -e "$DO_BUILT" ] || [ ! -d "$(dirname "$target")" ] || - : >>"$target.did" + : >>"$target.did.tmp" ( _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" + rm -f "$tmp.tmp" "$tmp.tmp2" "$target.did" return $rv fi + echo "$PWD/$target" >>"$DO_BUILT" mv "$tmp.tmp" "$target" 2>/dev/null || ! test -s "$tmp.tmp2" || mv "$tmp.tmp2" "$target" 2>/dev/null + [ -e "$target.did.tmp" ] && + mv "$target.did.tmp" "$target.did" || + : >>"$target.did" rm -f "$tmp.tmp2" else _debug "do $DO_DEPTH$target exists." >&2 diff --git a/t/201-fail/.gitignore b/t/201-fail/.gitignore index e1c33af..dd9fa0f 100644 --- a/t/201-fail/.gitignore +++ b/t/201-fail/.gitignore @@ -1 +1,3 @@ /fail +/want-fail +/maybe-fail diff --git a/t/201-fail/all.do b/t/201-fail/all.do index 8857ea6..7c06cb9 100644 --- a/t/201-fail/all.do +++ b/t/201-fail/all.do @@ -4,7 +4,6 @@ rm -f this-doesnt-exist redo-ifcreate this-doesnt-exist >/dev/null 2>&1 || exit 34 # expected to pass - rm -f fail ! redo-ifchange fail >/dev/null 2>&1 || exit 44 # expected to fail @@ -16,3 +15,14 @@ redo-ifchange fail >/dev/null 2>&1 || exit 55 # expected to pass # Make sure we don't leave this lying around for future runs, or redo # might mark it as "manually modified" (since we did!) rm -f fail + +rm -f maybe-fail +: >want-fail +! redo-ifchange maybe-fail >/dev/null 2>&1 || exit 66 +rm -f want-fail +../flush-cache +redo-ifchange maybe-fail || exit 67 # failed last time, must retry +: >want-fail +../flush-cache +redo-ifchange maybe-fail || exit 68 # passed last time, no dep, no redo +rm -f want-fail diff --git a/t/201-fail/clean.do b/t/201-fail/clean.do index 436ff19..560df11 100644 --- a/t/201-fail/clean.do +++ b/t/201-fail/clean.do @@ -1 +1 @@ -rm -f fail *~ .*~ +rm -f fail maybe-fail want-fail *~ .*~ diff --git a/t/201-fail/maybe-fail.do b/t/201-fail/maybe-fail.do new file mode 100644 index 0000000..3939d0f --- /dev/null +++ b/t/201-fail/maybe-fail.do @@ -0,0 +1,2 @@ +[ -e 'want-fail' ] && exit 1 +echo x diff --git a/t/360-symlinks/.gitignore b/t/360-symlinks/.gitignore index 2b0acc8..063a5c1 100644 --- a/t/360-symlinks/.gitignore +++ b/t/360-symlinks/.gitignore @@ -1,4 +1,4 @@ -*.did +*.ran *.extra a b diff --git a/t/360-symlinks/a.do b/t/360-symlinks/a.do index 30b8320..b7bfe87 100644 --- a/t/360-symlinks/a.do +++ b/t/360-symlinks/a.do @@ -1,4 +1,4 @@ -echo x >>a.did +echo x >>a.ran rm -f $2.extra echo foo >$2.extra ln -s $2.extra $3 diff --git a/t/360-symlinks/all.do b/t/360-symlinks/all.do index 865207d..13ca7a3 100644 --- a/t/360-symlinks/all.do +++ b/t/360-symlinks/all.do @@ -1,14 +1,14 @@ -rm -f a a.extra b b.did +rm -f a a.extra b b.ran d0="" redo a redo-ifchange b -d1=$(cat b.did) +d1=$(cat b.ran) [ "$d0" != "$d1" ] || exit 11 # b only rebuilds if a changes ../flush-cache redo-ifchange b -d2=$(cat b.did) +d2=$(cat b.ran) [ "$d1" = "$d2" ] || exit 12 . ../skip-if-minimal-do.sh @@ -20,7 +20,7 @@ d2=$(cat b.did) ../flush-cache redo a redo-ifchange b -d3=$(cat b.did) +d3=$(cat b.ran) [ "$d2" != "$d3" ] || exit 13 # Explicitly check that changing a's symlink target (a.extra) does *not* @@ -30,5 +30,5 @@ d3=$(cat b.did) ../flush-cache touch a.extra redo-ifchange b -d4=$(cat b.did) +d4=$(cat b.ran) [ "$d3" = "$d4" ] || exit 14 diff --git a/t/360-symlinks/b.do b/t/360-symlinks/b.do index 52159b0..b5a3314 100644 --- a/t/360-symlinks/b.do +++ b/t/360-symlinks/b.do @@ -1,3 +1,3 @@ -echo x >>b.did +echo x >>b.ran redo-ifchange a cat a >$3 diff --git a/t/360-symlinks/clean.do b/t/360-symlinks/clean.do index fceeb8e..a819450 100644 --- a/t/360-symlinks/clean.do +++ b/t/360-symlinks/clean.do @@ -1 +1 @@ -rm -f *~ .*~ a b *.extra *.did +rm -f *~ .*~ a b *.extra *.ran