mirror of https://github.com/sbt/sbt.git
[2.x] fix: Fixes cache invaliation on version change
**Problem** packageBin includes version into the file name, which ends up invalidating the cache. **Solution** Define packageInternal, which does not include version in the file name.
This commit is contained in:
parent
b76ac09d44
commit
7ef5a3b2d7
|
|
@ -112,6 +112,25 @@ private[librarymanagement] abstract class ArtifactFunctions {
|
||||||
base + "-" + module.revision + classifierStr + "." + artifact.extension
|
base + "-" + module.revision + classifierStr + "." + artifact.extension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like `artifactName`, but omits the module's version.
|
||||||
|
*/
|
||||||
|
def internalArtifactName(
|
||||||
|
scalaVersion: ScalaVersion,
|
||||||
|
module: ModuleID,
|
||||||
|
artifact: Artifact
|
||||||
|
): String =
|
||||||
|
import artifact.*
|
||||||
|
val classifierStr = classifier match
|
||||||
|
case None => ""
|
||||||
|
case Some(c) => s"-${c}"
|
||||||
|
val cross = CrossVersion(module.crossVersion, scalaVersion.full, scalaVersion.binary)
|
||||||
|
val withPlatform = module.crossVersion match
|
||||||
|
case _: Disabled => artifact.name
|
||||||
|
case _ => CrossVersion.addPlatformSuffix(artifact.name, module.platformOpt, None)
|
||||||
|
val base = CrossVersion.applyCross(withPlatform, cross)
|
||||||
|
s"${base}${classifierStr}.${artifact.extension}"
|
||||||
|
|
||||||
val classifierTypeMap = Map(SourceClassifier -> SourceType, DocClassifier -> DocType)
|
val classifierTypeMap = Map(SourceClassifier -> SourceType, DocClassifier -> DocType)
|
||||||
@deprecated("Configuration should not be decided from the classifier.", "1.0")
|
@deprecated("Configuration should not be decided from the classifier.", "1.0")
|
||||||
def classifierConf(classifier: String): Configuration =
|
def classifierConf(classifier: String): Configuration =
|
||||||
|
|
|
||||||
|
|
@ -1770,6 +1770,8 @@ object Defaults extends BuildCommon with DefExtra {
|
||||||
packageTaskSettings(packageBin, packageBinMappings) ++
|
packageTaskSettings(packageBin, packageBinMappings) ++
|
||||||
packageTaskSettings(packageSrc, packageSrcMappings) ++
|
packageTaskSettings(packageSrc, packageSrcMappings) ++
|
||||||
packageTaskSettings(packageDoc, packageDocMappings) ++
|
packageTaskSettings(packageDoc, packageDocMappings) ++
|
||||||
|
packageTaskSettings(packageInternal, packageBinMappings) ++
|
||||||
|
inTask(packageInternal)(Seq(artifactName :== Artifact.internalArtifactName)) ++
|
||||||
Seq(Keys.`package` := packageBin.value)
|
Seq(Keys.`package` := packageBin.value)
|
||||||
|
|
||||||
def packageBinMappings: Initialize[Task[Seq[(HashedVirtualFileRef, String)]]] =
|
def packageBinMappings: Initialize[Task[Seq[(HashedVirtualFileRef, String)]]] =
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,7 @@ object Keys {
|
||||||
|
|
||||||
// package keys
|
// package keys
|
||||||
val packageBin = taskKey[HashedVirtualFileRef]("Produces a main artifact, such as a binary jar.").withRank(ATask)
|
val packageBin = taskKey[HashedVirtualFileRef]("Produces a main artifact, such as a binary jar.").withRank(ATask)
|
||||||
|
val packageInternal = taskKey[HashedVirtualFileRef]("Produces a binary JAR for internal use (inter-project classpaths, BSP).").withRank(DTask)
|
||||||
val `package` = taskKey[HashedVirtualFileRef]("Produces the main artifact, such as a binary jar. This is typically an alias for the task that actually does the packaging.").withRank(APlusTask)
|
val `package` = taskKey[HashedVirtualFileRef]("Produces the main artifact, such as a binary jar. This is typically an alias for the task that actually does the packaging.").withRank(APlusTask)
|
||||||
val packageDoc = taskKey[HashedVirtualFileRef]("Produces a documentation artifact, such as a jar containing API documentation.").withRank(AMinusTask)
|
val packageDoc = taskKey[HashedVirtualFileRef]("Produces a documentation artifact, such as a jar containing API documentation.").withRank(AMinusTask)
|
||||||
val packageSrc = taskKey[HashedVirtualFileRef]("Produces a source artifact, such as a jar containing sources and resources.").withRank(AMinusTask)
|
val packageSrc = taskKey[HashedVirtualFileRef]("Produces a source artifact, such as a jar containing sources and resources.").withRank(AMinusTask)
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ private[sbt] object ClasspathImpl {
|
||||||
(Def
|
(Def
|
||||||
.task {
|
.task {
|
||||||
val converter = fileConverter.value
|
val converter = fileConverter.value
|
||||||
val vf = (packageBin / artifactPath).value
|
val vf = (packageInternal / artifactPath).value
|
||||||
val jar = converter.toPath(vf)
|
val jar = converter.toPath(vf)
|
||||||
(TrackLevel.intersection(track, exportToInternal.value), vf, jar)
|
(TrackLevel.intersection(track, exportToInternal.value), vf, jar)
|
||||||
})
|
})
|
||||||
|
|
@ -141,13 +141,13 @@ private[sbt] object ClasspathImpl {
|
||||||
Def.task {
|
Def.task {
|
||||||
val converter = fileConverter.value
|
val converter = fileConverter.value
|
||||||
val analysisFile = converter.toVirtualFile(compileAnalysisFile.value.toPath)
|
val analysisFile = converter.toVirtualFile(compileAnalysisFile.value.toPath)
|
||||||
Seq((packageBin.value, analysisFile))
|
Seq((packageInternal.value, analysisFile))
|
||||||
}
|
}
|
||||||
case (TrackLevel.TrackIfMissing, _, jar) if !jar.toFile().exists =>
|
case (TrackLevel.TrackIfMissing, _, jar) if !jar.toFile().exists =>
|
||||||
Def.task {
|
Def.task {
|
||||||
val converter = fileConverter.value
|
val converter = fileConverter.value
|
||||||
val analysisFile = converter.toVirtualFile(compileAnalysisFile.value.toPath)
|
val analysisFile = converter.toVirtualFile(compileAnalysisFile.value.toPath)
|
||||||
Seq((packageBin.value, analysisFile))
|
Seq((packageInternal.value, analysisFile))
|
||||||
}
|
}
|
||||||
case (_, vf, _) =>
|
case (_, vf, _) =>
|
||||||
Def.task {
|
Def.task {
|
||||||
|
|
|
||||||
|
|
@ -824,7 +824,7 @@ object BuildServerProtocol {
|
||||||
val internalDependencyClasspath = for {
|
val internalDependencyClasspath = for {
|
||||||
(ref, configs) <- bspInternalDependencyConfigurations.value
|
(ref, configs) <- bspInternalDependencyConfigurations.value
|
||||||
config <- configs
|
config <- configs
|
||||||
} yield ref / config / Keys.packageBin
|
} yield ref / config / Keys.packageInternal
|
||||||
(
|
(
|
||||||
target,
|
target,
|
||||||
scalacOptions,
|
scalacOptions,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package example
|
||||||
|
|
||||||
|
@main
|
||||||
|
def main(args: String*): Unit =
|
||||||
|
println(Foo.greeting)
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import sbt.internal.util.CacheEventSummary
|
||||||
|
import complete.DefaultParsers.*
|
||||||
|
|
||||||
|
Global / localCacheDirectory := baseDirectory.value / "diskcache"
|
||||||
|
|
||||||
|
scalaVersion := "3.8.4"
|
||||||
|
|
||||||
|
lazy val checkMiss = inputKey[Unit]("Assert the exact onsite/miss count of the previous run")
|
||||||
|
|
||||||
|
lazy val foo = project
|
||||||
|
|
||||||
|
lazy val app = project.dependsOn(foo)
|
||||||
|
|
||||||
|
lazy val root = (project in file("."))
|
||||||
|
.aggregate(foo, app)
|
||||||
|
.settings(
|
||||||
|
checkMiss := {
|
||||||
|
val expected: Int = (Space ~> NatBasic).parsed
|
||||||
|
val s = streams.value
|
||||||
|
val config = Def.cacheConfiguration.value
|
||||||
|
val prev = config.cacheEventLog.previous match
|
||||||
|
case d: CacheEventSummary.Data => d
|
||||||
|
case CacheEventSummary.Empty => sys.error("empty event log")
|
||||||
|
s.log.info(s"missCount = ${prev.missCount}")
|
||||||
|
assert(prev.missCount == expected, s"prev.missCount = ${prev.missCount} (expected $expected)")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package example
|
||||||
|
|
||||||
|
object Foo:
|
||||||
|
def greeting: String = "hello"
|
||||||
|
end Foo
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
# warm the disk cache
|
||||||
|
> app/compile
|
||||||
|
|
||||||
|
# after a clean, recompiling app (and foo) should fully restore from the disk cache
|
||||||
|
> clean
|
||||||
|
> app/compile
|
||||||
|
> checkMiss 0
|
||||||
|
|
||||||
|
# bumping foo's version alone (e.g. what sbt-dynver would do on a new commit) must not
|
||||||
|
# invalidate app's compile cache entry, since foo's jar content hasn't changed
|
||||||
|
> set foo / version := "0.2.0"
|
||||||
|
> clean
|
||||||
|
> app/compile
|
||||||
|
> checkMiss 0
|
||||||
Loading…
Reference in New Issue