mirror of https://github.com/sbt/sbt.git
Merge pull request #6026 from eed3si9n/wip/content
Make remoteCacheId content-based
This commit is contained in:
commit
8c3f2a50f7
|
|
@ -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/*"
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
// This is necessary because tests are run in batch mode
|
||||
object CompileState {
|
||||
@volatile var previousIterations: Int = -1
|
||||
}
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue