diff --git a/ivy/src/main/scala/sbt/EvictionWarning.scala b/ivy/src/main/scala/sbt/EvictionWarning.scala new file mode 100644 index 000000000..4d3baec98 --- /dev/null +++ b/ivy/src/main/scala/sbt/EvictionWarning.scala @@ -0,0 +1,44 @@ +package sbt + +import collection.mutable + +final class EvictionWarningOptions( + val configurations: Seq[String], + val level: Level.Value) { +} +object EvictionWarningOptions { + def apply(): EvictionWarningOptions = + new EvictionWarningOptions(Vector("compile"), Level.Warn) +} + +object EvictionWarning { + def apply(options: EvictionWarningOptions, report: UpdateReport, log: Logger): Unit = { + val evictions = buildEvictions(options, report) + processEvictions(evictions, log) + } + + private[sbt] def buildEvictions(options: EvictionWarningOptions, report: UpdateReport): Seq[ModuleDetailReport] = { + val buffer: mutable.ListBuffer[ModuleDetailReport] = mutable.ListBuffer() + val confs = report.configurations filter { x => options.configurations contains x.configuration } + confs flatMap { confReport => + confReport.details map { detail => + if ((detail.modules exists { _.evicted }) && + !(buffer exists { x => (x.organization == detail.organization) && (x.name == detail.name) })) { + buffer += detail + } + } + } + buffer.toList.toVector + } + + private[sbt] def processEvictions(evictions: Seq[ModuleDetailReport], log: Logger): Unit = { + if (!evictions.isEmpty) { + log.warn("Some dependencies were evicted:") + evictions foreach { detail => + val revs = detail.modules filter { _.evicted } map { _.module.revision } + val winner = (detail.modules filterNot { _.evicted } map { _.module.revision }).headOption map { " -> " + _ } getOrElse "" + log.warn(s"\t* ${detail.organization}:${detail.name} (${revs.mkString(", ")})$winner") + } + } + } +} diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index fa13a0df2..c3ade184b 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1101,7 +1101,13 @@ object Classpaths { transitiveUpdate <<= transitiveUpdateTask, updateCacheName := "update_cache" + (if (crossPaths.value) s"_${scalaBinaryVersion.value}" else ""), update <<= updateTask tag (Tags.Update, Tags.Network), - update := { val report = update.value; ConflictWarning(conflictWarning.value, report, streams.value.log); report }, + update := { + val report = update.value + val log = streams.value.log + ConflictWarning(conflictWarning.value, report, log) + EvictionWarning(EvictionWarningOptions(), report, log) + report + }, classifiersModule in updateClassifiers := { import language.implicitConversions implicit val key = (m: ModuleID) => (m.organization, m.name, m.revision) @@ -1263,11 +1269,13 @@ object Classpaths { } def doWork: In => UpdateReport = Tracked.inputChanged(cacheFile / "inputs") { (inChanged: Boolean, in: In) => - val outCache = Tracked.lastOutput[In, UpdateReport](outCacheFile) { - case (_, Some(out)) if uptodate(inChanged, out) => out - case _ => work(in) - } - outCache(in) + // TODO FIX THIS! + // val outCache = Tracked.lastOutput[In, UpdateReport](outCacheFile) { + // case (_, Some(out)) if uptodate(inChanged, out) => out + // case _ => work(in) + // } + // outCache(in) + work(in) } val f = if (skip && !force) skipWork else doWork f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)