diff --git a/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala b/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala index 694eab1d3..cb65aa82c 100644 --- a/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala +++ b/src/main/scala-sbt-0.13/sbt/dependencygraph/DependencyGraphSbtCompat.scala @@ -1,7 +1,81 @@ -package sbt.dependencygraph +package sbt +package dependencygraph + +import scala.language.implicitConversions + +import java.util.concurrent.TimeUnit + +import Keys._ +import Def.Initialize +import CrossVersion._ + +import scala.concurrent.duration.FiniteDuration object DependencyGraphSbtCompat { object Implicits { implicit def convertConfig(config: sbt.Configuration): String = config.toString + + implicit class RichUpdateConfiguration(val updateConfig: UpdateConfiguration) extends AnyVal { + def withMissingOk(missingOk: Boolean): UpdateConfiguration = + updateConfig.copy(missingOk = missingOk) + } + } + + /** + * This is copied directly from https://github.com/sbt/sbt/blob/2952a2b9b672c5402b824ad2d2076243eb643598/main/src/main/scala/sbt/Defaults.scala#L1471-L1523 + * and then changed to update the UpdateConfiguration to ignore missing artifacts. + */ + def updateTask(task: TaskKey[_]): Initialize[Task[UpdateReport]] = Def.task { + val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached) + val isRoot = executionRoots.value contains resolvedScoped.value + val forceUpdate = forceUpdatePeriod.value + val s = streams.value + val fullUpdateOutput = s.cacheDirectory / "out" + val forceUpdateByTime = forceUpdate match { + case None => false + case Some(period) => + val elapsedDuration = new FiniteDuration(System.currentTimeMillis() - fullUpdateOutput.lastModified(), TimeUnit.MILLISECONDS) + fullUpdateOutput.exists() && elapsedDuration > period + } + val scalaProvider = appConfiguration.value.provider.scalaProvider + + // Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for: + // the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked) + // the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion + def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) => + (partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match { + case (Some(res), Some(sh), _) if res == sh => jars + case (Some(res), _, Some(decl)) if res == decl => jars + case _ => Nil + } + val subScalaJars: String => Seq[File] = Defaults.unmanagedScalaInstanceOnly.value match { + case Some(si) => subUnmanaged(si.version, si.jars) + case None => sv => if (scalaProvider.version == sv) scalaProvider.jars else Nil + } + val transform: UpdateReport => UpdateReport = r => sbt.Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars) + val uwConfig = (unresolvedWarningConfiguration in update).value + val show = Reference.display(thisProjectRef.value) + val st = state.value + val logicalClock = LogicalClock(st.hashCode) + val depDir = dependencyCacheDirectory.value + val uc0 = (updateConfiguration in task).value + val ms = publishMavenStyle.value + val cw = compatibilityWarningOptions.value + // Normally, log would capture log messages at all levels. + // Ivy logs are treated specially using sbt.UpdateConfiguration.logging. + // This code bumps up the sbt.UpdateConfiguration.logging to Full when logLevel is Debug. + import UpdateLogging.{ Full, DownloadOnly, Default } + val uc = (logLevel in update).?.value orElse st.get(logLevel.key) match { + case Some(Level.Debug) if uc0.logging == Default => uc0.copy(logging = Full) + case Some(x) if uc0.logging == Default => uc0.copy(logging = DownloadOnly) + case _ => uc0 + } + val ewo = + if (executionRoots.value exists { _.key == evicted.key }) EvictionWarningOptions.empty + else (evictionWarningOptions in update).value + sbt.Classpaths.cachedUpdate(s.cacheDirectory / updateCacheName.value, show, ivyModule.value, uc, transform, + skip = (skip in update).value, force = isRoot || forceUpdateByTime, depsUpdated = depsUpdated, + uwConfig = uwConfig, logicalClock = logicalClock, depDir = Some(depDir), + ewo = ewo, mavenStyle = ms, compatWarning = cw, log = s.log) } } diff --git a/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala b/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala index 68887c10c..4e08319db 100644 --- a/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala +++ b/src/main/scala-sbt-1.0/sbt/dependencygraph/DependencyGraphSbtCompat.scala @@ -1,7 +1,64 @@ -package sbt.dependencygraph +package sbt +package dependencygraph + +import Keys._ +import Def.Initialize + +import CrossVersion.partialVersion +import sbt.internal.LibraryManagement object DependencyGraphSbtCompat { - object Implicits { - implicit def convertConfig(config: sbt.Configuration): sbt.Configuration = config + object Implicits + + // https://github.com/sbt/sbt/blob/4ce4fb72bde3b8acfaf526b79d32ca1463bc687b/main/src/main/scala/sbt/Defaults.scala#L2298 adapted + // to allow customization of UpdateConfiguration + def updateTask(task: TaskKey[_]): Initialize[Task[UpdateReport]] = Def.task { + val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached) + val isRoot = executionRoots.value contains resolvedScoped.value + val s = streams.value + val scalaProvider = appConfiguration.value.provider.scalaProvider + + // Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for: + // the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked) + // the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion + def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) ⇒ + (partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match { + case (Some(res), Some(sh), _) if res == sh ⇒ jars + case (Some(res), _, Some(decl)) if res == decl ⇒ jars + case _ ⇒ Nil + } + + val subScalaJars: String ⇒ Seq[File] = SbtAccess.unmanagedScalaInstanceOnly.value match { + case Some(si) ⇒ subUnmanaged(si.version, si.allJars) + case None ⇒ sv ⇒ if (scalaProvider.version == sv) scalaProvider.jars else Nil + } + + val transform: UpdateReport ⇒ UpdateReport = + r ⇒ Classpaths.substituteScalaFiles(scalaOrganization.value, r)(subScalaJars) + + val evictionOptions = Def.taskDyn { + if (executionRoots.value.exists(_.key == evicted.key)) + Def.task(EvictionWarningOptions.empty) + else Def.task((evictionWarningOptions in update).value) + }.value + + LibraryManagement.cachedUpdate( + // LM API + lm = dependencyResolution.value, + // Ivy-free ModuleDescriptor + module = ivyModule.value, + s.cacheStoreFactory.sub(updateCacheName.value), + Reference.display(thisProjectRef.value), + (updateConfiguration in task).value, + transform = transform, + skip = (skip in update).value, + force = isRoot, + depsUpdated = transitiveUpdate.value.exists(!_.stats.cached), + uwConfig = (unresolvedWarningConfiguration in update).value, + ewo = evictionOptions, + mavenStyle = publishMavenStyle.value, + compatWarning = compatibilityWarningOptions.value, + log = s.log + ) } } diff --git a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala index 9768de3e9..369c7f3dc 100644 --- a/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala +++ b/src/main/scala/net/virtualvoid/sbt/graph/DependencyGraphSettings.scala @@ -16,18 +16,18 @@ package net.virtualvoid.sbt.graph +import scala.language.reflectiveCalls + import sbt._ import Keys._ -import CrossVersion._ import sbt.complete.Parser import org.apache.ivy.core.resolve.ResolveOptions import net.virtualvoid.sbt.graph.backend.{ IvyReport, SbtUpdateReport } import net.virtualvoid.sbt.graph.rendering.{ AsciiGraph, DagreHTML } import net.virtualvoid.sbt.graph.util.IOUtil - import internal.librarymanagement._ import librarymanagement._ - +import sbt.dependencygraph.DependencyGraphSbtCompat import sbt.dependencygraph.DependencyGraphSbtCompat.Implicits._ object DependencyGraphSettings { @@ -37,7 +37,7 @@ object DependencyGraphSettings { def graphSettings = Seq( ivyReportFunction := ivyReportFunctionTask.value, updateConfiguration in ignoreMissingUpdate := updateConfiguration.value.withMissingOk(true), - ignoreMissingUpdate := update.value, + ignoreMissingUpdate := DependencyGraphSbtCompat.updateTask(ignoreMissingUpdate).value, filterScalaLibrary in Global := true) ++ Seq(Compile, Test, IntegrationTest, Runtime, Provided, Optional).flatMap(ivyReportForConfig) def ivyReportForConfig(config: Configuration) = inConfig(config)(Seq( @@ -198,41 +198,4 @@ object DependencyGraphSettings { case _ ⇒ None } } - - /** - * This is copied directly from sbt/main/Defaults.scala and then changed to update the UpdateConfiguration - * to ignore missing artifacts. - */ - /*def ignoreMissingUpdateT = - ignoreMissingUpdate := { - // FIXME: remove busywork - - val scalaVersion = Keys.scalaVersion.value - val unmanagedScalaInstanceOnly = SbtAccess.unmanagedScalaInstanceOnly.value - val scalaOrganization = Keys.scalaOrganization.value - - val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached) - val isRoot = executionRoots.value contains resolvedScoped.value - val s = streams.value - val scalaProvider = appConfiguration.value.provider.scalaProvider - - // Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for: - // the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked) - // the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion - def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) ⇒ - (partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion)) match { - case (Some(res), Some(sh), _) if res == sh ⇒ jars - case (Some(res), _, Some(decl)) if res == decl ⇒ jars - case _ ⇒ Nil - } - val subScalaJars: String ⇒ Seq[File] = unmanagedScalaInstanceOnly match { - case Some(si) ⇒ subUnmanaged(si.version, si.allJars) - case None ⇒ sv ⇒ if (scalaProvider.version == sv) scalaProvider.jars else Nil - } - val transform: UpdateReport ⇒ UpdateReport = r ⇒ Classpaths.substituteScalaFiles(scalaOrganization, r)(subScalaJars) - - val show = Reference.display(thisProjectRef.value) - SbtAccess.cachedUpdater( - s.cacheDirectory, show, ivyModule.value, (updateConfiguration in ignoreMissingUpdate).value, transform, skip = (skip in update).value, force = isRoot, depsUpdated = depsUpdated, log = s.log) - }*/ }