**Problem**
Disk cache currently uses symbolic links, which won't
work on Windows without the Administrator privileges or
Developer Mode.
**Solution**
This falls back to using file copy.
**Problem**
Current implementation of testQuick depends on the concept of timestamp,
which probably won't work well with the new consistent analysis store or
the idea of remote caching.
**Solution**
This is a step towards cached testing by making the incrementality hermetic
(no longer depends on the timestamp). Instead this calculates the aggregated
SHA-256 of the class files involved in the test.
**Problem**
Currently `syncBlobs` delete the existing files in the out directory when remote cache kicks in.
**Solution**
1. This refactors `Digest(...)` and adds support for `Digest.apply(Path)` and `Digest.sameDigest(...)`
2. This uses the `sameDigest` to compare the digest and replace the existing out files only when it needs to
For the details about this PR, please see the blog post https://eed3si9n.com/sbt-remote-cache/.
* Add cache basics
* Refactor Attributed to use StringAttributeMap, which is Map[StringAttributeKey, String]
* Implement disk cache
* Rename Package to Pkg
* Virtualize packageBin
* Use HashedVirtualFileRef for packageBin
* Virtualize compile task
I noticed that sbt does a _lot_ of no-op docs in the sbt project.
Through some debugging, I determined that this was because the target
directory last modified time of some of the dependent projects would
change between runs. I'm not really sure why that was happening but
instead of computing the last modified time of the directory, we should
be checking the last modified time of the directory contents.
After this change a no-op `doc` in the sbt project returns in less than
one second on my mac. Before, it was more like 25-60 seconds (the upper
bound is one runs `doc` because `sbtRoot/doc` takes about a minute).
We discovered in the community build that 1.3.0-RC4 breaks the
lucidchart scalafmt plugins. We can unbreak binary compatibility by
adding alternative classes.
There are just too many instances in which sbt's code relies on
the `lastModified`/`setLastModified` semantics, so instead of moving
to `get`/`setModifiedTime`, we use new IO calls that offer the new
timestamp precision, but retain the old semantics.
FileInfo is used to wrap information like last modified time on
files that may or may not exist. Arguably, that does not make
much sense: the non-existent files should not lead to modification
file information, hashes, and a persistent serialized version of
the resulting meaningless information. However, considering that
the FileInfo information is serialized and saved, it is necessary
to preserve compatibility at this stage. Therefore the modification
time is explicitly set to zero for those files that do not exist
when each FileInfo is built.