sbt-cached-updates is an sbt plugin which caches all the sbt update tasks.
By default, sbt only caches the update
task. It does not cache updateClassifiers
or updateSbtClassifiers
.
This plugin fixes that.
If you notice that updates are slow or perhaps importing/refreshing the sbt project in Intellij IDEA takes forever then you may benefit from using this plugin.
To diagnose what task is slow then either:
- run sbt with:
or,
sbt -Dsbt.task.timings=true -Dsbt.task.timings.on.shutdown=false
- enable the sbt-optimizer plugin.
Keep in mind that updates are forced when you run the task directly.
This is an AutoPlugin
which is automatically added to any project which requires
the IvyPlugin
which is the
default for all projects.
This plugin requires sbt 1.0.0+.
It is recommended that you add this plugin to your project/plugins.sbt
file:
addSbtPlugin("nz.co.bottech" % "sbt-cached-updates" % "1.0.0")
If you also work on other projects that do not use this plugin then add the line above to
~/.sbt/1.0/plugins/build.sbt
.
One thing that may prevent the cache from working is the ~/.ivy2/exclude_classifiers
file.
It seems that this file is to try and prevent repeatedly attempting to download classifiers that do not exist. The problem is that it frequently ends up either not excluding enough or excluding too much.
It is strongly recommended that you delete this file and the lock file before using this plugin.
updateClassifiers
will now print the message:
Updating classifiers for xxx...
when it is updating, just like it does for update
. If you don't see this then it is using the cached results.
You can find the update cache in xxx/target/streams/$global/updateClassifiers/$global/streams/update_cache_2.12
.
This directory will contain two files:
inputs
- The hash of all the inputs.output
- The results from running the update.
If the hash is different to the previous hash then there will be a cache miss and the update task will run and cache the new results.
updateSbtClassifiers
works a little bit differently. It will first update a "base" module and then get all the
modules from that and then again with the classifiersModule
that has all the modules as dependencies.
The messages for this look like:
Updating classifiers for sbt (base)...
...
Updating classifiers for sbt (modules)...
This is normal if you have actually changed a dependency or if you are running the task directly.
To see what is going on enable debug logging:
set xxx/updateClassifiers/logLevel := Level.Debug
Now when you run your task watch out for the messages:
[debug] Input hash: Success(1021736120)
[debug] ...
[info] Updating classifiers for xxx...
The messages in between will tell you why it isn't using the cached output.
You may see that the hash is changing between executions, followed by a message saying that the inputs have changed, even though you have not changed any dependencies.
When run with debug logging there will be an additional file in the cache directory:
inputs.json
- JSON representation of the inputs that is hashed.
Compare the inputs.json
files from two separate executions.
As mentioned earlier, sbt will generate a ~/.ivy2/exclude_classifiers
file. These are filtered out of the inputs.
Then when the update runs it will take the excludes from the update report and overwrite the exclude_classifiers
file.
What can happen is that the exclude_classifiers
file gets into a strange state where it has only one classifier
excluded for a library when it should have both. This causes the inputs to alternate.
For example; If exclude_classifiers
contains sources
then when the update runs it ignores sources
but then the
report will say to exclude javadoc
. Now exclude_classifiers
will contain javadoc
but not sources
. It keeps
alternating between javadoc
and sources
.
This is likely a bug in sbt, specifically sbt.Classpaths$.withExcludes
, but I have been unable to find a way to
reliably reproduce it.
This plugin was generated from the BotTech/sbt-autoplugin.g8 Giter8 template.
Special thanks to: