From 0c07fa1851c59d1ade64cae5bfce1b71a22d4694 Mon Sep 17 00:00:00 2001 From: Maksim Ochenashko Date: Sat, 20 Jun 2020 14:05:41 +0300 Subject: [PATCH 1/3] Allow customization of remote cache artifacts --- main/src/main/scala/sbt/Keys.scala | 2 + .../main/scala/sbt/internal/RemoteCache.scala | 211 +++++++++++++----- 2 files changed, 162 insertions(+), 51 deletions(-) diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 4bb5b154e..4faf06755 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -345,6 +345,8 @@ object Keys { val remoteCacheId = taskKey[String]("Unique identifier for the remote cache.") val remoteCacheProjectId = taskKey[ModuleID]("ModuleID used for remote cache JARs.") val remoteCacheIdCandidates = taskKey[Seq[String]]("Remote cache ids to pull.") + val remoteCacheArtifacts = taskKey[Seq[RemoteCacheArtifact]]("Remote cache artifact definitions.") + val remoteCacheArtifact = taskKey[RemoteCacheArtifact]("The remote cache artifact definition.") val pullRemoteCache = taskKey[Unit]("Retrieve remote cache.") val pushRemoteCache = taskKey[Unit]("Push remote cache to the cache server.") val pushRemoteCacheArtifact = settingKey[Boolean]("Enables publishing an artifact to remote cache.") diff --git a/main/src/main/scala/sbt/internal/RemoteCache.scala b/main/src/main/scala/sbt/internal/RemoteCache.scala index 28beca05e..011c00396 100644 --- a/main/src/main/scala/sbt/internal/RemoteCache.scala +++ b/main/src/main/scala/sbt/internal/RemoteCache.scala @@ -25,11 +25,12 @@ import sbt.util.Logger object RemoteCache { final val cachedCompileClassifier = "cached-compile" - final val cachedTestClasifier = "cached-test" + final val cachedTestClassifier = "cached-test" final val commitLength = 10 def gitCommitId: String = scala.sys.process.Process("git rev-parse HEAD").!!.trim.take(commitLength) + def gitCommitIds(n: Int): List[String] = scala.sys.process .Process("git log -n " + n.toString + " --format=%H") @@ -41,7 +42,7 @@ object RemoteCache { lazy val globalSettings: Seq[Def.Setting[_]] = Seq( remoteCacheId := gitCommitId, remoteCacheIdCandidates := gitCommitIds(5), - pushRemoteCacheTo :== None, + pushRemoteCacheTo :== None ) lazy val projectSettings: Seq[Def.Setting[_]] = (Seq( @@ -54,12 +55,21 @@ object RemoteCache { ModuleID(o, m, v).cross(c) }, pushRemoteCacheConfiguration / publishMavenStyle := true, - pushRemoteCacheConfiguration / artifacts := artifactDefs(defaultArtifactTasks).value, - pushRemoteCacheConfiguration / packagedArtifacts := packaged(defaultArtifactTasks).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 := { + enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value + }, Compile / packageCache / pushRemoteCacheArtifact := true, Test / packageCache / pushRemoteCacheArtifact := true, Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier), - Test / packageCache / artifact := Artifact(moduleName.value, cachedTestClasifier), + Test / packageCache / artifact := Artifact(moduleName.value, cachedTestClassifier), remoteCachePom / pushRemoteCacheArtifact := true, pushRemoteCacheConfiguration := { Classpaths.publishConfig( @@ -75,19 +85,17 @@ object RemoteCache { ) }, pullRemoteCache := { - val s = streams.value + 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 compileAf = (Compile / compileAnalysisFile).value - val compileOutput = (Compile / classDirectory).value - val testAf = (Test / compileAnalysisFile).value - val testOutput = (Test / classDirectory).value - val testStreams = (Test / test / streams).value - val testResult = Defaults.succeededFile(testStreams.cacheDirectory) + val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value + val applicable = artifacts.filterNot(RemoteCacheArtifact.isPomArtifact) + val classifiers = applicable.flatMap(_.artifact.classifier).toVector + var found = false ids foreach { id: String => @@ -95,19 +103,25 @@ object RemoteCache { val modId = p.withRevision(v) if (found) () else - pullFromMavenRepo0(modId, smi, is, dr, t, s.log) match { + pullFromMavenRepo0(modId, classifiers, smi, is, dr, t, log) match { case Right(xs0) => - val xs = xs0.distinct - xs.find(_.toString.endsWith(s"$v-$cachedCompileClassifier.jar")) foreach { - jar: File => - extractCache(jar, compileOutput, compileAf, None) - } - xs.find(_.toString.endsWith(s"$v-$cachedTestClasifier.jar")) foreach { jar: File => - extractCache(jar, testOutput, testAf, Some(testResult)) + 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 $classifier") + + case None => + log.info(s"remote cache artifact not found for $classifier") + } } found = true case Left(unresolvedWarning) => - s.log.info(s"remote cache not found for ${v}") + log.info(s"remote cache not found for ${v}") } } }, @@ -118,7 +132,9 @@ object RemoteCache { publisher.makePomFile((pushRemoteCache / ivyModule).value, config, s.log) config.file.get }, - remoteCachePom / packagedArtifact := ((makePom / artifact).value -> remoteCachePom.value), + remoteCachePom / remoteCacheArtifact := { + RemoteCacheArtifact.Pom((makePom / artifact).value, remoteCachePom) + } ) ++ inTask(pushRemoteCache)( Seq( ivyConfiguration := { @@ -146,7 +162,7 @@ object RemoteCache { val s = streams.value val config = pushRemoteCacheConfiguration.value IvyActions.publish(ivyModule.value, config, s.log) - } tag (Tags.Publish, Tags.Network)).value, + } tag (Tags.Publish, Tags.Network)).value ) ) ++ inTask(pullRemoteCache)( Seq( @@ -157,10 +173,12 @@ object RemoteCache { .withResolvers(rs) } ) - ) ++ inConfig(Compile)(packageCacheSettings) - ++ inConfig(Test)(packageCacheSettings)) + ) ++ inConfig(Compile)(packageCacheSettings(compileArtifact(Compile, cachedCompileClassifier))) + ++ inConfig(Test)(packageCacheSettings(testArtifact(Test, cachedTestClassifier)))) - def packageCacheSettings: Seq[Def.Setting[_]] = + private def packageCacheSettings[A <: RemoteCacheArtifact]( + cacheArtifact: Def.Initialize[Task[A]] + ): Seq[Def.Setting[_]] = inTask(packageCache)( Seq( packageCache.in(Defaults.TaskZero) := { @@ -180,15 +198,42 @@ object RemoteCache { // } artp }, + remoteCacheArtifact := cacheArtifact.value, packagedArtifact := (artifact.value -> packageCache.value), - artifactPath := Defaults.artifactPathSetting(artifact).value, + artifactPath := Defaults.artifactPathSetting(artifact).value ) ) + def compileArtifact( + configuration: Configuration, + classifier: String + ): Def.Initialize[Task[RemoteCacheArtifact.Compile]] = Def.task { + RemoteCacheArtifact.Compile( + Artifact(moduleName.value, classifier), + configuration / packageCache, + (configuration / classDirectory).value, + (configuration / compileAnalysisFile).value + ) + } + + def testArtifact( + configuration: Configuration, + classifier: String + ): Def.Initialize[Task[RemoteCacheArtifact.Test]] = Def.task { + RemoteCacheArtifact.Test( + Artifact(moduleName.value, classifier), + configuration / packageCache, + (configuration / classDirectory).value, + (configuration / compileAnalysisFile).value, + Defaults.succeededFile((configuration / test / streams).value.cacheDirectory) + ) + } + private def toVersion(v: String): String = s"0.0.0-$v" private def pullFromMavenRepo0( modId: ModuleID, + classifiers: Vector[String], smi: Option[ScalaModuleInfo], is: IvySbt, dr: DependencyResolution, @@ -202,46 +247,68 @@ object RemoteCache { .withScalaModuleInfo(smi) .withDependencies(deps) } - val deps = - Vector(modId.classifier(cachedCompileClassifier), modId.classifier(cachedTestClasifier)) + val deps = classifiers.map(modId.classifier) val mconfig = dummyModule(deps) val m = new is.Module(mconfig) dr.retrieve(m, cacheDir, log) } - private def extractCache( - jar: File, - output: File, - analysisFile: File, - testResult: Option[File] + private def findJar(classifier: Option[String], ver: String, jars: Vector[File]): Option[File] = { + val suffix = classifier.fold(ver)(c => s"$ver-$c.jar") + jars.find(_.toString.endsWith(suffix)) + } + + private def extractJar(cacheArtifact: RemoteCacheArtifact, jar: File): Unit = + cacheArtifact match { + case RemoteCacheArtifact.Compile(_, _, extractDirectory, analysisFile) => + extractCache(jar, extractDirectory, preserveLastModified = true) { output => + extractAnalysis(output, analysisFile) + } + + case RemoteCacheArtifact.Test(_, _, extractDirectory, analysisFile, testResult) => + extractCache(jar, extractDirectory, preserveLastModified = true) { output => + extractAnalysis(output, analysisFile) + extractTestResult(output, testResult) + } + + case RemoteCacheArtifact.Custom(_, _, extractDirectory, preserveLastModified) => + extractCache(jar, extractDirectory, preserveLastModified)(_ => ()) + + case RemoteCacheArtifact.Pom(_, _) => + () + } + + private def extractCache(jar: File, output: File, preserveLastModified: Boolean)( + processOutput: File => Unit ): Unit = { IO.delete(output) - IO.unzip(jar, output) + IO.unzip(jar, output, preserveLastModified = preserveLastModified) + processOutput(output) + IO.delete(output / "META-INF") + } + + private def extractAnalysis(output: File, analysisFile: File): Unit = { val metaDir = output / "META-INF" val expandedAnalysis = metaDir / "inc_compile.zip" if (expandedAnalysis.exists) { IO.move(expandedAnalysis, analysisFile) } IO.delete(metaDir) - // testResult match { - // case Some(r) => - // val expandedTestResult = output / "META-INF" / "succeeded_tests" - // if (expandedTestResult.exists) { - // IO.move(expandedTestResult, r) - // } - // case _ => () - // } - () + } + + private def extractTestResult(output: File, testResult: File): Unit = { + //val expandedTestResult = output / "META-INF" / "succeeded_tests" + //if (expandedTestResult.exists) { + // IO.move(expandedTestResult, testResult) + //} } private def defaultArtifactTasks: Seq[TaskKey[File]] = - Seq(remoteCachePom, Compile / packageCache, Test / packageCache) - - private def packaged(pkgTasks: Seq[TaskKey[File]]): Def.Initialize[Task[Map[Artifact, File]]] = - enabledOnly(packagedArtifact.toSettingKey, pkgTasks) apply (_.join.map(_.toMap)) - - private def artifactDefs(pkgTasks: Seq[TaskKey[File]]): Def.Initialize[Seq[Artifact]] = - enabledOnly(artifact, pkgTasks) + Seq( + remoteCachePom, + Compile / packageCache, + Test / packageCache + ) private def enabledOnly[A]( key: SettingKey[A], @@ -252,3 +319,45 @@ object RemoteCache { case (a, true) => a }) } + +sealed trait RemoteCacheArtifact { + def artifact: Artifact + def packaged: TaskKey[File] +} + +object RemoteCacheArtifact { + + final case class Pom( + artifact: Artifact, + packaged: TaskKey[File] + ) extends RemoteCacheArtifact + + final case class Compile( + artifact: Artifact, + packaged: TaskKey[File], + extractDirectory: File, + analysisFile: File + ) extends RemoteCacheArtifact + + final case class Test( + artifact: Artifact, + packaged: TaskKey[File], + extractDirectory: File, + analysisFile: File, + testResult: File + ) extends RemoteCacheArtifact + + final case class Custom( + artifact: Artifact, + packaged: TaskKey[File], + extractDirectory: File, + preserveLastModified: Boolean + ) extends RemoteCacheArtifact + + def isPomArtifact(artifact: RemoteCacheArtifact): Boolean = + artifact match { + case _: RemoteCacheArtifact.Pom => true + case _ => false + } + +} From 71ea117a3912c1a196b1c2201c804a143fc266f6 Mon Sep 17 00:00:00 2001 From: Maksim Ochenashko Date: Sun, 21 Jun 2020 09:41:56 +0300 Subject: [PATCH 2/3] Use contraband for generation of RemoteCacheArtifact --- .../CompileRemoteCacheArtifact.scala | 44 ++++++++++ .../CustomRemoteCacheArtifact.scala | 44 ++++++++++ .../remotecache/PomRemoteCacheArtifact.scala | 36 ++++++++ .../remotecache/RemoteCacheArtifact.scala | 27 ++++++ .../remotecache/TestRemoteCacheArtifact.scala | 48 ++++++++++ main/src/main/contraband/remotecache.json | 83 ++++++++++++++++++ main/src/main/scala/sbt/Keys.scala | 1 + .../main/scala/sbt/internal/RemoteCache.scala | 87 +++++-------------- 8 files changed, 307 insertions(+), 63 deletions(-) create mode 100644 main/src/main/contraband-scala/sbt/internal/remotecache/CompileRemoteCacheArtifact.scala create mode 100644 main/src/main/contraband-scala/sbt/internal/remotecache/CustomRemoteCacheArtifact.scala create mode 100644 main/src/main/contraband-scala/sbt/internal/remotecache/PomRemoteCacheArtifact.scala create mode 100644 main/src/main/contraband-scala/sbt/internal/remotecache/RemoteCacheArtifact.scala create mode 100644 main/src/main/contraband-scala/sbt/internal/remotecache/TestRemoteCacheArtifact.scala create mode 100644 main/src/main/contraband/remotecache.json diff --git a/main/src/main/contraband-scala/sbt/internal/remotecache/CompileRemoteCacheArtifact.scala b/main/src/main/contraband-scala/sbt/internal/remotecache/CompileRemoteCacheArtifact.scala new file mode 100644 index 000000000..1cb1bd77f --- /dev/null +++ b/main/src/main/contraband-scala/sbt/internal/remotecache/CompileRemoteCacheArtifact.scala @@ -0,0 +1,44 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.remotecache +final class CompileRemoteCacheArtifact private ( + artifact: sbt.librarymanagement.Artifact, + packaged: sbt.TaskKey[java.io.File], + val extractDirectory: java.io.File, + val analysisFile: java.io.File) extends sbt.internal.remotecache.RemoteCacheArtifact(artifact, packaged) with Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: CompileRemoteCacheArtifact => (this.artifact == x.artifact) && (this.packaged == x.packaged) && (this.extractDirectory == x.extractDirectory) && (this.analysisFile == x.analysisFile) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.remotecache.CompileRemoteCacheArtifact".##) + artifact.##) + packaged.##) + extractDirectory.##) + analysisFile.##) + } + override def toString: String = { + "CompileRemoteCacheArtifact(" + artifact + ", " + packaged + ", " + extractDirectory + ", " + analysisFile + ")" + } + private[this] def copy(artifact: sbt.librarymanagement.Artifact = artifact, packaged: sbt.TaskKey[java.io.File] = packaged, extractDirectory: java.io.File = extractDirectory, analysisFile: java.io.File = analysisFile): CompileRemoteCacheArtifact = { + new CompileRemoteCacheArtifact(artifact, packaged, extractDirectory, analysisFile) + } + def withArtifact(artifact: sbt.librarymanagement.Artifact): CompileRemoteCacheArtifact = { + copy(artifact = artifact) + } + def withPackaged(packaged: sbt.TaskKey[java.io.File]): CompileRemoteCacheArtifact = { + copy(packaged = packaged) + } + def withExtractDirectory(extractDirectory: java.io.File): CompileRemoteCacheArtifact = { + copy(extractDirectory = extractDirectory) + } + def withAnalysisFile(analysisFile: java.io.File): CompileRemoteCacheArtifact = { + copy(analysisFile = analysisFile) + } +} +object CompileRemoteCacheArtifact { + + def apply(artifact: sbt.librarymanagement.Artifact, packaged: sbt.TaskKey[java.io.File], extractDirectory: java.io.File, analysisFile: java.io.File): CompileRemoteCacheArtifact = new CompileRemoteCacheArtifact(artifact, packaged, extractDirectory, analysisFile) +} diff --git a/main/src/main/contraband-scala/sbt/internal/remotecache/CustomRemoteCacheArtifact.scala b/main/src/main/contraband-scala/sbt/internal/remotecache/CustomRemoteCacheArtifact.scala new file mode 100644 index 000000000..0c9e83b51 --- /dev/null +++ b/main/src/main/contraband-scala/sbt/internal/remotecache/CustomRemoteCacheArtifact.scala @@ -0,0 +1,44 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.remotecache +final class CustomRemoteCacheArtifact private ( + artifact: sbt.librarymanagement.Artifact, + packaged: sbt.TaskKey[java.io.File], + val extractDirectory: java.io.File, + val preserveLastModified: Boolean) extends sbt.internal.remotecache.RemoteCacheArtifact(artifact, packaged) with Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: CustomRemoteCacheArtifact => (this.artifact == x.artifact) && (this.packaged == x.packaged) && (this.extractDirectory == x.extractDirectory) && (this.preserveLastModified == x.preserveLastModified) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.remotecache.CustomRemoteCacheArtifact".##) + artifact.##) + packaged.##) + extractDirectory.##) + preserveLastModified.##) + } + override def toString: String = { + "CustomRemoteCacheArtifact(" + artifact + ", " + packaged + ", " + extractDirectory + ", " + preserveLastModified + ")" + } + private[this] def copy(artifact: sbt.librarymanagement.Artifact = artifact, packaged: sbt.TaskKey[java.io.File] = packaged, extractDirectory: java.io.File = extractDirectory, preserveLastModified: Boolean = preserveLastModified): CustomRemoteCacheArtifact = { + new CustomRemoteCacheArtifact(artifact, packaged, extractDirectory, preserveLastModified) + } + def withArtifact(artifact: sbt.librarymanagement.Artifact): CustomRemoteCacheArtifact = { + copy(artifact = artifact) + } + def withPackaged(packaged: sbt.TaskKey[java.io.File]): CustomRemoteCacheArtifact = { + copy(packaged = packaged) + } + def withExtractDirectory(extractDirectory: java.io.File): CustomRemoteCacheArtifact = { + copy(extractDirectory = extractDirectory) + } + def withPreserveLastModified(preserveLastModified: Boolean): CustomRemoteCacheArtifact = { + copy(preserveLastModified = preserveLastModified) + } +} +object CustomRemoteCacheArtifact { + + def apply(artifact: sbt.librarymanagement.Artifact, packaged: sbt.TaskKey[java.io.File], extractDirectory: java.io.File, preserveLastModified: Boolean): CustomRemoteCacheArtifact = new CustomRemoteCacheArtifact(artifact, packaged, extractDirectory, preserveLastModified) +} diff --git a/main/src/main/contraband-scala/sbt/internal/remotecache/PomRemoteCacheArtifact.scala b/main/src/main/contraband-scala/sbt/internal/remotecache/PomRemoteCacheArtifact.scala new file mode 100644 index 000000000..2e956f0ef --- /dev/null +++ b/main/src/main/contraband-scala/sbt/internal/remotecache/PomRemoteCacheArtifact.scala @@ -0,0 +1,36 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.remotecache +final class PomRemoteCacheArtifact private ( + artifact: sbt.librarymanagement.Artifact, + packaged: sbt.TaskKey[java.io.File]) extends sbt.internal.remotecache.RemoteCacheArtifact(artifact, packaged) with Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: PomRemoteCacheArtifact => (this.artifact == x.artifact) && (this.packaged == x.packaged) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (17 + "sbt.internal.remotecache.PomRemoteCacheArtifact".##) + artifact.##) + packaged.##) + } + override def toString: String = { + "PomRemoteCacheArtifact(" + artifact + ", " + packaged + ")" + } + private[this] def copy(artifact: sbt.librarymanagement.Artifact = artifact, packaged: sbt.TaskKey[java.io.File] = packaged): PomRemoteCacheArtifact = { + new PomRemoteCacheArtifact(artifact, packaged) + } + def withArtifact(artifact: sbt.librarymanagement.Artifact): PomRemoteCacheArtifact = { + copy(artifact = artifact) + } + def withPackaged(packaged: sbt.TaskKey[java.io.File]): PomRemoteCacheArtifact = { + copy(packaged = packaged) + } +} +object PomRemoteCacheArtifact { + + def apply(artifact: sbt.librarymanagement.Artifact, packaged: sbt.TaskKey[java.io.File]): PomRemoteCacheArtifact = new PomRemoteCacheArtifact(artifact, packaged) +} diff --git a/main/src/main/contraband-scala/sbt/internal/remotecache/RemoteCacheArtifact.scala b/main/src/main/contraband-scala/sbt/internal/remotecache/RemoteCacheArtifact.scala new file mode 100644 index 000000000..0014ba6ac --- /dev/null +++ b/main/src/main/contraband-scala/sbt/internal/remotecache/RemoteCacheArtifact.scala @@ -0,0 +1,27 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.remotecache +abstract class RemoteCacheArtifact( + val artifact: sbt.librarymanagement.Artifact, + val packaged: sbt.TaskKey[java.io.File]) extends Serializable { + + + + + override def equals(o: Any): Boolean = o match { + case x: RemoteCacheArtifact => (this.artifact == x.artifact) && (this.packaged == x.packaged) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (17 + "sbt.internal.remotecache.RemoteCacheArtifact".##) + artifact.##) + packaged.##) + } + override def toString: String = { + "RemoteCacheArtifact(" + artifact + ", " + packaged + ")" + } +} +object RemoteCacheArtifact { + +} diff --git a/main/src/main/contraband-scala/sbt/internal/remotecache/TestRemoteCacheArtifact.scala b/main/src/main/contraband-scala/sbt/internal/remotecache/TestRemoteCacheArtifact.scala new file mode 100644 index 000000000..d6336ec97 --- /dev/null +++ b/main/src/main/contraband-scala/sbt/internal/remotecache/TestRemoteCacheArtifact.scala @@ -0,0 +1,48 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.remotecache +final class TestRemoteCacheArtifact private ( + artifact: sbt.librarymanagement.Artifact, + packaged: sbt.TaskKey[java.io.File], + val extractDirectory: java.io.File, + val analysisFile: java.io.File, + val testResult: java.io.File) extends sbt.internal.remotecache.RemoteCacheArtifact(artifact, packaged) with Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: TestRemoteCacheArtifact => (this.artifact == x.artifact) && (this.packaged == x.packaged) && (this.extractDirectory == x.extractDirectory) && (this.analysisFile == x.analysisFile) && (this.testResult == x.testResult) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.remotecache.TestRemoteCacheArtifact".##) + artifact.##) + packaged.##) + extractDirectory.##) + analysisFile.##) + testResult.##) + } + override def toString: String = { + "TestRemoteCacheArtifact(" + artifact + ", " + packaged + ", " + extractDirectory + ", " + analysisFile + ", " + testResult + ")" + } + private[this] def copy(artifact: sbt.librarymanagement.Artifact = artifact, packaged: sbt.TaskKey[java.io.File] = packaged, extractDirectory: java.io.File = extractDirectory, analysisFile: java.io.File = analysisFile, testResult: java.io.File = testResult): TestRemoteCacheArtifact = { + new TestRemoteCacheArtifact(artifact, packaged, extractDirectory, analysisFile, testResult) + } + def withArtifact(artifact: sbt.librarymanagement.Artifact): TestRemoteCacheArtifact = { + copy(artifact = artifact) + } + def withPackaged(packaged: sbt.TaskKey[java.io.File]): TestRemoteCacheArtifact = { + copy(packaged = packaged) + } + def withExtractDirectory(extractDirectory: java.io.File): TestRemoteCacheArtifact = { + copy(extractDirectory = extractDirectory) + } + def withAnalysisFile(analysisFile: java.io.File): TestRemoteCacheArtifact = { + copy(analysisFile = analysisFile) + } + def withTestResult(testResult: java.io.File): TestRemoteCacheArtifact = { + copy(testResult = testResult) + } +} +object TestRemoteCacheArtifact { + + def apply(artifact: sbt.librarymanagement.Artifact, packaged: sbt.TaskKey[java.io.File], extractDirectory: java.io.File, analysisFile: java.io.File, testResult: java.io.File): TestRemoteCacheArtifact = new TestRemoteCacheArtifact(artifact, packaged, extractDirectory, analysisFile, testResult) +} diff --git a/main/src/main/contraband/remotecache.json b/main/src/main/contraband/remotecache.json new file mode 100644 index 000000000..486d25f9b --- /dev/null +++ b/main/src/main/contraband/remotecache.json @@ -0,0 +1,83 @@ +{ + "codecNamespace": "sbt.internal.remotecache", + "fullCodec": "RemoteCacheArtifactCodec", + "types": [ + { + "name": "RemoteCacheArtifact", + "namespace": "sbt.internal.remotecache", + "target": "Scala", + "type": "interface", + "fields": [ + { + "name": "artifact", + "type": "sbt.librarymanagement.Artifact" + }, + { + "name": "packaged", + "type": "sbt.TaskKey[java.io.File]" + } + ], + "types": [ + { + "name": "PomRemoteCacheArtifact", + "namespace": "sbt.internal.remotecache", + "target": "Scala", + "type": "record", + "fields": [] + }, + { + "name": "CompileRemoteCacheArtifact", + "namespace": "sbt.internal.remotecache", + "target": "Scala", + "type": "record", + "fields": [ + { + "name": "extractDirectory", + "type": "java.io.File" + }, + { + "name": "analysisFile", + "type": "java.io.File" + } + ] + }, + { + "name": "TestRemoteCacheArtifact", + "namespace": "sbt.internal.remotecache", + "target": "Scala", + "type": "record", + "fields": [ + { + "name": "extractDirectory", + "type": "java.io.File" + }, + { + "name": "analysisFile", + "type": "java.io.File" + }, + { + "name": "testResult", + "type": "java.io.File" + } + ] + }, + { + "name": "CustomRemoteCacheArtifact", + "namespace": "sbt.internal.remotecache", + "target": "Scala", + "type": "record", + "fields": [ + { + "name": "extractDirectory", + "type": "java.io.File" + }, + { + "name": "preserveLastModified", + "type": "Boolean" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 4faf06755..3cd8340e5 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -25,6 +25,7 @@ import sbt.internal.bsp._ import sbt.internal.inc.ScalaInstance import sbt.internal.io.WatchState import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt } +import sbt.internal.remotecache.RemoteCacheArtifact import sbt.internal.server.ServerHandler import sbt.internal.util.{ AttributeKey, ProgressState, SourcePosition } import sbt.io._ diff --git a/main/src/main/scala/sbt/internal/RemoteCache.scala b/main/src/main/scala/sbt/internal/RemoteCache.scala index 011c00396..828421143 100644 --- a/main/src/main/scala/sbt/internal/RemoteCache.scala +++ b/main/src/main/scala/sbt/internal/RemoteCache.scala @@ -20,6 +20,7 @@ import sbt.librarymanagement.syntax._ import sbt.internal.librarymanagement._ import sbt.io.IO import sbt.io.syntax._ +import sbt.internal.remotecache._ import sbt.internal.inc.JarUtils import sbt.util.Logger @@ -93,7 +94,7 @@ object RemoteCache { val p = remoteCacheProjectId.value val ids = remoteCacheIdCandidates.value val artifacts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value - val applicable = artifacts.filterNot(RemoteCacheArtifact.isPomArtifact) + val applicable = artifacts.filterNot(isPomArtifact) val classifiers = applicable.flatMap(_.artifact.classifier).toVector var found = false @@ -133,7 +134,7 @@ object RemoteCache { config.file.get }, remoteCachePom / remoteCacheArtifact := { - RemoteCacheArtifact.Pom((makePom / artifact).value, remoteCachePom) + PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom) } ) ++ inTask(pushRemoteCache)( Seq( @@ -204,11 +205,17 @@ object RemoteCache { ) ) + def isPomArtifact(artifact: RemoteCacheArtifact): Boolean = + artifact match { + case _: PomRemoteCacheArtifact => true + case _ => false + } + def compileArtifact( configuration: Configuration, classifier: String - ): Def.Initialize[Task[RemoteCacheArtifact.Compile]] = Def.task { - RemoteCacheArtifact.Compile( + ): Def.Initialize[Task[CompileRemoteCacheArtifact]] = Def.task { + CompileRemoteCacheArtifact( Artifact(moduleName.value, classifier), configuration / packageCache, (configuration / classDirectory).value, @@ -219,8 +226,8 @@ object RemoteCache { def testArtifact( configuration: Configuration, classifier: String - ): Def.Initialize[Task[RemoteCacheArtifact.Test]] = Def.task { - RemoteCacheArtifact.Test( + ): Def.Initialize[Task[TestRemoteCacheArtifact]] = Def.task { + TestRemoteCacheArtifact( Artifact(moduleName.value, classifier), configuration / packageCache, (configuration / classDirectory).value, @@ -260,21 +267,21 @@ object RemoteCache { private def extractJar(cacheArtifact: RemoteCacheArtifact, jar: File): Unit = cacheArtifact match { - case RemoteCacheArtifact.Compile(_, _, extractDirectory, analysisFile) => - extractCache(jar, extractDirectory, preserveLastModified = true) { output => - extractAnalysis(output, analysisFile) + case a: CompileRemoteCacheArtifact => + extractCache(jar, a.extractDirectory, preserveLastModified = true) { output => + extractAnalysis(output, a.analysisFile) } - case RemoteCacheArtifact.Test(_, _, extractDirectory, analysisFile, testResult) => - extractCache(jar, extractDirectory, preserveLastModified = true) { output => - extractAnalysis(output, analysisFile) - extractTestResult(output, testResult) + case a: TestRemoteCacheArtifact => + extractCache(jar, a.extractDirectory, preserveLastModified = true) { output => + extractAnalysis(output, a.analysisFile) + extractTestResult(output, a.testResult) } - case RemoteCacheArtifact.Custom(_, _, extractDirectory, preserveLastModified) => - extractCache(jar, extractDirectory, preserveLastModified)(_ => ()) + case a: CustomRemoteCacheArtifact => + extractCache(jar, a.extractDirectory, a.preserveLastModified)(_ => ()) - case RemoteCacheArtifact.Pom(_, _) => + case _ => () } @@ -304,11 +311,7 @@ object RemoteCache { } private def defaultArtifactTasks: Seq[TaskKey[File]] = - Seq( - remoteCachePom, - Compile / packageCache, - Test / packageCache - ) + Seq(remoteCachePom, Compile / packageCache, Test / packageCache) private def enabledOnly[A]( key: SettingKey[A], @@ -319,45 +322,3 @@ object RemoteCache { case (a, true) => a }) } - -sealed trait RemoteCacheArtifact { - def artifact: Artifact - def packaged: TaskKey[File] -} - -object RemoteCacheArtifact { - - final case class Pom( - artifact: Artifact, - packaged: TaskKey[File] - ) extends RemoteCacheArtifact - - final case class Compile( - artifact: Artifact, - packaged: TaskKey[File], - extractDirectory: File, - analysisFile: File - ) extends RemoteCacheArtifact - - final case class Test( - artifact: Artifact, - packaged: TaskKey[File], - extractDirectory: File, - analysisFile: File, - testResult: File - ) extends RemoteCacheArtifact - - final case class Custom( - artifact: Artifact, - packaged: TaskKey[File], - extractDirectory: File, - preserveLastModified: Boolean - ) extends RemoteCacheArtifact - - def isPomArtifact(artifact: RemoteCacheArtifact): Boolean = - artifact match { - case _: RemoteCacheArtifact.Pom => true - case _ => false - } - -} From 9047a49dd0d54800b4433a999f53cf4dcfcfab93 Mon Sep 17 00:00:00 2001 From: Maksim Ochenashko Date: Tue, 23 Jun 2020 10:19:05 +0300 Subject: [PATCH 3/3] Add test scenario --- .../sbt-test/actions/remote-cache/build.sbt | 59 +++++++++++++++++++ .../remote-cache/src/main/scala/MyClass.scala | 1 + .../remote-cache/src/test/scala/MyTest.scala | 1 + sbt/src/sbt-test/actions/remote-cache/test | 58 ++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 sbt/src/sbt-test/actions/remote-cache/build.sbt create mode 100644 sbt/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala create mode 100644 sbt/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala create mode 100644 sbt/src/sbt-test/actions/remote-cache/test diff --git a/sbt/src/sbt-test/actions/remote-cache/build.sbt b/sbt/src/sbt-test/actions/remote-cache/build.sbt new file mode 100644 index 000000000..9e58f260f --- /dev/null +++ b/sbt/src/sbt-test/actions/remote-cache/build.sbt @@ -0,0 +1,59 @@ +import sbt.internal.remotecache.CustomRemoteCacheArtifact + +lazy val root = (project in file(".")) + .configs(CustomArtifact) + .settings( + name := "my-project", + scalaVersion := "2.12.11", + 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) + }, + Compile / sourceGenerators += Def.task { + val extractDirectory = (CustomArtifact / sourceManaged).value + val output = extractDirectory / "HelloWorld.scala" + IO.write(output, "class HelloWorld") + Seq(output) + }.taskValue + ) + .settings(customArtifactSettings) + +lazy val CustomArtifact = config("custom-artifact") + +def customArtifactSettings: Seq[Def.Setting[_]] = { + val classifier = "custom-artifact" + + inConfig(CustomArtifact)( + Seq( + packageOptions := { + val n = name.value + "-" + classifier + val ver = version.value + val orgName = organizationName.value + + List(Package.addSpecManifestAttributes(n, ver, orgName)) + }, + sourceManaged := (Compile / target).value / "custom-artifact-gen", + mappings := { + val sourcesDir = sourceManaged.value + val sources = sourcesDir.allPaths.pair(Path.relativeTo(sourcesDir)) + + sources + }, + packageConfiguration := Defaults.packageConfigurationTask.value, + packageCache := Defaults.packageTask.value, + artifact := Artifact(moduleName.value, classifier), + packagedArtifact := (artifact.value -> packageCache.value), + artifactPath := Defaults.artifactPathSetting(artifact).value, + artifactName := Artifact.artifactName + ) + ) +} \ No newline at end of file diff --git a/sbt/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala b/sbt/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala new file mode 100644 index 000000000..7c7f7e635 --- /dev/null +++ b/sbt/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala @@ -0,0 +1 @@ +object MyClass \ No newline at end of file diff --git a/sbt/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala b/sbt/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala new file mode 100644 index 000000000..d27811abd --- /dev/null +++ b/sbt/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala @@ -0,0 +1 @@ +object MyTest \ No newline at end of file diff --git a/sbt/src/sbt-test/actions/remote-cache/test b/sbt/src/sbt-test/actions/remote-cache/test new file mode 100644 index 000000000..e90fade3e --- /dev/null +++ b/sbt/src/sbt-test/actions/remote-cache/test @@ -0,0 +1,58 @@ +> compile +> pushRemoteCache + +# Generated sources, compiled classes +$ exists target/custom-artifact-gen/HelloWorld.scala +$ exists target/scala-2.12/classes/HelloWorld.class +$ exists target/scala-2.12/classes/MyClass.class +$ exists target/scala-2.12/classes/MyClass$.class +$ exists target/scala-2.12/zinc/inc_compile_2.12.zip +$ 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 + +# 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 + +# 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 + +> clean + +$ absent target/custom-artifact-gen/HelloWorld.scala +$ absent target/scala-2.12/classes/HelloWorld.class +$ absent target/scala-2.12/classes/MyClass.class +$ absent target/scala-2.12/classes/MyClass$.class +$ absent target/scala-2.12/zinc/inc_compile_2.12.zip +$ absent target/scala-2.12/test-classes/MyTest.class +$ absent target/scala-2.12/test-classes/MyTest$.class +$ absent target/scala-2.12/test-zinc/inc_compile_2.12.zip + +> pullRemoteCache + +# Files extracted from the cache artifacts +$ exists target/custom-artifact-gen/HelloWorld.scala +$ exists target/scala-2.12/classes/HelloWorld.class +$ exists target/scala-2.12/classes/MyClass.class +$ exists target/scala-2.12/classes/MyClass$.class +$ exists target/scala-2.12/zinc/inc_compile_2.12.zip +$ 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 + +# Artifacts can be pushed twice (enabled overriding) +> pushRemoteCache \ No newline at end of file