Merge pull request #6026 from eed3si9n/wip/content

Make remoteCacheId content-based
This commit is contained in:
eugene yokota 2020-11-01 22:06:37 -05:00 committed by GitHub
commit 8c3f2a50f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 301 additions and 161 deletions

View File

@ -23,7 +23,7 @@ matrix:
include:
- env:
- SBT_LOCAL=true
- SBT_VERSION_PROP=-Dsbt.version=1.4.1-SNAPSHOT
- SBT_VERSION_PROP=-Dsbt.version=1.4.2-SNAPSHOT
- TRAVIS_JDK=adopt@1.8.0-222
- SBT_CMD="++$SCALA_213; $UTIL_TESTS; ++$SCALA_212; $UTIL_TESTS; scripted actions/* source-dependencies/*1of3 dependency-management/*1of4 java/*"

View File

@ -8,14 +8,15 @@ import java.nio.file.{ Files, Path => JPath }
import scala.util.Try
ThisBuild / version := {
val v = "1.4.1-SNAPSHOT"
// update .travis.yml too for dog fooding
val v = "1.4.2-SNAPSHOT"
nightlyVersion.getOrElse(v)
}
ThisBuild / versionScheme := Some("early-semver")
ThisBuild / scalafmtOnCompile := !(Global / insideCI).value
ThisBuild / Test / scalafmtOnCompile := !(Global / insideCI).value
ThisBuild / turbo := true
ThisBuild / usePipelining := !(Global / insideCI).value
ThisBuild / usePipelining := false // !(Global / insideCI).value
val excludeLint = SettingKey[Set[Def.KeyedInitialize[_]]]("excludeLintKeys")
Global / excludeLint := (Global / excludeLint).?.value.getOrElse(Set.empty)

View File

@ -2532,6 +2532,14 @@ object Classpaths {
excludeFilter in unmanagedJars value
)
).map(exportClasspath) ++ Seq(
externalDependencyClasspath / outputFileStamps := {
val stamper = timeWrappedStamper.value
val converter = fileConverter.value
externalDependencyClasspath.value flatMap { file0 =>
val p = file0.data.toPath
FileStamp(stamper.library(converter.toVirtualFile(p))).map(p -> _)
}
},
dependencyClasspathFiles := data(dependencyClasspath.value).map(_.toPath),
dependencyClasspathFiles / outputFileStamps := {
val stamper = timeWrappedStamper.value

View File

@ -386,6 +386,7 @@ object Keys {
val pushRemoteCacheArtifact = settingKey[Boolean]("Enables publishing an artifact to remote cache.")
val pushRemoteCacheConfiguration = taskKey[PublishConfiguration]("")
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 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)

View File

@ -9,19 +9,29 @@ package sbt
package internal
import java.io.File
import java.nio.file.Path
import Keys._
import SlashSyntax0._
import ScopeFilter.Make._
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 sbt.coursierint.LMCoursier
import sbt.librarymanagement._
import sbt.librarymanagement.ivy.Credentials
import sbt.librarymanagement.ivy.{ Credentials, IvyPaths, UpdateOptions }
import sbt.librarymanagement.syntax._
import sbt.nio.FileStamp
import sbt.nio.Keys.{ inputFileStamps, outputFileStamps }
import sbt.internal.librarymanagement._
import sbt.io.IO
import sbt.io.syntax._
import sbt.internal.remotecache._
import sbt.internal.inc.JarUtils
import sbt.internal.inc.{ HashUtil, JarUtils }
import sbt.util.InterfaceUtil.toOption
import sbt.util.Logger
object RemoteCache {
@ -41,91 +51,49 @@ object RemoteCache {
.map(_.take(commitLength))
lazy val globalSettings: Seq[Def.Setting[_]] = Seq(
remoteCacheId := gitCommitId,
remoteCacheIdCandidates := gitCommitIds(5),
remoteCacheId := "",
remoteCacheIdCandidates := Nil,
pushRemoteCacheTo :== None
)
lazy val projectSettings: Seq[Def.Setting[_]] = (Seq(
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,
pushRemoteCache := (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 _ = pushRemoteCache.all(filter).value
()
}
}).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,
pushRemoteCacheConfiguration / remoteCacheArtifacts := {
enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value
},
pushRemoteCacheConfiguration / publishMavenStyle := true,
Compile / packageCache / pushRemoteCacheArtifact := true,
Test / packageCache / pushRemoteCacheArtifact := true,
Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier),
Test / packageCache / artifact := Artifact(moduleName.value, cachedTestClassifier),
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 := {
val s = streams.value
val config = (remoteCachePom / makePomConfiguration).value
@ -142,50 +110,40 @@ object RemoteCache {
},
remoteCachePom / remoteCacheArtifact := {
PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom)
}
},
remoteCacheResolvers := pushRemoteCacheTo.value.toVector,
) ++ inTask(pushRemoteCache)(
Seq(
ivyPaths := IvyPaths(baseDirectory.value, crossTarget.value / "remote-cache"),
ivyConfiguration := {
val other = pushRemoteCacheTo.value.toVector
val config0 = Classpaths.mkIvyConfiguration.value
config0
.withOtherResolvers(other)
.withResolvers(remoteCacheResolvers.value.toVector)
.withOtherResolvers(pushRemoteCacheTo.value.toVector)
.withResolutionCacheDir(crossTarget.value / "alt-resolution")
.withPaths(ivyPaths.value)
.withUpdateOptions(UpdateOptions().withGigahorse(true))
},
ivySbt := {
val config0 = ivyConfiguration.value
Credentials.register(credentials.value, streams.value.log)
val config0 = ivyConfiguration.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)(
Seq(
dependencyResolution := Defaults.dependencyResolutionTask.value,
csrConfiguration := {
val rs = pushRemoteCacheTo.value.toVector
val rs = pushRemoteCacheTo.value.toVector ++ remoteCacheResolvers.value.toVector
LMCoursier.scalaCompilerBridgeConfigurationTask.value
.withResolvers(rs)
}
)
) ++ inConfig(Compile)(packageCacheSettings(compileArtifact(Compile, cachedCompileClassifier)))
++ inConfig(Test)(packageCacheSettings(testArtifact(Test, cachedTestClassifier))))
) ++ inConfig(Compile)(configCacheSettings(compileArtifact(Compile, cachedCompileClassifier)))
++ inConfig(Test)(configCacheSettings(testArtifact(Test, cachedTestClassifier))))
private def packageCacheSettings[A <: RemoteCacheArtifact](
cacheArtifact: Def.Initialize[Task[A]]
def configCacheSettings[A <: RemoteCacheArtifact](
cacheArtifactTask: Def.Initialize[Task[A]]
): Seq[Def.Setting[_]] =
inTask(packageCache)(
Seq(
@ -206,10 +164,128 @@ object RemoteCache {
// }
artp
},
remoteCacheArtifact := cacheArtifact.value,
pushRemoteCacheArtifact := true,
remoteCacheArtifact := cacheArtifactTask.value,
packagedArtifact := (artifact.value -> packageCache.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 =
@ -245,26 +321,35 @@ object RemoteCache {
private def toVersion(v: String): String = s"0.0.0-$v"
private lazy val doption = new DownloadOptions
private def pullFromMavenRepo0(
modId: ModuleID,
classifiers: Vector[String],
smi: Option[ScalaModuleInfo],
is: IvySbt,
dr: DependencyResolution,
cacheDir: File,
artifacts: Vector[IArtifact],
r: DependencyResolver,
log: Logger
): Either[UnresolvedWarning, Vector[File]] = {
def dummyModule(deps: Vector[ModuleID]): ModuleDescriptorConfiguration = {
val module = ModuleID("com.example.temp", "fake", "0.1.0-SNAPSHOT")
val info = ModuleInfo("fake", "", None, None, Vector(), "", None, None, Vector())
ModuleDescriptorConfiguration(module, info)
.withScalaModuleInfo(smi)
.withDependencies(deps)
): Either[Throwable, Vector[File]] = {
try {
val files = r.download(artifacts.toArray, doption).getArtifactsReports.toVector map {
report =>
if (report == null) sys.error(s"failed to download $artifacts: " + r.toString)
else
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] = {
@ -322,7 +407,7 @@ object RemoteCache {
}
private def defaultArtifactTasks: Seq[TaskKey[File]] =
Seq(remoteCachePom, Compile / packageCache, Test / packageCache)
Seq(Compile / packageCache, Test / packageCache)
private def enabledOnly[A](
key: SettingKey[A],
@ -332,4 +417,14 @@ object RemoteCache {
Classpaths.forallIn(pushRemoteCacheArtifact, pkgTasks))(_ zip _ collect {
case (a, true) => a
})
private def extractHash(inputs: Seq[(Path, FileStamp)]): Vector[String] =
inputs.toVector map {
case (_, stamp0) => toOption(stamp0.stamp.getHash).getOrElse("cafe")
}
private def combineHash(vs: Vector[String]): String = {
val hashValue = HashUtil.farmHash(vs.sorted.mkString("").getBytes("UTF-8"))
java.lang.Long.toHexString(hashValue)
}
}

View File

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

View File

@ -1,38 +1,74 @@
import sbt.internal.remotecache.CustomRemoteCacheArtifact
import sbt.internal.inc.Analysis
import complete.DefaultParsers._
lazy val CustomArtifact = config("custom-artifact")
// Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.")
ThisBuild / scalaVersion := "2.12.12"
ThisBuild / pushRemoteCacheTo := Some(
MavenCache("local-cache", (ThisBuild / baseDirectory).value / "r")
)
lazy val root = (project in file("."))
.configs(CustomArtifact)
.settings(
name := "my-project",
scalaVersion := "2.12.12",
pushRemoteCacheTo := Some(
MavenCache("local-cache", (ThisBuild / baseDirectory).value / "remote-cache")
),
remoteCacheId := "fixed-id",
remoteCacheIdCandidates := Seq("fixed-id"),
pushRemoteCacheConfiguration := pushRemoteCacheConfiguration.value.withOverwrite(true),
pushRemoteCacheConfiguration / remoteCacheArtifacts += {
val art = (CustomArtifact / artifact).value
val packaged = CustomArtifact / packageCache
val extractDirectory = (CustomArtifact / sourceManaged).value
CustomRemoteCacheArtifact(art, packaged, extractDirectory, preserveLastModified = false)
},
customArtifactSettings,
pushRemoteCacheConfiguration / remoteCacheArtifacts += (CustomArtifact / packageCache / remoteCacheArtifact).value,
Compile / pushRemoteCacheConfiguration := (Compile / pushRemoteCacheConfiguration).value.withOverwrite(true),
Test / pushRemoteCacheConfiguration := (Test / pushRemoteCacheConfiguration).value.withOverwrite(true),
Compile / sourceGenerators += Def.task {
val extractDirectory = (CustomArtifact / sourceManaged).value
val output = extractDirectory / "HelloWorld.scala"
IO.write(output, "class HelloWorld")
Seq(output)
}.taskValue
)
.settings(customArtifactSettings)
}.taskValue,
// bring back fixed-id because JDK 8/11 would be different intentionally
Compile / remoteCacheId := "fixed-id",
Compile / remoteCacheIdCandidates := Seq((Compile / remoteCacheId).value),
Test / remoteCacheId := "fixed-id",
Test / remoteCacheIdCandidates := Seq((Test / remoteCacheId).value),
CustomArtifact / remoteCacheId := "fixed-id",
CustomArtifact / remoteCacheIdCandidates := Seq((CustomArtifact / remoteCacheId).value),
lazy val CustomArtifact = config("custom-artifact")
// test tasks
recordPreviousIterations := {
val log = streams.value.log
CompileState.previousIterations = {
val previousAnalysis = (previousCompile in Compile).value.analysis.asScala
previousAnalysis match {
case None =>
log.info("No previous analysis detected")
0
case Some(a: Analysis) => a.compilations.allCompilations.size
}
}
},
checkIterations := {
val expected: Int = (Space ~> NatBasic).parsed
val actual: Int = ((compile in Compile).value match { case a: Analysis => a.compilations.allCompilations.size }) - CompileState.previousIterations
assert(expected == actual, s"Expected $expected compilations, got $actual")
}
)
def customArtifactSettings: Seq[Def.Setting[_]] = {
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)(
sbt.internal.RemoteCache.configCacheSettings(cachedArtifactTask) ++
Seq(
packageOptions := {
val n = name.value + "-" + classifier

View File

@ -0,0 +1,4 @@
// This is necessary because tests are run in batch mode
object CompileState {
@volatile var previousIterations: Int = -1
}

View File

@ -1,3 +1,4 @@
> recordPreviousIterations
> compile
> pushRemoteCache
@ -11,25 +12,20 @@ $ exists target/scala-2.12/test-classes/MyTest.class
$ exists target/scala-2.12/test-classes/MyTest$.class
$ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip
# Pom file
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id.pom
$ exists remote-cache/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/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id.pom.sha1
# Compile
$ exists remote-cache/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/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/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar.sha1
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar
$ exists r/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 r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-compile.jar.sha1
# Test
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-test.jar
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-test.jar.md5
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-test.jar.sha1
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-test.jar
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-test.jar.md5
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-cached-test.jar.sha1
# Custom artifact
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-custom-artifact.jar
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-custom-artifact.jar.md5
$ exists remote-cache/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-custom-artifact.jar.sha1
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-custom-artifact.jar
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-custom-artifact.jar.md5
$ exists r/my-project/my-project_2.12/0.0.0-fixed-id/my-project_2.12-0.0.0-fixed-id-custom-artifact.jar.sha1
> clean
@ -54,5 +50,8 @@ $ exists target/scala-2.12/test-classes/MyTest.class
$ exists target/scala-2.12/test-classes/MyTest$.class
$ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip
> debug
> checkIterations 1
# Artifacts can be pushed twice (enabled overriding)
> pushRemoteCache