Refactor remote cache to per-config

Refactor remote caching to be scoped to configuration.
In addition, this avoid the use of dependency resolver (since I'm not resolving anything) and directly invoke the Ivy resolver for the artifact, somewhat analogus to publishing process.
This should speed up the `pullRemoteCache` since it avoids the POM download as well.

For sbt-binrary-remote-cache this created a bit of complication since the (publishing) resolver doesn't act correctly as (downloading) resolver in terms of the credentials, so I had to create a new key `remoteCacheResolvers` to have asymmetric resolver.
This commit is contained in:
Eugene Yokota 2020-11-01 15:08:46 -05:00
parent 078280ac47
commit 744cfefa6c
7 changed files with 224 additions and 158 deletions

View File

@ -16,7 +16,7 @@ ThisBuild / versionScheme := Some("early-semver")
ThisBuild / scalafmtOnCompile := !(Global / insideCI).value ThisBuild / scalafmtOnCompile := !(Global / insideCI).value
ThisBuild / Test / scalafmtOnCompile := !(Global / insideCI).value ThisBuild / Test / scalafmtOnCompile := !(Global / insideCI).value
ThisBuild / turbo := true ThisBuild / turbo := true
ThisBuild / usePipelining := !(Global / insideCI).value ThisBuild / usePipelining := false // !(Global / insideCI).value
val excludeLint = SettingKey[Set[Def.KeyedInitialize[_]]]("excludeLintKeys") val excludeLint = SettingKey[Set[Def.KeyedInitialize[_]]]("excludeLintKeys")
Global / excludeLint := (Global / excludeLint).?.value.getOrElse(Set.empty) Global / excludeLint := (Global / excludeLint).?.value.getOrElse(Set.empty)

View File

@ -386,6 +386,7 @@ object Keys {
val pushRemoteCacheArtifact = settingKey[Boolean]("Enables publishing an artifact to remote cache.") val pushRemoteCacheArtifact = settingKey[Boolean]("Enables publishing an artifact to remote cache.")
val pushRemoteCacheConfiguration = taskKey[PublishConfiguration]("") val pushRemoteCacheConfiguration = taskKey[PublishConfiguration]("")
val pushRemoteCacheTo = settingKey[Option[Resolver]]("The resolver to publish remote cache to.") val pushRemoteCacheTo = settingKey[Option[Resolver]]("The resolver to publish remote cache to.")
val remoteCacheResolvers = settingKey[Seq[Resolver]]("Resolvers for remote cache.")
val remoteCachePom = taskKey[File]("Generates a pom for publishing when publishing Maven-style.") val remoteCachePom = taskKey[File]("Generates a pom for publishing when publishing Maven-style.")
val usePipelining = settingKey[Boolean]("Use subproject pipelining for compilation.").withRank(BSetting) val usePipelining = settingKey[Boolean]("Use subproject pipelining for compilation.").withRank(BSetting)
val exportPipelining = settingKey[Boolean]("Product early output so downstream subprojects can do pipelining.").withRank(BSetting) val exportPipelining = settingKey[Boolean]("Product early output so downstream subprojects can do pipelining.").withRank(BSetting)

View File

@ -14,10 +14,15 @@ import Keys._
import SlashSyntax0._ import SlashSyntax0._
import ScopeFilter.Make._ import ScopeFilter.Make._
import Project._ // for tag and inTask() import Project._ // for tag and inTask()
import org.apache.ivy.core.module.descriptor.{ Artifact => IArtifact, DefaultArtifact }
import org.apache.ivy.core.resolve.DownloadOptions
import org.apache.ivy.core.report.DownloadStatus
import org.apache.ivy.plugins.resolver.DependencyResolver
import std.TaskExtra._ // for join import std.TaskExtra._ // for join
import sbt.coursierint.LMCoursier import sbt.coursierint.LMCoursier
import sbt.librarymanagement._ import sbt.librarymanagement._
import sbt.librarymanagement.ivy.Credentials import sbt.librarymanagement.ivy.{ Credentials, IvyPaths, UpdateOptions }
import sbt.librarymanagement.syntax._ import sbt.librarymanagement.syntax._
import sbt.nio.FileStamp import sbt.nio.FileStamp
import sbt.nio.Keys.{ inputFileStamps, outputFileStamps } import sbt.nio.Keys.{ inputFileStamps, outputFileStamps }
@ -52,94 +57,43 @@ object RemoteCache {
) )
lazy val projectSettings: Seq[Def.Setting[_]] = (Seq( lazy val projectSettings: Seq[Def.Setting[_]] = (Seq(
remoteCacheId := (Def.taskDyn { pushRemoteCache := (Def.taskDyn {
val filter = val arts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
ScopeFilter(configurations = inConfigurations(Compile, Test), tasks = inTasks(packageCache)) val configs = arts flatMap { art =>
art.packaged.scopedKey.scope match {
case Scope(_, Select(c), _, _) => Some(c)
case _ => None
}
}
val filter = ScopeFilter(configurations = inConfigurationsByKeys(configs: _*))
Def.task { Def.task {
val allHashes = remoteCacheId.all(filter).value val _ = pushRemoteCache.all(filter).value
combineHash(allHashes.toVector) ()
}
}).value,
pullRemoteCache := (Def.taskDyn {
val arts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
val configs = arts flatMap { art =>
art.packaged.scopedKey.scope match {
case Scope(_, Select(c), _, _) => Some(c)
case _ => None
}
}
val filter = ScopeFilter(configurations = inConfigurationsByKeys(configs: _*))
Def.task {
val _ = pullRemoteCache.all(filter).value
()
} }
}).value, }).value,
remoteCacheIdCandidates := List(remoteCacheId.value),
remoteCacheProjectId := {
val o = organization.value
val m = moduleName.value
val id = remoteCacheId.value
val c = (projectID / crossVersion).value
val v = toVersion(id)
ModuleID(o, m, v).cross(c)
},
pushRemoteCacheConfiguration / publishMavenStyle := true,
pushRemoteCacheConfiguration / packagedArtifacts := Def.taskDyn {
val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
artifacts
.map(a => a.packaged.map(file => (a.artifact, file)))
.join
.apply(_.join.map(_.toMap))
}.value,
pushRemoteCacheConfiguration / remoteCacheArtifacts := { pushRemoteCacheConfiguration / remoteCacheArtifacts := {
enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value
}, },
pushRemoteCacheConfiguration / publishMavenStyle := true,
Compile / packageCache / pushRemoteCacheArtifact := true, Compile / packageCache / pushRemoteCacheArtifact := true,
Test / packageCache / pushRemoteCacheArtifact := true, Test / packageCache / pushRemoteCacheArtifact := true,
Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier), Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier),
Test / packageCache / artifact := Artifact(moduleName.value, cachedTestClassifier), Test / packageCache / artifact := Artifact(moduleName.value, cachedTestClassifier),
remoteCachePom / pushRemoteCacheArtifact := true, remoteCachePom / pushRemoteCacheArtifact := true,
pushRemoteCacheConfiguration := {
Classpaths.publishConfig(
(pushRemoteCacheConfiguration / publishMavenStyle).value,
Classpaths.deliverPattern(crossTarget.value),
if (isSnapshot.value) "integration" else "release",
ivyConfigurations.value.map(c => ConfigRef(c.name)).toVector,
(pushRemoteCacheConfiguration / packagedArtifacts).value.toVector,
(pushRemoteCacheConfiguration / checksums).value.toVector,
Classpaths.getPublishTo(pushRemoteCacheTo.value).name,
ivyLoggingLevel.value,
isSnapshot.value
)
},
pullRemoteCache := {
val log = streams.value.log
val smi = scalaModuleInfo.value
val dr = (pullRemoteCache / dependencyResolution).value
val is = (pushRemoteCache / ivySbt).value
val t = crossTarget.value / "cache-download"
val p = remoteCacheProjectId.value
val ids = remoteCacheIdCandidates.value
val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
val applicable = artifacts.filterNot(isPomArtifact)
val classifiers = applicable.flatMap(_.artifact.classifier).toVector
var found = false
ids foreach {
id: String =>
val v = toVersion(id)
val modId = p.withRevision(v)
if (found) ()
else
pullFromMavenRepo0(modId, classifiers, smi, is, dr, t, log) match {
case Right(xs0) =>
val jars = xs0.distinct
applicable.foreach { art =>
val classifier = art.artifact.classifier
findJar(classifier, v, jars) match {
case Some(jar) =>
extractJar(art, jar)
log.info(s"remote cache artifact extracted for $p $classifier")
case None =>
log.info(s"remote cache artifact not found for $p $classifier")
}
}
found = true
case Left(unresolvedWarning) =>
log.info(s"remote cache not found for ${v}")
}
}
},
remoteCachePom := { remoteCachePom := {
val s = streams.value val s = streams.value
val config = (remoteCachePom / makePomConfiguration).value val config = (remoteCachePom / makePomConfiguration).value
@ -156,62 +110,43 @@ object RemoteCache {
}, },
remoteCachePom / remoteCacheArtifact := { remoteCachePom / remoteCacheArtifact := {
PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom) PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom)
} },
remoteCacheResolvers := pushRemoteCacheTo.value.toVector,
) ++ inTask(pushRemoteCache)( ) ++ inTask(pushRemoteCache)(
Seq( Seq(
ivyPaths := IvyPaths(baseDirectory.value, crossTarget.value / "remote-cache"),
ivyConfiguration := { ivyConfiguration := {
val other = pushRemoteCacheTo.value.toVector
val config0 = Classpaths.mkIvyConfiguration.value val config0 = Classpaths.mkIvyConfiguration.value
config0 config0
.withOtherResolvers(other) .withResolvers(remoteCacheResolvers.value.toVector)
.withOtherResolvers(pushRemoteCacheTo.value.toVector)
.withResolutionCacheDir(crossTarget.value / "alt-resolution") .withResolutionCacheDir(crossTarget.value / "alt-resolution")
.withPaths(ivyPaths.value)
.withUpdateOptions(UpdateOptions().withGigahorse(true))
}, },
ivySbt := { ivySbt := {
val config0 = ivyConfiguration.value
Credentials.register(credentials.value, streams.value.log) Credentials.register(credentials.value, streams.value.log)
val config0 = ivyConfiguration.value
new IvySbt(config0, CustomHttp.okhttpClient.value) new IvySbt(config0, CustomHttp.okhttpClient.value)
}, },
ivyModule := {
val is = ivySbt.value
new is.Module(moduleSettings.value)
},
moduleSettings := {
val smi = scalaModuleInfo.value
ModuleDescriptorConfiguration(remoteCacheProjectId.value, projectInfo.value)
.withScalaModuleInfo(smi)
},
pushRemoteCache.in(Defaults.TaskZero) := (Def.task {
val s = streams.value
val config = pushRemoteCacheConfiguration.value
IvyActions.publish(ivyModule.value, config, s.log)
} tag (Tags.Publish, Tags.Network)).value
) )
) ++ inTask(pullRemoteCache)( ) ++ inTask(pullRemoteCache)(
Seq( Seq(
dependencyResolution := Defaults.dependencyResolutionTask.value, dependencyResolution := Defaults.dependencyResolutionTask.value,
csrConfiguration := { csrConfiguration := {
val rs = pushRemoteCacheTo.value.toVector val rs = pushRemoteCacheTo.value.toVector ++ remoteCacheResolvers.value.toVector
LMCoursier.scalaCompilerBridgeConfigurationTask.value LMCoursier.scalaCompilerBridgeConfigurationTask.value
.withResolvers(rs) .withResolvers(rs)
} }
) )
) ++ inConfig(Compile)(packageCacheSettings(compileArtifact(Compile, cachedCompileClassifier))) ) ++ inConfig(Compile)(configCacheSettings(compileArtifact(Compile, cachedCompileClassifier)))
++ inConfig(Test)(packageCacheSettings(testArtifact(Test, cachedTestClassifier)))) ++ inConfig(Test)(configCacheSettings(testArtifact(Test, cachedTestClassifier))))
def packageCacheSettings[A <: RemoteCacheArtifact]( def configCacheSettings[A <: RemoteCacheArtifact](
cacheArtifact: Def.Initialize[Task[A]] cacheArtifactTask: Def.Initialize[Task[A]]
): Seq[Def.Setting[_]] = ): Seq[Def.Setting[_]] =
inTask(packageCache)( inTask(packageCache)(
Seq( Seq(
remoteCacheId := {
val inputs = (unmanagedSources / inputFileStamps).value
val cp = (externalDependencyClasspath / outputFileStamps).value
val extraInc = (extraIncOptions.value) flatMap {
case (k, v) =>
Vector(k, v)
}
combineHash(extractHash(inputs) ++ extractHash(cp) ++ extraInc)
},
packageCache.in(Defaults.TaskZero) := { packageCache.in(Defaults.TaskZero) := {
val original = packageBin.in(Defaults.TaskZero).value val original = packageBin.in(Defaults.TaskZero).value
val artp = artifactPath.value val artp = artifactPath.value
@ -229,10 +164,128 @@ object RemoteCache {
// } // }
artp artp
}, },
remoteCacheArtifact := cacheArtifact.value, pushRemoteCacheArtifact := true,
remoteCacheArtifact := cacheArtifactTask.value,
packagedArtifact := (artifact.value -> packageCache.value), packagedArtifact := (artifact.value -> packageCache.value),
artifactPath := Defaults.artifactPathSetting(artifact).value artifactPath := Defaults.artifactPathSetting(artifact).value
) )
) ++ inTask(pushRemoteCache)(
Seq(
moduleSettings := {
val smi = scalaModuleInfo.value
ModuleDescriptorConfiguration(remoteCacheProjectId.value, projectInfo.value)
.withScalaModuleInfo(smi)
},
pushRemoteCache.in(Defaults.TaskZero) := (Def.task {
val s = streams.value
val config = pushRemoteCacheConfiguration.value
val is = (pushRemoteCache / ivySbt).value
val m = new is.Module(moduleSettings.value)
IvyActions.publish(m, config, s.log)
} tag (Tags.Publish, Tags.Network)).value,
)
) ++ Seq(
remoteCacheIdCandidates := List(remoteCacheId.value),
remoteCacheProjectId := {
val o = organization.value
val m = moduleName.value
val id = remoteCacheId.value
val c = (projectID / crossVersion).value
val v = toVersion(id)
ModuleID(o, m, v).cross(c)
},
remoteCacheId := {
val inputs = (unmanagedSources / inputFileStamps).value
val cp = (externalDependencyClasspath / outputFileStamps).?.value.getOrElse(Nil)
val extraInc = (extraIncOptions.value) flatMap {
case (k, v) =>
Vector(k, v)
}
combineHash(extractHash(inputs) ++ extractHash(cp) ++ extraInc)
},
pushRemoteCacheConfiguration := {
Classpaths.publishConfig(
(pushRemoteCacheConfiguration / publishMavenStyle).value,
Classpaths.deliverPattern(crossTarget.value),
if (isSnapshot.value) "integration" else "release",
ivyConfigurations.value.map(c => ConfigRef(c.name)).toVector,
(pushRemoteCacheConfiguration / packagedArtifacts).value.toVector,
(pushRemoteCacheConfiguration / checksums).value.toVector,
Classpaths.getPublishTo(pushRemoteCacheTo.value).name,
ivyLoggingLevel.value,
isSnapshot.value
)
},
pushRemoteCacheConfiguration / packagedArtifacts := Def.taskDyn {
val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
artifacts
.map(a => a.packaged.map(file => (a.artifact, file)))
.join
.apply(_.join.map(_.toMap))
}.value,
pushRemoteCacheConfiguration / remoteCacheArtifacts := {
List((packageCache / remoteCacheArtifact).value)
},
pullRemoteCache := {
import scala.collection.JavaConverters._
val log = streams.value.log
val r = remoteCacheResolvers.value.head
val p = remoteCacheProjectId.value
val ids = remoteCacheIdCandidates.value
val is = (pushRemoteCache / ivySbt).value
val m = new is.Module((pushRemoteCache / moduleSettings).value)
val smi = scalaModuleInfo.value
val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value
val nonPom = artifacts.filterNot(isPomArtifact).toVector
m.withModule(log) {
case (ivy, md, _) =>
val resolver = ivy.getSettings.getResolver(r.name)
if (resolver eq null) sys.error(s"undefined resolver '${r.name}'")
val cross = CrossVersion(p, smi)
val crossf: String => String = cross.getOrElse(identity _)
var found = false
ids foreach {
id: String =>
val v = toVersion(id)
val modId = p.withRevision(v).withName(crossf(p.name))
val ivyId = IvySbt.toID(modId)
if (found) ()
else {
val rawa = nonPom map { _.artifact }
val seqa = CrossVersion.substituteCross(rawa, cross)
val as = seqa map { a =>
val extra = a.classifier match {
case Some(c) => Map("e:classifier" -> c)
case None => Map.empty
}
new DefaultArtifact(ivyId, null, a.name, a.`type`, a.extension, extra.asJava)
}
pullFromMavenRepo0(as, resolver, log) match {
case Right(xs0) =>
val jars = xs0.distinct
nonPom.foreach { art =>
val classifier = art.artifact.classifier
findJar(classifier, v, jars) match {
case Some(jar) =>
extractJar(art, jar)
log.info(s"remote cache artifact extracted for $p $classifier")
case None =>
log.info(s"remote cache artifact not found for $p $classifier")
}
}
found = true
case Left(e) =>
log.info(s"remote cache not found for ${v}")
log.debug(e.getMessage)
}
}
}
()
}
},
) )
def isPomArtifact(artifact: RemoteCacheArtifact): Boolean = def isPomArtifact(artifact: RemoteCacheArtifact): Boolean =
@ -268,26 +321,35 @@ object RemoteCache {
private def toVersion(v: String): String = s"0.0.0-$v" private def toVersion(v: String): String = s"0.0.0-$v"
private lazy val doption = new DownloadOptions
private def pullFromMavenRepo0( private def pullFromMavenRepo0(
modId: ModuleID, artifacts: Vector[IArtifact],
classifiers: Vector[String], r: DependencyResolver,
smi: Option[ScalaModuleInfo],
is: IvySbt,
dr: DependencyResolution,
cacheDir: File,
log: Logger log: Logger
): Either[UnresolvedWarning, Vector[File]] = { ): Either[Throwable, Vector[File]] = {
def dummyModule(deps: Vector[ModuleID]): ModuleDescriptorConfiguration = { try {
val module = ModuleID("com.example.temp", "fake", "0.1.0-SNAPSHOT") val files = r.download(artifacts.toArray, doption).getArtifactsReports.toVector map {
val info = ModuleInfo("fake", "", None, None, Vector(), "", None, None, Vector()) report =>
ModuleDescriptorConfiguration(module, info) if (report == null) sys.error(s"failed to download $artifacts: " + r.toString)
.withScalaModuleInfo(smi) else
.withDependencies(deps) report.getDownloadStatus match {
case DownloadStatus.NO =>
val o = report.getArtifactOrigin
if (o.isLocal) {
val localFile = new File(o.getLocation)
if (!localFile.exists) sys.error(s"$localFile doesn't exist")
else localFile
} else report.getLocalFile
case DownloadStatus.SUCCESSFUL =>
report.getLocalFile
case DownloadStatus.FAILED =>
sys.error(s"failed to download $artifacts: " + r.toString)
}
}
Right(files)
} catch {
case e: Throwable => Left(e)
} }
val deps = classifiers.map(modId.classifier)
val mconfig = dummyModule(deps)
val m = new is.Module(mconfig)
dr.retrieve(m, cacheDir, log)
} }
private def findJar(classifier: Option[String], ver: String, jars: Vector[File]): Option[File] = { private def findJar(classifier: Option[String], ver: String, jars: Vector[File]): Option[File] = {
@ -345,7 +407,7 @@ object RemoteCache {
} }
private def defaultArtifactTasks: Seq[TaskKey[File]] = private def defaultArtifactTasks: Seq[TaskKey[File]] =
Seq(remoteCachePom, Compile / packageCache, Test / packageCache) Seq(Compile / packageCache, Test / packageCache)
private def enabledOnly[A]( private def enabledOnly[A](
key: SettingKey[A], key: SettingKey[A],

View File

@ -10,8 +10,9 @@ pushRemoteCacheTo := Some(
MavenCache("local-cache", (ThisBuild / baseDirectory).value / "remote-cache-semanticdb") MavenCache("local-cache", (ThisBuild / baseDirectory).value / "remote-cache-semanticdb")
) )
remoteCacheId := "fixed-id" Compile / remoteCacheId := "fixed-id"
Compile / remoteCacheIdCandidates := Seq((Compile / remoteCacheId).value)
remoteCacheIdCandidates := Seq(remoteCacheId.value) Test / remoteCacheId := "fixed-id"
Test / remoteCacheIdCandidates := Seq((Test / remoteCacheId).value)
pushRemoteCacheConfiguration := pushRemoteCacheConfiguration.value.withOverwrite(true) Compile / pushRemoteCacheConfiguration := (Compile / pushRemoteCacheConfiguration).value.withOverwrite(true)
Test / pushRemoteCacheConfiguration := (Test / pushRemoteCacheConfiguration).value.withOverwrite(true)

View File

@ -10,11 +10,6 @@ $ exists target/scala-2.12/test-classes/MyTest$.class
$ exists target/scala-2.12/test-classes/META-INF/semanticdb/src/test/scala/MyTest.scala.semanticdb $ exists target/scala-2.12/test-classes/META-INF/semanticdb/src/test/scala/MyTest.scala.semanticdb
$ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip $ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip
# Pom file
$ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id.pom
$ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id.pom.md5
$ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id.pom.sha1
# Compile # Compile
$ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar $ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar
$ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar.md5 $ exists remote-cache-semanticdb/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar.md5

View File

@ -10,27 +10,27 @@ val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterati
ThisBuild / scalaVersion := "2.12.12" ThisBuild / scalaVersion := "2.12.12"
ThisBuild / pushRemoteCacheTo := Some( ThisBuild / pushRemoteCacheTo := Some(
MavenCache("local-cache", (ThisBuild / baseDirectory).value / "remote-cache") MavenCache("local-cache", (ThisBuild / baseDirectory).value / "r")
) )
lazy val root = (project in file(".")) lazy val root = (project in file("."))
.configs(CustomArtifact) .configs(CustomArtifact)
.settings( .settings(
name := "my-project", name := "my-project",
pushRemoteCacheConfiguration := pushRemoteCacheConfiguration.value.withOverwrite(true),
pushRemoteCacheConfiguration / remoteCacheArtifacts += { customArtifactSettings,
val art = (CustomArtifact / artifact).value pushRemoteCacheConfiguration / remoteCacheArtifacts += (CustomArtifact / packageCache / remoteCacheArtifact).value,
val packaged = CustomArtifact / packageCache
val extractDirectory = (CustomArtifact / sourceManaged).value Compile / pushRemoteCacheConfiguration := (Compile / pushRemoteCacheConfiguration).value.withOverwrite(true),
CustomRemoteCacheArtifact(art, packaged, extractDirectory, preserveLastModified = false) Test / pushRemoteCacheConfiguration := (Test / pushRemoteCacheConfiguration).value.withOverwrite(true),
},
Compile / sourceGenerators += Def.task { Compile / sourceGenerators += Def.task {
val extractDirectory = (CustomArtifact / sourceManaged).value val extractDirectory = (CustomArtifact / sourceManaged).value
val output = extractDirectory / "HelloWorld.scala" val output = extractDirectory / "HelloWorld.scala"
IO.write(output, "class HelloWorld") IO.write(output, "class HelloWorld")
Seq(output) Seq(output)
}.taskValue, }.taskValue,
customArtifactSettings,
// test tasks // test tasks
recordPreviousIterations := { recordPreviousIterations := {
val log = streams.value.log val log = streams.value.log
@ -54,7 +54,14 @@ lazy val root = (project in file("."))
def customArtifactSettings: Seq[Def.Setting[_]] = { def customArtifactSettings: Seq[Def.Setting[_]] = {
val classifier = "custom-artifact" val classifier = "custom-artifact"
def cachedArtifactTask = Def.task {
val art = (CustomArtifact / artifact).value
val packaged = CustomArtifact / packageCache
val extractDirectory = (CustomArtifact / sourceManaged).value
CustomRemoteCacheArtifact(art, packaged, extractDirectory, preserveLastModified = false)
}
inConfig(CustomArtifact)( inConfig(CustomArtifact)(
sbt.internal.RemoteCache.configCacheSettings(cachedArtifactTask) ++
Seq( Seq(
packageOptions := { packageOptions := {
val n = name.value + "-" + classifier val n = name.value + "-" + classifier

View File

@ -13,19 +13,19 @@ $ exists target/scala-2.12/test-classes/MyTest$.class
$ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip $ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip
# Compile # Compile
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-cached-compile.jar $ exists r/my-project/my-project_2.12/0.0.0-789740d77fd44aa9/my-project_2.12-0.0.0-789740d77fd44aa9-cached-compile.jar
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-cached-compile.jar.md5 $ exists r/my-project/my-project_2.12/0.0.0-789740d77fd44aa9/my-project_2.12-0.0.0-789740d77fd44aa9-cached-compile.jar.md5
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-cached-compile.jar.sha1 $ exists r/my-project/my-project_2.12/0.0.0-789740d77fd44aa9/my-project_2.12-0.0.0-789740d77fd44aa9-cached-compile.jar.sha1
# Test # Test
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-cached-test.jar $ exists r/my-project/my-project_2.12/0.0.0-9cd077da3ad28ae5/my-project_2.12-0.0.0-9cd077da3ad28ae5-cached-test.jar
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-cached-test.jar.md5 $ exists r/my-project/my-project_2.12/0.0.0-9cd077da3ad28ae5/my-project_2.12-0.0.0-9cd077da3ad28ae5-cached-test.jar.md5
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-cached-test.jar.sha1 $ exists r/my-project/my-project_2.12/0.0.0-9cd077da3ad28ae5/my-project_2.12-0.0.0-9cd077da3ad28ae5-cached-test.jar.sha1
# Custom artifact # Custom artifact
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-custom-artifact.jar $ exists r/my-project/my-project_2.12/0.0.0-1497188b634e2cd0/my-project_2.12-0.0.0-1497188b634e2cd0-custom-artifact.jar
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-custom-artifact.jar.md5 $ exists r/my-project/my-project_2.12/0.0.0-1497188b634e2cd0/my-project_2.12-0.0.0-1497188b634e2cd0-custom-artifact.jar.md5
$ exists remote-cache/my-project/my-project_2.12/0.0.0-b63e5c6efa2d0fd2/my-project_2.12-0.0.0-b63e5c6efa2d0fd2-custom-artifact.jar.sha1 $ exists r/my-project/my-project_2.12/0.0.0-1497188b634e2cd0/my-project_2.12-0.0.0-1497188b634e2cd0-custom-artifact.jar.sha1
> clean > clean