diff --git a/build.sbt b/build.sbt index 3e5bd5175..1472deeba 100644 --- a/build.sbt +++ b/build.sbt @@ -708,6 +708,33 @@ lazy val mainProj = (project in file("main")) mimaSettings, mimaBinaryIssueFilters ++= Vector( exclude[DirectMissingMethodProblem]("sbt.Keys.scalaCompilerBridgeBinaryJar"), + exclude[DirectMissingMethodProblem]("sbt.Keys.packageCache"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pullRemoteCache"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCache"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCacheArtifact"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCacheConfiguration"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCacheTo"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheArtifact"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheArtifacts"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheId"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheIdCandidates"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCachePom"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheProjectId"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheResolvers"), + exclude[DirectMissingMethodProblem]("sbt.Keys.packageCache"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheId"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheProjectId"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheIdCandidates"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheArtifacts"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheArtifact"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pullRemoteCache"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCache"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCacheArtifact"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCacheConfiguration"), + exclude[DirectMissingMethodProblem]("sbt.Keys.pushRemoteCacheTo"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCacheResolvers"), + exclude[DirectMissingMethodProblem]("sbt.Keys.remoteCachePom"), + exclude[DirectMissingMethodProblem]("sbt.internal.RemoteCache.*"), exclude[DirectMissingMethodProblem]("sbt.internal.Compiler.*"), ), ) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 161b4d507..87ee441c4 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2781,7 +2781,7 @@ object Classpaths { packagedDefaultArtifacts.value } else Map.empty[Artifact, HashedVirtualFileRef] } - ) ++ RemoteCache.projectSettings + ) /** * Produces the Maven-compatible artifacts of an sbt plugin. diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 1992f1b1d..81ae104b8 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -23,7 +23,6 @@ import sbt.internal.bsp.* import sbt.internal.inc.ScalaInstance import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt } import sbt.internal.librarymanagement.ivy.{ IvyConfiguration, UpdateOptions } -import sbt.internal.remotecache.RemoteCacheArtifact import sbt.internal.server.BuildServerProtocol.BspFullWorkspace import sbt.internal.server.{ BspCompileTask, BuildServerReporter, ServerHandler } import sbt.internal.util.{ AttributeKey, ProgressState, SourcePosition } @@ -299,7 +298,6 @@ object Keys { val `package` = taskKey[HashedVirtualFileRef]("Produces the main artifact, such as a binary jar. This is typically an alias for the task that actually does the packaging.").withRank(APlusTask) val packageDoc = taskKey[HashedVirtualFileRef]("Produces a documentation artifact, such as a jar containing API documentation.").withRank(AMinusTask) val packageSrc = taskKey[HashedVirtualFileRef]("Produces a source artifact, such as a jar containing sources and resources.").withRank(AMinusTask) - val packageCache = taskKey[HashedVirtualFileRef]("Produces the main artifact for caching.") val packageOptions = taskKey[Seq[PackageOption]]("Options for packaging.").withRank(BTask) val packageTimestamp = settingKey[Option[Long]]("Overwrites timestamps in JAR file to make the build reproducible; None keeps the existing timestamps (useful for web resources)").withRank(CSetting) @@ -429,19 +427,6 @@ object Keys { val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on") val closeClassLoaders = settingKey[Boolean]("Close classloaders in run and test when the task completes.").withRank(DSetting) val allowZombieClassLoaders = settingKey[Boolean]("Allow a classloader that has previously been closed by `run` or `test` to continue loading classes.") - // val useRemoteCache = settingKey[Boolean]("Use remote cache.") - 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.") - 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[HashedVirtualFileRef]("Generates a pom for publishing when publishing Maven-style.") val localCacheDirectory = settingKey[File]("Operating system specific cache directory.") val localDigestCacheByteSize = SettingKey[Long](BasicKeys.localDigestCacheByteSize).withRank(DSetting) val usePipelining = settingKey[Boolean]("Use subproject pipelining for compilation.").withRank(BSetting) diff --git a/main/src/main/scala/sbt/RemoteCache.scala b/main/src/main/scala/sbt/RemoteCache.scala index 2844a48e7..91f5b616c 100644 --- a/main/src/main/scala/sbt/RemoteCache.scala +++ b/main/src/main/scala/sbt/RemoteCache.scala @@ -12,47 +12,12 @@ package internal import java.io.File import java.nio.file.Path -import org.apache.ivy.core.module.descriptor.{ DefaultArtifact, Artifact as IArtifact } -import org.apache.ivy.core.report.DownloadStatus -import org.apache.ivy.core.resolve.DownloadOptions -import org.apache.ivy.plugins.resolver.DependencyResolver -import sbt.Defaults.prefix import sbt.Keys.* -import sbt.Project.{ inConfig as _, * } -import sbt.ProjectExtra.* -import sbt.ScopeFilter.Make.* -import sbt.ScopeAxis.Select -import sbt.SlashSyntax0.* -import sbt.coursierint.LMCoursier -import sbt.internal.inc.{ HashUtil, JarUtils } -import sbt.internal.librarymanagement.* -import sbt.internal.remotecache.* -import sbt.io.IO -import sbt.io.syntax.* import sbt.librarymanagement.* -import sbt.internal.librarymanagement.ivy.{ IvyCredentials, UpdateOptions } -import sbt.librarymanagement.syntax.* -import sbt.nio.FileStamp -import sbt.nio.Keys.{ inputFileStamps, outputFileStamps } -import sbt.std.TaskExtra.* -import sbt.util.InterfaceUtil.toOption -import sbt.util.{ CacheImplicits, DiskActionCacheStore, Logger } -import sbt.util.CacheImplicits.given +import sbt.util.{ CacheImplicits, DiskActionCacheStore } import sjsonnew.JsonFormat -import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFileRef } -import xsbti.compile.CompileAnalysis - -import scala.collection.mutable - -object RemoteCache { - final val cachedCompileClassifier = "cached-compile" - final val cachedTestClassifier = "cached-test" - final val commitLength = 10 - - // TODO: cap with caffeine - private[sbt] val analysisStore: mutable.Map[HashedVirtualFileRef, CompileAnalysis] = - mutable.Map.empty +object RemoteCache: private[sbt] def artifactToStr(art: Artifact): String = { import LibraryManagementCodec.given import sjsonnew.support.scalajson.unsafe.* @@ -60,31 +25,11 @@ object RemoteCache { CompactPrinter(Converter.toJsonUnsafe(art)(using format)) } - 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") - .!! - .linesIterator - .toList - .map(_.take(commitLength)) - lazy val defaultCacheLocation: File = SysProp.globalLocalCache lazy val globalSettings: Seq[Def.Setting[?]] = Seq( - remoteCacheId := "", - remoteCacheIdCandidates :== Nil, - pushRemoteCacheTo :== None, localCacheDirectory :== defaultCacheLocation, localDigestCacheByteSize :== CacheImplicits.defaultLocalDigestCacheByteSize, - pushRemoteCache / ivyPaths := { - val app = appConfiguration.value - val base = app.baseDirectory.getCanonicalFile - // base is used only to resolve relative paths, which should never happen - IvyPaths(base.toString, localCacheDirectory.value.toString) - }, rootOutputDirectory := { appConfiguration.value.baseDirectory .toPath() @@ -103,408 +48,4 @@ object RemoteCache { remoteCacheTlsClientKey := SysProp.remoteCacheTlsClientKey, remoteCacheHeaders := SysProp.remoteCacheHeaders, ) - - lazy val projectSettings: Seq[Def.Setting[?]] = (Seq( - pushRemoteCache := ((Def - .task { - val arts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value - val configs = arts flatMap { art => - art.packaged.scopedKey.scope match { - case Scope(_, Select(c), _, _) => Some(c) - case _ => None - } - } - ScopeFilter(configurations = inConfigurationsByKeys(configs*)) - }) - .flatMapTask { case filter => - Def.task { - val _ = pushRemoteCache.all(filter).value - () - } - }) - .value, - pullRemoteCache := ((Def - .task { - val arts = (pushRemoteCacheConfiguration / remoteCacheArtifacts).value - val configs = arts flatMap { art => - art.packaged.scopedKey.scope match { - case Scope(_, Select(c), _, _) => Some(c) - case _ => None - } - } - ScopeFilter(configurations = inConfigurationsByKeys(configs*)) - }) - .flatMapTask { case filter => - Def.task { - val _ = pullRemoteCache.all(filter).value - () - } - }) - .value, - pushRemoteCacheConfiguration / remoteCacheArtifacts := Def.uncached { - enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value - }, - pushRemoteCacheConfiguration / publishMavenStyle := true, - Compile / packageCache / pushRemoteCacheArtifact := true, - Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier), - remoteCachePom / pushRemoteCacheArtifact := true, - remoteCachePom := Def.uncached { - val s = streams.value - val converter = fileConverter.value - val config = (remoteCachePom / makePomConfiguration).value - val publisher = Keys.publisher.value - publisher.makePomFile((pushRemoteCache / ivyModule).value, config, s.log) - converter.toVirtualFile(config.file.get.toPath) - }, - remoteCachePom / artifactPath := { - Defaults.prefixArtifactPathSetting(makePom / artifact, "remote-cache").value - }, - remoteCachePom / makePomConfiguration := { - val converter = fileConverter.value - val config = makePomConfiguration.value - val out = converter.toPath((remoteCachePom / artifactPath).value) - config.withFile(out.toFile()) - }, - remoteCachePom / remoteCacheArtifact := Def.uncached { - PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom) - }, - remoteCacheResolvers := pushRemoteCacheTo.value.toVector, - ) ++ inTask(pushRemoteCache)( - Seq( - ivyPaths := (Scope.Global / pushRemoteCache / ivyPaths).value, - ivyConfiguration := Def.uncached { - val config0 = Classpaths.mkIvyConfiguration.value - config0 - .withResolvers(remoteCacheResolvers.value.toVector) - .withOtherResolvers(pushRemoteCacheTo.value.toVector) - .withResolutionCacheDir(crossTarget.value / "alt-resolution") - .withPaths(ivyPaths.value) - .withUpdateOptions(UpdateOptions().withGigahorse(true)) - }, - ivySbt := Def.uncached { - IvyCredentials.register(credentials.value, streams.value.log) - val config0 = ivyConfiguration.value - new IvySbt(config0) - }, - ) - ) ++ inTask(pullRemoteCache)( - Seq( - dependencyResolution := Def.uncached(Defaults.dependencyResolutionTask.value), - csrConfiguration := Def.uncached { - val rs = pushRemoteCacheTo.value.toVector ++ remoteCacheResolvers.value.toVector - LMCoursier.scalaCompilerBridgeConfigurationTask.value - .withResolvers(rs) - } - ) - ) ++ inConfig(Compile)(configCacheSettings(compileArtifact(Compile, cachedCompileClassifier)))) - - def getResourceFilePaths() = Def.task { - val syncDir = crossTarget.value / (prefix(configuration.value.name) + "sync") - val file = syncDir / "copy-resource" - file - } - - def configCacheSettings[A <: RemoteCacheArtifact]( - cacheArtifactTask: Def.Initialize[Task[A]] - ): Seq[Def.Setting[?]] = - inTask(packageCache)( - Seq( - (Defaults.TaskZero / packageCache) := Def.uncached { - val converter = fileConverter.value - val original = (Defaults.TaskZero / packageBin).value - val originalFile = converter.toPath(original) - val artp = artifactPath.value - val artpFile = converter.toPath(artp) - val af = compileAnalysisFile.value - IO.copyFile(originalFile.toFile(), artpFile.toFile()) - // skip zip manipulation if the artp is a blank file - if (af.exists && artpFile.toFile().length() > 0) { - JarUtils.includeInJar(artpFile.toFile(), Vector(af -> s"META-INF/inc_compile.zip")) - } - val rf = getResourceFilePaths().value - if (rf.exists) { - JarUtils.includeInJar(artpFile.toFile(), Vector(rf -> s"META-INF/copy-resources.txt")) - } - // val testStream = (test / streams).?.value - // testStream foreach { s => - // val sf = Defaults.succeededFile(s.cacheDirectory) - // if (sf.exists) { - // JarUtils.includeInJar(artp, Vector(sf -> s"META-INF/succeeded_tests")) - // } - // } - converter.toVirtualFile(artpFile) - }, - pushRemoteCacheArtifact := true, - remoteCacheArtifact := Def.uncached(cacheArtifactTask.value), - packagedArtifact := Def.uncached(artifact.value -> packageCache.value), - artifactPath := Defaults.artifactPathSetting(artifact).value - ) - ) ++ inTask(pushRemoteCache)( - Seq( - moduleSettings := Def.uncached { - val smi = scalaModuleInfo.value - ModuleDescriptorConfiguration(remoteCacheProjectId.value, projectInfo.value) - .withScalaModuleInfo(smi) - }, - (Defaults.TaskZero / pushRemoteCache) := (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 := Def.uncached { - 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 := Def.uncached { - val inputs = (unmanagedSources / inputFileStamps).value - val cp = (externalDependencyClasspath / outputFileStamps).?.value.getOrElse(Nil) - val extraInc = (extraIncOptions.value) flatMap { (k, v) => - Vector(k, v) - } - combineHash(extractHash(inputs) ++ extractHash(cp) ++ extraInc) - }, - pushRemoteCacheConfiguration := Def.uncached { - val converter = fileConverter.value - val artifacts = - (pushRemoteCacheConfiguration / packagedArtifacts).value.toVector.map { (a, vf) => - a -> converter.toPath(vf).toFile - } - Classpaths.publishConfig( - (pushRemoteCacheConfiguration / publishMavenStyle).value, - Classpaths.deliverPattern(crossTarget.value), - if (isSnapshot.value) "integration" else "release", - ivyConfigurations.value.map(c => ConfigRef(c.name)).toVector, - artifacts, - (pushRemoteCacheConfiguration / checksums).value.toVector, - Classpaths.getPublishTo(pushRemoteCacheTo.value).name, - ivyLoggingLevel.value, - isSnapshot.value - ) - }, - pushRemoteCacheConfiguration / packagedArtifacts := Def.uncached( - (Def - .task { (pushRemoteCacheConfiguration / remoteCacheArtifacts).value }) - .flatMapTask { case artifacts => - artifacts - .map(a => a.packaged.map(file => (a.artifact, file))) - .join - .apply(_.join.map(_.toMap)) - } - .value - ), - pushRemoteCacheConfiguration / remoteCacheArtifacts := Def.uncached { - List((packageCache / remoteCacheArtifact).value) - }, - pullRemoteCache := Def.uncached { - import scala.jdk.CollectionConverters.* - 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 - val copyResources = getResourceFilePaths().value - 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[String](_)) - 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, copyResources) - 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 = - artifact match { - case _: PomRemoteCacheArtifact => true - case _ => false - } - - def compileArtifact( - configuration: Configuration, - classifier: String - ): Def.Initialize[Task[CompileRemoteCacheArtifact]] = Def.task { - CompileRemoteCacheArtifact( - Artifact(moduleName.value, classifier), - configuration / packageCache, - (configuration / classDirectory).value, - (configuration / compileAnalysisFile).value - ) - } - - private def toVersion(v: String): String = s"0.0.0-$v" - - private lazy val doption = new DownloadOptions - private def pullFromMavenRepo0( - artifacts: Vector[IArtifact], - r: DependencyResolver, - log: Logger - ): 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) - } - } - - 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, - copyResources: File - ): Unit = - cacheArtifact match { - case a: CompileRemoteCacheArtifact => - extractCache(jar, a.extractDirectory, preserveLastModified = true) { output => - extractAnalysis(output, a.analysisFile) - extractResourceList(output, copyResources) - } - - case a: TestRemoteCacheArtifact => - extractCache(jar, a.extractDirectory, preserveLastModified = true) { output => - extractAnalysis(output, a.analysisFile) - extractTestResult(output, a.testResult) - } - - case a: CustomRemoteCacheArtifact => - extractCache(jar, a.extractDirectory, a.preserveLastModified)(_ => ()) - - case _ => - () - } - - private def extractCache(jar: File, output: File, preserveLastModified: Boolean)( - processOutput: File => Unit - ): Unit = { - IO.delete(output) - IO.unzip(jar, output, preserveLastModified = preserveLastModified) - processOutput(output) - - // preserve semanticdb dir - // https://github.com/scalameta/scalameta/blob/a7927ee8e012cfff/semanticdb/scalac/library/src/main/scala/scala/meta/internal/semanticdb/scalac/SemanticdbPaths.scala#L9 - Option((output / "META-INF").listFiles).foreach( - _.iterator.filterNot(_.getName == "semanticdb").foreach(IO.delete) - ) - } - - 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) - } - } - - private def extractResourceList(output: File, copyResources: File): Unit = { - val metaDir = output / "META-INF" - val extractedCopyResources = metaDir / "copy-resources.txt" - if (extractedCopyResources.exists) { - IO.move(extractedCopyResources, copyResources) - } - } - - 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[HashedVirtualFileRef]] = - Seq(Compile / packageCache, Test / packageCache) - - private def enabledOnly[A]( - key: SettingKey[A], - pkgTasks: Seq[TaskKey[HashedVirtualFileRef]] - ): Def.Initialize[Seq[A]] = - Classpaths - .forallIn(key, pkgTasks) - .zipWith(Classpaths.forallIn(pushRemoteCacheArtifact, pkgTasks)) - .apply(_.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) - } -} +end RemoteCache diff --git a/main/src/main/scala/sbt/internal/LintUnused.scala b/main/src/main/scala/sbt/internal/LintUnused.scala index d11b04785..215830fd6 100644 --- a/main/src/main/scala/sbt/internal/LintUnused.scala +++ b/main/src/main/scala/sbt/internal/LintUnused.scala @@ -43,7 +43,6 @@ object LintUnused { onLoadMessage, onUnload, pollInterval, - pushRemoteCacheArtifact, sbt.nio.Keys.outputFileStamper, sbt.nio.Keys.watchTriggers, serverConnectionType, diff --git a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/build.sbt b/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/build.sbt deleted file mode 100644 index 3153cb66d..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/build.sbt +++ /dev/null @@ -1,18 +0,0 @@ -name := "my-project" - -scalaVersion := "2.12.20" - -semanticdbIncludeInJar := true - -semanticdbEnabled := true - -pushRemoteCacheTo := Some( - MavenCache("local-cache", (ThisBuild / baseDirectory).value / "remote-cache-semanticdb") -) - -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) diff --git a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/disabled b/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/disabled deleted file mode 100644 index 3875dd2ea..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/disabled +++ /dev/null @@ -1,48 +0,0 @@ -> pushRemoteCache - -# Generated sources, compiled classes -$ exists target/scala-2.12/classes/MyClass.class -$ exists target/scala-2.12/classes/MyClass$.class -$ exists target/scala-2.12/classes/META-INF/semanticdb/src/main/scala/MyClass.scala.semanticdb -$ 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-classes/META-INF/semanticdb/src/test/scala/MyTest.scala.semanticdb -$ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip - -# 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 -$ 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.sha1 - -# Test -$ 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-test.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-test.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-test.jar.sha1 - -> clean - -$ absent target/scala-2.12/classes/MyClass.class -$ absent target/scala-2.12/classes/MyClass$.class -$ absent target/scala-2.12/classes/META-INF -$ 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-classes/META-INF -$ absent target/scala-2.12/test-zinc/inc_compile_2.12.zip - -> pullRemoteCache - -# Files extracted from the cache artifacts -$ exists target/scala-2.12/classes/MyClass.class -$ exists target/scala-2.12/classes/MyClass$.class -$ exists target/scala-2.12/classes/META-INF/semanticdb/src/main/scala/MyClass.scala.semanticdb -$ 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-classes/META-INF/semanticdb/src/test/scala/MyTest.scala.semanticdb -$ exists target/scala-2.12/test-zinc/inc_compile_2.12.zip - -# Artifacts can be pushed twice (enabled overriding) -> pushRemoteCache - diff --git a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/src/main/scala/MyClass.scala b/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/src/main/scala/MyClass.scala deleted file mode 100644 index 2d9059cdb..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/src/main/scala/MyClass.scala +++ /dev/null @@ -1 +0,0 @@ -object MyClass diff --git a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/src/test/scala/MyTest.scala b/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/src/test/scala/MyTest.scala deleted file mode 100644 index 9caa86632..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache-semanticdb/src/test/scala/MyTest.scala +++ /dev/null @@ -1 +0,0 @@ -object MyTest diff --git a/sbt-app/src/sbt-test/actions/remote-cache/build.sbt b/sbt-app/src/sbt-test/actions/remote-cache/build.sbt deleted file mode 100644 index 4d87f8c62..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache/build.sbt +++ /dev/null @@ -1,95 +0,0 @@ -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.20" -ThisBuild / pushRemoteCacheTo := Some( - MavenCache("local-cache", (ThisBuild / baseDirectory).value / "r") -) - -lazy val root = (project in file(".")) - .configs(CustomArtifact) - .settings( - name := "my-project", - - 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, - // 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), - - // test tasks - recordPreviousIterations := { - val log = streams.value.log - CompileState.previousIterations = { - val previousAnalysis = (Compile / previousCompile).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 / 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 - 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-app/src/sbt-test/actions/remote-cache/disabled b/sbt-app/src/sbt-test/actions/remote-cache/disabled deleted file mode 100644 index 5da745c18..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache/disabled +++ /dev/null @@ -1,56 +0,0 @@ -> recordPreviousIterations -> 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 - -# Compile -$ 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 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 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 - -$ 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 - -> checkIterations 1 - -# Artifacts can be pushed twice (enabled overriding) -> pushRemoteCache \ No newline at end of file diff --git a/sbt-app/src/sbt-test/actions/remote-cache/project/CompileState.scala b/sbt-app/src/sbt-test/actions/remote-cache/project/CompileState.scala deleted file mode 100644 index 078db9c7b..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache/project/CompileState.scala +++ /dev/null @@ -1,4 +0,0 @@ -// This is necessary because tests are run in batch mode -object CompileState { - @volatile var previousIterations: Int = -1 -} diff --git a/sbt-app/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala b/sbt-app/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala deleted file mode 100644 index 7c7f7e635..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache/src/main/scala/MyClass.scala +++ /dev/null @@ -1 +0,0 @@ -object MyClass \ No newline at end of file diff --git a/sbt-app/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala b/sbt-app/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala deleted file mode 100644 index d27811abd..000000000 --- a/sbt-app/src/sbt-test/actions/remote-cache/src/test/scala/MyTest.scala +++ /dev/null @@ -1 +0,0 @@ -object MyTest \ No newline at end of file