writeSiteArchive already supported rebuilding in place (rather than
creating a new build directory and moving it into place; see comments
at top of builder.js), but it was not used and didn't work:
* run-app.js only passed previousBuilders to the bundler in the case
of a client-only refresh, in which case it also passed
hasCachedBundle, bypassing writeSiteArchive altogether.
* writeSiteArchive's use of previousBuilders seemingly didn't work,
because the site archive itself was never written in place, so
trying to write the targets "in place" into a brand-new build
directory didn't make sense (and threw an error).
With this change, previousBuilders are kept across all rebuilds
(not just client-only refreshes), which enables efficient, in-place
building (except on Windows, where in-place building has never been
supported), and writeSiteArchive is fixed to write the site archive
in place as well.
The only reason for the files.stat in atomicallyRewriteFile (called
by Builder#write), which was taking up time comparable to write
and rename (not as much as one of those but same order of
magnitude, in the hundreds of ms total)... was for the case where we
are trying to rename a file in a way that overwrites an existing
directory. We can avoid the stat by catching this unusual case when
rename throws an error.
The exact borderline between "Isobuild" and "the tool" is a little hazy,
but the idea is that "Isobuild" is the part that you could imagine being
embedded in a non-command-line build tool. It's not about commands or
UI, but just about building packages and apps.
A next step could be moving things that are strictly "the command-line
tool" into their own subdir, and leaving the top directory mostly just
for shared utilities like buildmessage. (Which could even go in a utils
subdir?)