From d97170e48d1d369651993122d45a082afd88e9ed Mon Sep 17 00:00:00 2001 From: Timo Schmid Date: Wed, 29 May 2019 18:50:01 +0200 Subject: [PATCH] Overwrite evicted task #170 --- .../coursier/sbtcoursier/CoursierPlugin.scala | 1 + .../coursier/sbtcoursier/EvictedTasks.scala | 92 +++++++++++++++++++ .../sbt-test/sbt-coursier/evicted/build.sbt | 9 ++ .../sbt-coursier/evicted/project/plugins.sbt | 13 +++ .../src/sbt-test/sbt-coursier/evicted/test | 1 + 5 files changed, 116 insertions(+) create mode 100644 modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/EvictedTasks.scala create mode 100644 modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/build.sbt create mode 100644 modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/project/plugins.sbt create mode 100644 modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/test diff --git a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala index 953fa2df0..78b2d6024 100644 --- a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala +++ b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/CoursierPlugin.scala @@ -162,6 +162,7 @@ object CoursierPlugin extends AutoPlugin { withClassifiers = true, sbtClassifiers = true ).value, + evicted := EvictedTasks.evictedTask().value, coursierConfigGraphs := InputsTasks.ivyGraphsTask.value, coursierSbtClassifiersModule := classifiersModule.in(updateSbtClassifiers).value, coursierConfigurations := InputsTasks.coursierConfigurationsTask(None).value, diff --git a/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/EvictedTasks.scala b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/EvictedTasks.scala new file mode 100644 index 000000000..d1ab5945e --- /dev/null +++ b/modules/sbt-coursier/src/main/scala/coursier/sbtcoursier/EvictedTasks.scala @@ -0,0 +1,92 @@ +package coursier.sbtcoursier + +import coursier.core.{Configuration, Dependency} +import coursier.sbtcoursier.CoursierPlugin.autoImport.coursierResolutions +import sbt.{Def, EvictionWarning, Task} +import sbt.Keys._ + +object EvictedTasks { + + def evictedTask(): Def.Initialize[Task[EvictionWarning]] = + Def.task { + val log = streams.value.log + + val resolution = coursierResolutions.value + .filter(_._1.contains(Configuration("compile"))) + .head + ._2 + + def isEvicted(dependency: Dependency): Boolean = + resolution.finalDependenciesCache.keys.exists { finalDependency => + dependency.module == finalDependency.module && dependency.version != finalDependency.version + } + + def findAllVersions(dependency: Dependency): Set[String] = + resolution.finalDependenciesCache.keys + .filter(_.module == dependency.module) + .map(_.version) + .toSet + + def findLatestVersion(dependency: Dependency): String = + resolution.dependencies + .find(_.module == dependency.module) + .map(_.version) + .getOrElse("(unknown)") // this should never happen actually + + def findReverseDeps(dependency: Dependency): Seq[(Dependency, String)] = + resolution.reverseDependencies + .filterKeys(_.module == dependency.module) + .toSeq + .flatMap { t => + t._2.map(d => (d, d.version + " => " + t._1.version)) + } + .distinct + + // evicted deps and all their versions + val evictedDeps: Map[Dependency, Set[String]] = + resolution.rootDependencies + .filter(isEvicted) + .map { rootDep => + (rootDep, findAllVersions(rootDep)) + } + .toMap + + // TODO Returns 0 conflicts, investigate + /* + val conflicts: Seq[Conflict] = Conflict(resolution) + if(conflicts.nonEmpty) { + log.warn( + s"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:") + conflicts.foreach { conflict => + log.warn(s"""Using ${conflict.module}:${conflict.version} over ${conflict.wantedVersion} + |(wanted by ${conflict.dependeeModule}:${conflict.dependeeVersion})""".stripMargin) + } + } + */ + + if (evictedDeps.nonEmpty) { + log.warn( + s"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:") + evictedDeps.foreach { evictedDep => + log.warn(s" *: ${evictedDep._1.module}:${findLatestVersion( + evictedDep._1)} (${evictedDep._2.mkString(", ")})") + findReverseDeps(evictedDep._1).foreach { reverse => + log.warn( + s" +- ${reverse._1.module}:${reverse._1.version} (depends on ${reverse._2})") + } + } + } + + EvictionWarning( + dependencyResolution.value.moduleDescriptor( + projectID.value, + Vector(), + scalaModuleInfo.value + ), + (evictionWarningOptions in evicted).value, + update.value, + log + ) + } + +} diff --git a/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/build.sbt b/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/build.sbt new file mode 100644 index 000000000..1aab61136 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/build.sbt @@ -0,0 +1,9 @@ +scalaVersion := "2.11.8" + +libraryDependencies ++= { + sys.props("sbt.log.noformat") = "true" // disables colors in coursierWhatDependsOn output + Seq( + "org.typelevel" %% "cats-effect" % "1.3.1", + "org.typelevel" %% "cats-core" % "1.5.0" + ) +} diff --git a/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/project/plugins.sbt b/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/project/plugins.sbt new file mode 100644 index 000000000..503ac2871 --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/project/plugins.sbt @@ -0,0 +1,13 @@ +addSbtPlugin { + + val name = sys.props.getOrElse( + "plugin.name", + sys.error("plugin.name Java property not set") + ) + val version = sys.props.getOrElse( + "plugin.version", + sys.error("plugin.version Java property not set") + ) + + "io.get-coursier" % name % version +} diff --git a/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/test b/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/test new file mode 100644 index 000000000..5e9c5834b --- /dev/null +++ b/modules/sbt-coursier/src/sbt-test/sbt-coursier/evicted/test @@ -0,0 +1 @@ +> evicted