diff --git a/redo/builder.py b/redo/builder.py index 2499f4c..eca8335 100644 --- a/redo/builder.py +++ b/redo/builder.py @@ -344,8 +344,17 @@ class _BuildJob(object): before_t = self.before_t after_t = _try_stat(t) st1 = os.fstat(f.fileno()) + st1b = _try_stat(self.tmpname1) st2 = _try_stat(self.tmpname2) - if (after_t and + if not st1.st_size and not st1b: + warn("%s: %s deleted %s; don't do that.\n" + % (_nice(t), argv[2], self.tmpname1)) + # not fatal, continue + if st1.st_size > 0 and not st1b: + err('%s: %s wrote to stdout but deleted %s.\n' + % (_nice(t), argv[2], self.tmpname1)) + rv = 207 + elif (after_t and (not before_t or before_t.st_mtime != after_t.st_mtime) and not stat.S_ISDIR(after_t.st_mode)): err('%s modified %s directly!\n' % (argv[2], t)) @@ -365,11 +374,15 @@ class _BuildJob(object): except OSError, e: dnt = os.path.dirname(t) if not os.path.exists(dnt): + # This could happen, so report a simple error message + # that gives a hint for how to fix your .do script. err('%s: target dir %r does not exist!\n' % (t, dnt)) else: + # I don't know why this would happen, so raise the + # full exception if it ever does. err('%s: rename %s: %s\n' % (t, self.tmpname2, e)) raise - os.unlink(self.tmpname1) + unlink(self.tmpname1) elif st1.st_size > 0: try: os.rename(self.tmpname1, t) diff --git a/t/202-del/.gitignore b/t/202-del/.gitignore index 5fbfe70..0b5079e 100644 --- a/t/202-del/.gitignore +++ b/t/202-del/.gitignore @@ -1 +1,2 @@ deltest2 +/destruct diff --git a/t/202-del/all.do b/t/202-del/all.do index da01d62..dcbcd15 100644 --- a/t/202-del/all.do +++ b/t/202-del/all.do @@ -1 +1 @@ -redo deltest deltest2 +redo deltest deltest2 deltest3 diff --git a/t/202-del/clean.do b/t/202-del/clean.do index 146f645..e2cf539 100644 --- a/t/202-del/clean.do +++ b/t/202-del/clean.do @@ -1 +1,2 @@ +rm -rf destruct rm -f deltest2 *~ .*~ diff --git a/t/202-del/deltest3.do b/t/202-del/deltest3.do new file mode 100644 index 0000000..d1ba8a7 --- /dev/null +++ b/t/202-del/deltest3.do @@ -0,0 +1,25 @@ +rm -rf destruct +mkdir destruct +cd destruct +cat >destruct1.do <<-EOF + rm -f *.tmp + echo 'redir' >\$3 +EOF +cat >destruct2.do <<-EOF + rm -f *.tmp + echo 'stdout' +EOF + +# deleting unused stdout file is a warning only +redo destruct1 2>destruct1.log || exit 11 +[ "$(cat destruct1)" = "redir" ] || exit 12 + +# deleting *used* stdout file may be a fatal mistake, +# but we won't enforce that, since some redo variants +# might be more accepting or use different tmp file +# algorithms. So either the file should be correct, +# or it should be missing. +redo destruct2 2>destruct2.log || : +if [ -e "destruct2" ]; then + [ "$(cat destruct2)" = "stdout" ] || exit 22 +fi