diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 3ce80bf67..00d53e26e 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -2278,7 +2278,8 @@ object Classpaths { unresolvedWarningConfiguration in update := UnresolvedWarningConfiguration( dependencyPositions.value ), - update := (updateTask tag (Tags.Update, Tags.Network)).value, + updateFull := (updateTask tag (Tags.Update, Tags.Network)).value, + update := (updateWithoutDetails("update") tag (Tags.Update, Tags.Network)).value, update := { val report = update.value val log = streams.value.log @@ -2656,9 +2657,23 @@ object Classpaths { } } - def updateTask: Initialize[Task[UpdateReport]] = Def.task { + def updateTask: Initialize[Task[UpdateReport]] = updateTask0("updateFull", true, true) + def updateWithoutDetails(label: String): Initialize[Task[UpdateReport]] = + updateTask0(label, false, false) + + /** + * cacheLabel - label to identify an update cache + * includeCallers - include the caller information + * includeDetails - include module reports for the evicted modules + */ + private def updateTask0( + cacheLabel: String, + includeCallers: Boolean, + includeDetails: Boolean + ): Initialize[Task[UpdateReport]] = Def.task { val s = streams.value - val cacheDirectory = streams.value.cacheDirectory + val cacheDirectory = crossTarget.value / cacheLabel / updateCacheName.value + val cacheStoreFactory: CacheStoreFactory = CacheStoreFactory.directory(cacheDirectory) val isRoot = executionRoots.value contains resolvedScoped.value val shouldForce = isRoot || { @@ -2721,7 +2736,7 @@ object Classpaths { lm = dependencyResolution.value, // Ivy-free ModuleDescriptor module = ivyModule.value, - s.cacheStoreFactory.sub(updateCacheName.value), + cacheStoreFactory = cacheStoreFactory, label = label, updateConf, substituteScalaFiles(scalaOrganization.value, _)(providedScalaJars), @@ -2732,6 +2747,8 @@ object Classpaths { ewo = evictionOptions, mavenStyle = publishMavenStyle.value, compatWarning = compatibilityWarningOptions.value, + includeCallers = includeCallers, + includeDetails = includeDetails, log = s.log ) } diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 0f5894bbf..ac2711453 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -370,6 +370,7 @@ object Keys { val ivyModule = taskKey[IvySbt#Module]("Provides the sbt interface to a configured Ivy module.").withRank(CTask) val updateCacheName = taskKey[String]("Defines the directory name used to store the update cache files (inside the streams cacheDirectory).").withRank(DTask) val update = taskKey[UpdateReport]("Resolves and optionally retrieves dependencies, producing a report.").withRank(ATask) + val updateFull = taskKey[UpdateReport]("Resolves and optionally retrieves dependencies, producing a full report with callers.").withRank(CTask) val evicted = taskKey[EvictionWarning]("Display detailed eviction warnings.").withRank(CTask) val evictionWarningOptions = settingKey[EvictionWarningOptions]("Options on eviction warnings after resolving managed dependencies.").withRank(DSetting) val transitiveUpdate = taskKey[Seq[UpdateReport]]("UpdateReports for the internal dependencies of this project.").withRank(DTask) diff --git a/main/src/main/scala/sbt/internal/LibraryManagement.scala b/main/src/main/scala/sbt/internal/LibraryManagement.scala index fc45b83c0..e6366446d 100644 --- a/main/src/main/scala/sbt/internal/LibraryManagement.scala +++ b/main/src/main/scala/sbt/internal/LibraryManagement.scala @@ -33,6 +33,8 @@ private[sbt] object LibraryManagement { ewo: EvictionWarningOptions, mavenStyle: Boolean, compatWarning: CompatibilityWarningOptions, + includeCallers: Boolean, + includeDetails: Boolean, log: Logger ): UpdateReport = { @@ -50,15 +52,15 @@ private[sbt] object LibraryManagement { throw unresolvedWarning.resolveException } log.debug(s"Done updating $label") - val finalReport = transform(report) + val report1 = transform(report) // Warn of any eviction and compatibility warnings - val ew = EvictionWarning(module, ewo, finalReport) + val ew = EvictionWarning(module, ewo, report1) ew.lines.foreach(log.warn(_)) ew.infoAllTheThings.foreach(log.info(_)) CompatibilityWarning.run(compatWarning, module, mavenStyle, log) - - finalReport + val report2 = transformDetails(report1, includeCallers, includeDetails) + report2 } /* Check if a update report is still up to date or we must resolve again. */ @@ -90,7 +92,9 @@ private[sbt] object LibraryManagement { import sbt.librarymanagement.LibraryManagementCodec._ val cachedResolve = Tracked.lastOutput[UpdateInputs, UpdateReport](cache) { case (_, Some(out)) if upToDate(inChanged, out) => markAsCached(out) - case _ => resolve + case pair => + log.debug(s""""not up to date. inChanged = $inChanged, force = $force""") + resolve } import scala.util.control.Exception.catching catching(classOf[NullPointerException], classOf[OutOfMemoryError]) @@ -150,4 +154,24 @@ private[sbt] object LibraryManagement { .withExtraAttributes(m.extraAttributes) .withConfigurations(if (confs) m.configurations else None) .branch(m.branchName) + + private[this] def transformDetails( + ur: UpdateReport, + includeCallers: Boolean, + includeDetails: Boolean + ): UpdateReport = { + val crs0 = ur.configurations + val crs1 = + if (includeDetails) crs0 + else crs0 map { _.withDetails(Vector()) } + val crs2 = + if (includeCallers) crs1 + else + crs1 map { cr => + val mrs0 = cr.modules + val mrs1 = mrs0 map { _.withCallers(Vector()) } + cr.withModules(mrs1) + } + ur.withConfigurations(crs2) + } } diff --git a/sbt/src/sbt-test/dependency-management/cache-update/build.sbt b/sbt/src/sbt-test/dependency-management/cache-update/build.sbt index db7eead25..b12fb7e29 100644 --- a/sbt/src/sbt-test/dependency-management/cache-update/build.sbt +++ b/sbt/src/sbt-test/dependency-management/cache-update/build.sbt @@ -31,7 +31,9 @@ lazy val root = (project in file(".")) // sbt resolves dependencies every compile when using %% with dependencyOverrides TaskKey[Unit]("check") := { val s = (streams in update).value - val cacheStoreFactory = s.cacheStoreFactory sub updateCacheName.value + + val cacheDirectory = crossTarget.value / "update" / updateCacheName.value + val cacheStoreFactory = sbt.util.CacheStoreFactory.directory(cacheDirectory) val module = ivyModule.value val updateConfig = updateConfiguration.value val extraInputHash0 = module.extraInputHash