gittup / tup

Tup is a file-based build system.
http://gittup.org/tup/
GNU General Public License v2.0
1.18k stars 145 forks source link

Errors when command creates ignored files but fails #460

Open wizeman opened 2 years ago

wizeman commented 2 years ago

This script works as expected:

$ cat good.sh
#!/usr/bin/env bash

set -euo pipefail

rm -rf .tup cache

cat > Tupfile.lua <<EOF
tup.rule({}, 'mkdir -p cache && echo hi > cache/cache.txt', { '^cache' })
EOF

tup init
tup
$ ./good.sh
tup repository initialized: .tup/db
[ tup ] [0.004s] Scanning filesystem...
[ tup ] [0.007s] Reading in new environment variables...
[ tup ] [0.011s] Parsing Tupfiles...
 0) [0.003s] .
 [ ] 100%
[ tup ] [0.020s] No files to delete.
[ tup ] [0.023s] Executing Commands...
 0) [0.006s] mkdir -p cache && echo hi > cache/cache.txt
 [ ] 100%
[ tup ] [0.033s] Updated.

However, this very similar one doesn't (the only difference between them is the command ends in && false in the one below):

$ cat bad.sh
#!/usr/bin/env bash

set -euo pipefail

rm -rf .tup cache

cat > Tupfile.lua <<EOF
tup.rule({}, 'mkdir -p cache && echo hi > cache/cache.txt && false', { '^cache' })
EOF

tup init
tup
$ ./bad.sh
.tup repository initialized: .tup/db
[ tup ] [0.005s] Scanning filesystem...
[ tup ] [0.010s] Reading in new environment variables...
[ tup ] [0.014s] Parsing Tupfiles...
 0) [0.004s] .
 [ ] 100%
[ tup ] [0.023s] No files to delete.
[ tup ] [0.028s] Executing Commands...
 [ ]   0%/home/username/tmp/tup/cache/cache.txt: No such file or directory
* 0) mkdir -p cache && echo hi > cache/cache.txt && false
 *** tup messages ***
 *** Command ID=13 failed with return value 1
tup error: Unable to rename temporary file '.tup/tmp/0' to destination '/home/username/tmp/tup/cache/cache.txt'
 [ ] 100%
 *** tup: 1 job failed.

Apart from the tup error: Unable to rename temporary file ... and No such file or directory errors, there is also a major problem in that the cache/cache.txt file doesn't get generated as I expected (even though the command failed).

This prevents the cache file from being reused when the command runs the next time (and, in my real-world case, means that the command runs very slowly).