From d6e2720201f2209a2f7eb0b1c500321a176f4be0 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 28 Jul 2017 01:37:01 -0400 Subject: [PATCH 1/3] Let `ModuleDescriptor` declare cache inputs --- build.sbt | 2 + .../LibraryManagementInterface.scala | 10 +++ .../sbt/internal/librarymanagement/Ivy.scala | 73 ++++++++++++++++++- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 91c79119e..3debd56b2 100644 --- a/build.sbt +++ b/build.sbt @@ -102,6 +102,8 @@ lazy val lmCore = (project in file("core")) // method open(java.net.URL)java.net.HttpURLConnection in object sbt.librarymanagement.Http does not have a correspondent in current version // Was private[sbt] and manually checked to be unused in Zinc or sbt ProblemFilters.exclude[DirectMissingMethodProblem]("sbt.librarymanagement.Http.open"), + // New methods added to LM API + ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.librarymanagement.ModuleDescriptor.*"), ) ) .configure(addSbtIO, addSbtUtilLogging, addSbtUtilPosition, addSbtUtilCache) diff --git a/core/src/main/scala/sbt/librarymanagement/LibraryManagementInterface.scala b/core/src/main/scala/sbt/librarymanagement/LibraryManagementInterface.scala index 6afc27e2d..33c72c55f 100644 --- a/core/src/main/scala/sbt/librarymanagement/LibraryManagementInterface.scala +++ b/core/src/main/scala/sbt/librarymanagement/LibraryManagementInterface.scala @@ -81,4 +81,14 @@ trait ModuleDescriptor { * if any. */ def scalaModuleInfo: Option[ScalaModuleInfo] + + /** + * The input parameters used to construct the `ModuleSettings`. + */ + def moduleSettings: ModuleSettings + + /** + * Hash for extra parameter that were not captured as `moduleSettings`. + */ + def extraInputHash: Long } diff --git a/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala b/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala index 86c1ef5f2..dcf5f3327 100644 --- a/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala +++ b/ivy/src/main/scala/sbt/internal/librarymanagement/Ivy.scala @@ -36,10 +36,12 @@ import org.apache.ivy.util.extendable.ExtendableItem import org.apache.ivy.util.url._ import scala.xml.NodeSeq import scala.collection.mutable -import sbt.util.Logger +import scala.util.{ Success, Failure } +import sbt.util._ import sbt.librarymanagement.{ ModuleDescriptorConfiguration => InlineConfiguration, _ } import sbt.librarymanagement.ivy._ import sbt.librarymanagement.syntax._ + import IvyInternalDefaults._ import Resolver.PluginPattern import ivyint.{ @@ -49,6 +51,8 @@ import ivyint.{ SbtDefaultDependencyDescriptor, GigahorseUrlHandler } +import sjsonnew.JsonFormat +import sjsonnew.support.murmurhash.Hasher final class IvySbt(val configuration: IvyConfiguration) { self => /* @@ -336,6 +340,73 @@ final class IvySbt(val configuration: IvyConfiguration) { self => ) } private def toURL(file: File) = file.toURI.toURL + + // Todo: We just need writing side of this codec. We can clean up the reads. + private[sbt] object AltLibraryManagementCodec extends IvyLibraryManagementCodec { + import sbt.io.Hash + type InlineIvyHL = (Option[IvyPaths], Vector[Resolver], Vector[Resolver], Vector[ + ModuleConfiguration], Vector[String], Boolean) + def inlineIvyToHL(i: InlineIvyConfiguration): InlineIvyHL = + (i.paths, i.resolvers, i.otherResolvers, i.moduleConfigurations, + i.checksums, i.managedChecksums) + + type ExternalIvyHL = (Option[PlainFileInfo], Array[Byte]) + def externalIvyToHL(e: ExternalIvyConfiguration): ExternalIvyHL = + (e.baseDirectory.map(FileInfo.exists.apply), + e.uri.map(Hash.contentsIfLocal).getOrElse(Array.empty)) + + // Redefine to use a subset of properties, that are serialisable + override implicit lazy val InlineIvyConfigurationFormat: JsonFormat[InlineIvyConfiguration] = { + def hlToInlineIvy(i: InlineIvyHL): InlineIvyConfiguration = { + val (paths, resolvers, otherResolvers, moduleConfigurations, checksums, managedChecksums) = i + InlineIvyConfiguration() + .withPaths(paths) + .withResolvers(resolvers) + .withOtherResolvers(otherResolvers) + .withModuleConfigurations(moduleConfigurations) + .withManagedChecksums(managedChecksums) + .withChecksums(checksums) + } + projectFormat[InlineIvyConfiguration, InlineIvyHL](inlineIvyToHL, hlToInlineIvy) + } + + // Redefine to use a subset of properties, that are serialisable + override implicit lazy val ExternalIvyConfigurationFormat + : JsonFormat[ExternalIvyConfiguration] = { + def hlToExternalIvy(e: ExternalIvyHL): ExternalIvyConfiguration = { + val (baseDirectory, _) = e + ExternalIvyConfiguration( + None, + Some(NullLogger), + UpdateOptions(), + baseDirectory.map(_.file), + None /* the original uri is destroyed.. */, + Vector.empty + ) + } + projectFormat[ExternalIvyConfiguration, ExternalIvyHL](externalIvyToHL, hlToExternalIvy) + } + + // Redefine to switch to unionFormat + override implicit lazy val IvyConfigurationFormat: JsonFormat[IvyConfiguration] = + unionFormat2[IvyConfiguration, InlineIvyConfiguration, ExternalIvyConfiguration] + + object NullLogger extends sbt.internal.util.BasicLogger { + override def control(event: sbt.util.ControlEvent.Value, message: ⇒ String): Unit = () + override def log(level: Level.Value, message: ⇒ String): Unit = () + override def logAll(events: Seq[sbt.util.LogEvent]): Unit = () + override def success(message: ⇒ String): Unit = () + override def trace(t: ⇒ Throwable): Unit = () + } + } + + def extraInputHash: Long = { + import AltLibraryManagementCodec._ + Hasher.hash(owner.configuration) match { + case Success(keyHash) => keyHash.toLong + case Failure(_) => 0L + } + } } } From 208b8e427932f41bb17c0a7b6f2767622306ecae Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 28 Jul 2017 02:00:17 -0400 Subject: [PATCH 2/3] Exclude ReversedMissingMethodProblem sbt.internal.librarymanagement.formats.* --- build.sbt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.sbt b/build.sbt index 3debd56b2..144eb0a9a 100644 --- a/build.sbt +++ b/build.sbt @@ -104,6 +104,8 @@ lazy val lmCore = (project in file("core")) ProblemFilters.exclude[DirectMissingMethodProblem]("sbt.librarymanagement.Http.open"), // New methods added to LM API ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.librarymanagement.ModuleDescriptor.*"), + // New formats for Logger and GlockLock + ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.internal.librarymanagement.formats.*"), ) ) .configure(addSbtIO, addSbtUtilLogging, addSbtUtilPosition, addSbtUtilCache) From f976c6824b8ce0e8dec26c584a60f12806af0a39 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 28 Jul 2017 02:11:20 -0400 Subject: [PATCH 3/3] Name the reverse missing methods --- build.sbt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 144eb0a9a..6830f8389 100644 --- a/build.sbt +++ b/build.sbt @@ -103,7 +103,9 @@ lazy val lmCore = (project in file("core")) // Was private[sbt] and manually checked to be unused in Zinc or sbt ProblemFilters.exclude[DirectMissingMethodProblem]("sbt.librarymanagement.Http.open"), // New methods added to LM API - ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.librarymanagement.ModuleDescriptor.*"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.librarymanagement.ModuleDescriptor.moduleSettings"), + // New methods added to LM API + ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.librarymanagement.ModuleDescriptor.extraInputHash"), // New formats for Logger and GlockLock ProblemFilters.exclude[ReversedMissingMethodProblem]("sbt.internal.librarymanagement.formats.*"), )