redo
Alan Grosskurth's 2007 implementation of Daniel J. Bernstein's redo package was targetted at the Bourne Shell and was slightly simplistic.
This package comprises modified versions of Grosskurth's original scripts, with the following improvements:
The scripts now use the Bourne Again shell rather than the Bourne shell.
This allowed the use of BASHisms such as the printf builtin and $() expansion.
The interpreter that runs .do files is not fixed to only the Bourne shell.
.do script files must have a "hash-bang" at the start of the file, and must have execute permission (--x--x--x) turned on.
The MD5 data are now stored in the right place in the .redo database.
As Grosskurth pointed out, he took the shortcut of recording each target's MD5 hash in the database entry for that target.
This unfortunately means that an interrupted build loses information about which dependents remain built with the older revision of a rebuilt dependency.
If A and B both depend from target T, then interrupting a build after T and B were both built would lose the information that A was built with an older T with a different MD5 hash value.
These modified scripts store each dependency's MD5 has value in the database entry for the dependent.
Interrupting a build after T and B were both built retains the old MD5 hash for T in the database entry for A, which causes A to continue to be regarded as out of date with respect to T.
Both MD5 data and last modification timestamps are used.
It's quite expensive to run md5sum over every target and source file in the dependency tree, just to check whether their hashes have changed.
These modified scripts store the last modification timestamp as well and only bother to recalculate the MD5 hash for files whose last modification timestamps have changed, on the principle that, notwithstanding any intentional mucking around with timestamps by the user, if a file's last modification timestamp hasn't been changed, it hasn't been written to and its MD5 hash cannot thus have changed.
The scripts use stat from GNU fileutils for this.
Special files don't confuse things.
With some judicious use of [ -f ] instead of [ -e ], these scripts avoid problems with targets that are symbolic links, unix domain pipes or sockets, or block or character device files.
Such files do not have their MD5 hash taken (Imagine using redo for building /dev the old MAKEDEV way and MD5 hashing /dev/zero!) and are always taken to be "changed" when rebuilding.
The .redo database has less extraneous stuff.
It turns out that the following are simply unnecessary:
target.type files —
An existing file that doesn't have a database entry is by definition a source file, as a target (even if it doesn't exist) will always have a database entry.
There's no need to record anything in the database to mark source files.
As a side-effect of this, source files outwith the working directory tree (such as, say, headers in /usr/include) don't end up having useless database entries.
target.result files —
This needlessly duplicates the uptodate information.
These modified shell scripts are not intended to provide the extra functionality of Avery Pennarun's Python scripts.
Their target use is systems without Python, or without SQLite, and they provide the minimal necessary functionality for a working redo build system without extra things — not strictly necessary for the basic task of building — such as parallel building, complex search rules for .do files, debug trace capability, and redo-always.