The second half of redo-stamp: out-of-order building.

If a depends on b depends on c, and c is dirty but b uses redo-stamp
checksums, then 'redo-ifchange a' is indeterminate: we won't know if we need
to run a.do unless we first build b, but the script that *normally* runs
'redo-ifchange b' is a.do, and we don't want to run that yet, because we
don't know for sure if b is dirty, and we shouldn't build a unless one of
its dependencies is dirty.  Eek!

Luckily, there's a safe solution.  If we *know* a is dirty - eg. because
a.do or one of its children has definitely changed - then we can just run
a.do immediately and there's no problem, even if b is indeterminate, because
we were going to run a.do anyhow.

If a's dependencies are *not* definitely dirty, and all we have is
indeterminate ones like b, then that means a's build process *hasn't
changed*, which means its tree of dependencies still includes b, which means
we can deduce that if we *did* run a.do, it would end up running b.do.

Since we know that anyhow, we can safely just run b.do, which will either
b.set_checked() or b.set_changed().  Once that's done, we can re-parse a's
dependencies and this time conclusively tell if it needs to be redone or
not.  Even if it does, b is already up-to-date, so the 'redo-ifchange b'
line in a.do will be fast.

...now take all the above and do it recursively to handle nested
dependencies, etc, and you're done.
This commit is contained in:
Avery Pennarun 2010-12-11 04:40:05 -08:00
commit f702417ef3
6 changed files with 124 additions and 26 deletions

View file

@ -22,19 +22,19 @@ redo-ifchange usestamp
redo bob
redo-ifchange usestamp
[ "$(wc -l <stampy.log)" -eq 3 ] || exit 43
[ "$(wc -l <usestamp.log)" -eq 2 ] || exit 44
[ "$(wc -l <usestamp.log)" -eq 1 ] || exit 44
../flush-cache.sh
redo-ifchange usestamp
[ "$(wc -l <stampy.log)" -eq 3 ] || exit 45
[ "$(wc -l <usestamp.log)" -eq 2 ] || exit 46
[ "$(wc -l <usestamp.log)" -eq 1 ] || exit 46
../flush-cache.sh
echo two >inp
redo stampy
[ "$(wc -l <stampy.log)" -eq 4 ] || exit 51
[ "$(wc -l <usestamp.log)" -eq 2 ] || exit 52
[ "$(wc -l <usestamp.log)" -eq 1 ] || exit 52
redo-ifchange usestamp
[ "$(wc -l <stampy.log)" -eq 4 ] || exit 61
[ "$(wc -l <usestamp.log)" -eq 3 ] || exit 62
[ "$(wc -l <usestamp.log)" -eq 2 ] || exit 62