diff --git a/ivy/src/main/scala/sbt/EvictionWarning.scala b/ivy/src/main/scala/sbt/EvictionWarning.scala index 7279b77da..0e0234de5 100644 --- a/ivy/src/main/scala/sbt/EvictionWarning.scala +++ b/ivy/src/main/scala/sbt/EvictionWarning.scala @@ -9,6 +9,7 @@ final class EvictionWarningOptions private[sbt] ( val warnScalaVersionEviction: Boolean, val warnDirectEvictions: Boolean, val warnTransitiveEvictions: Boolean, + val infoAllEvictions: Boolean, val showCallers: Boolean, val guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean]) { private[sbt] def configStrings = configurations map { _.name } @@ -21,6 +22,8 @@ final class EvictionWarningOptions private[sbt] ( copy(warnDirectEvictions = warnDirectEvictions) def withWarnTransitiveEvictions(warnTransitiveEvictions: Boolean): EvictionWarningOptions = copy(warnTransitiveEvictions = warnTransitiveEvictions) + def withInfoAllEvictions(infoAllEvictions: Boolean): EvictionWarningOptions = + copy(infoAllEvictions = infoAllEvictions) def withShowCallers(showCallers: Boolean): EvictionWarningOptions = copy(showCallers = showCallers) def withGuessCompatible(guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean]): EvictionWarningOptions = @@ -30,21 +33,25 @@ final class EvictionWarningOptions private[sbt] ( warnScalaVersionEviction: Boolean = warnScalaVersionEviction, warnDirectEvictions: Boolean = warnDirectEvictions, warnTransitiveEvictions: Boolean = warnTransitiveEvictions, + infoAllEvictions: Boolean = infoAllEvictions, showCallers: Boolean = showCallers, guessCompatible: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = guessCompatible): EvictionWarningOptions = new EvictionWarningOptions(configurations = configurations, warnScalaVersionEviction = warnScalaVersionEviction, warnDirectEvictions = warnDirectEvictions, warnTransitiveEvictions = warnTransitiveEvictions, + infoAllEvictions = infoAllEvictions, showCallers = showCallers, guessCompatible = guessCompatible) } object EvictionWarningOptions { + def empty: EvictionWarningOptions = + new EvictionWarningOptions(Vector(), false, false, false, false, false, defaultGuess) def default: EvictionWarningOptions = - new EvictionWarningOptions(Vector(Compile), true, true, false, false, defaultGuess) + new EvictionWarningOptions(Vector(Compile), true, true, false, false, false, defaultGuess) def full: EvictionWarningOptions = - new EvictionWarningOptions(Vector(Compile), true, true, true, true, defaultGuess) + new EvictionWarningOptions(Vector(Compile), true, true, true, true, true, defaultGuess) lazy val defaultGuess: Function1[(ModuleID, Option[ModuleID], Option[IvyScala]), Boolean] = guessSecondSegment orElse guessSemVer orElse guessFalse @@ -78,6 +85,18 @@ final class EvictionPair private[sbt] ( val showCallers: Boolean) { override def toString: String = EvictionPair.evictionPairLines.showLines(this).mkString + override def equals(o: Any): Boolean = o match { + case o: EvictionPair => + (this.organization == o.organization) && + (this.name == o.name) + case _ => false + } + override def hashCode: Int = { + var hash = 1 + hash = hash * 31 + this.organization.## + hash = hash * 31 + this.name.## + hash + } } object EvictionPair { @@ -105,6 +124,7 @@ final class EvictionWarning private[sbt] ( val transitiveEvictions: Seq[EvictionPair], val allEvictions: Seq[EvictionPair]) { def reportedEvictions: Seq[EvictionPair] = scalaEvictions ++ directEvictions ++ transitiveEvictions + private[sbt] def infoAllTheThings: List[String] = EvictionWarning.infoAllTheThings(this) } object EvictionWarning { @@ -201,4 +221,21 @@ object EvictionWarning { out.toList } + + private[sbt] def infoAllTheThings(a: EvictionWarning): List[String] = + if (a.options.infoAllEvictions) { + import ShowLines._ + val evo = a.options + val out: mutable.ListBuffer[String] = mutable.ListBuffer() + a.allEvictions foreach { ev => + if ((a.scalaEvictions contains ev) && evo.warnScalaVersionEviction) () + else if ((a.directEvictions contains ev) && evo.warnDirectEvictions) () + else if ((a.transitiveEvictions contains ev) && evo.warnTransitiveEvictions) () + else { + out ++= ev.lines + } + } + if (out.isEmpty) Nil + else List("Here are other libraries that were evicted:") ::: out.toList + } else Nil } diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 8c8d69a7c..dac363583 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1150,13 +1150,9 @@ object Classpaths { unresolvedWarningConfiguration in update := UnresolvedWarningConfiguration(dependencyPositions.value), update <<= updateTask tag (Tags.Update, Tags.Network), update := { - import ShowLines._ val report = update.value val log = streams.value.log ConflictWarning(conflictWarning.value, report, log) - val ewo = (evictionWarningOptions in update).value - val ew = EvictionWarning(ivyModule.value, ewo, report, log) - ew.lines foreach { log.warn(_) } report }, evictionWarningOptions in evicted := EvictionWarningOptions.full, @@ -1166,6 +1162,7 @@ object Classpaths { val log = streams.value.log val ew = EvictionWarning(ivyModule.value, (evictionWarningOptions in evicted).value, report, log) ew.lines foreach { log.warn(_) } + ew.infoAllTheThings foreach { log.info(_) } ew }, classifiersModule in updateClassifiers := { @@ -1336,33 +1333,42 @@ object Classpaths { case Some(x) if uc0.logging == Default => uc0.copy(logging = DownloadOnly) case _ => uc0 } - cachedUpdate(s.cacheDirectory / updateCacheName.value, show, ivyModule.value, uc0, transform, + val ewo = + if (executionRoots.value exists { _.key == evicted.key }) EvictionWarningOptions.empty + else (evictionWarningOptions in update).value + cachedUpdate(s.cacheDirectory / updateCacheName.value, show, ivyModule.value, uc, transform, skip = (skip in update).value, force = isRoot, depsUpdated = depsUpdated, - uwConfig = uwConfig, logicalClock = logicalClock, depDir = Some(depDir), log = s.log) + uwConfig = uwConfig, logicalClock = logicalClock, depDir = Some(depDir), + ewo = ewo, log = s.log) } @deprecated("Use cachedUpdate with the variant that takes unresolvedHandler instead.", "0.13.6") def cachedUpdate(cacheFile: File, label: String, module: IvySbt#Module, config: UpdateConfiguration, transform: UpdateReport => UpdateReport, skip: Boolean, force: Boolean, depsUpdated: Boolean, log: Logger): UpdateReport = cachedUpdate(cacheFile, label, module, config, transform, skip, force, depsUpdated, - UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) + UnresolvedWarningConfiguration(), LogicalClock.unknown, None, EvictionWarningOptions.empty, log) private[sbt] def cachedUpdate(cacheFile: File, label: String, module: IvySbt#Module, config: UpdateConfiguration, transform: UpdateReport => UpdateReport, skip: Boolean, force: Boolean, depsUpdated: Boolean, - uwConfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File], log: Logger): UpdateReport = + uwConfig: UnresolvedWarningConfiguration, logicalClock: LogicalClock, depDir: Option[File], + ewo: EvictionWarningOptions, log: Logger): UpdateReport = { implicit val updateCache = updateIC type In = IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil def work = (_: In) match { case conf :+: settings :+: config :+: HNil => + import ShowLines._ log.info("Updating " + label + "...") val r = IvyActions.updateEither(module, config, uwConfig, logicalClock, depDir, log) match { case Right(ur) => ur case Left(uw) => - import ShowLines._ uw.lines foreach { log.warn(_) } throw uw.resolveException } log.info("Done updating.") - transform(r) + val result = transform(r) + val ew = EvictionWarning(module, ewo, result, log) + ew.lines foreach { log.warn(_) } + ew.infoAllTheThings foreach { log.info(_) } + result } def uptodate(inChanged: Boolean, out: UpdateReport): Boolean = !force && diff --git a/notes/0.13.8/eviction-warning-fix.markdown b/notes/0.13.8/eviction-warning-fix.markdown new file mode 100644 index 000000000..a0c2b2818 --- /dev/null +++ b/notes/0.13.8/eviction-warning-fix.markdown @@ -0,0 +1,15 @@ + [@cunei]: https://github.com/cunei + [@eed3si9n]: https://github.com/eed3si9n + [@gkossakowski]: https://github.com/gkossakowski + [@jsuereth]: https://github.com/jsuereth + [1615]: https://github.com/sbt/sbt/issues/1615 + +### Fixes with compatibility implications + +### Improvements + +- `evicted` will display all evictions (including the ones not suspected of binary incompatibility). [#1615][1615] by [@eed3si9n][@eed3si9n] + +### Bug fixes + +- Fixes eviction warning being too noisy. [#1615][1615] by [@eed3si9n][@eed3si9n]