From 22c7340f6fe4b8975c88b2091617176b955758c5 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Sun, 24 Jul 2016 14:32:33 +0200 Subject: [PATCH] Better inter-project dependencies handling --- README.md | 2 + doc/README.md | 2 + .../scala-2.10/coursier/CoursierPlugin.scala | 4 +- .../src/main/scala-2.10/coursier/Keys.scala | 2 +- .../src/main/scala-2.10/coursier/Tasks.scala | 37 ++++++++++++++---- .../inter-project/a/src/main/scala/A.scala | 6 +++ .../inter-project/b/src/main/scala/Main.scala | 13 +++++++ .../sbt-coursier/inter-project/build.sbt | 38 +++++++++++++++++++ .../inter-project/project/plugins.sbt | 11 ++++++ .../sbt-test/sbt-coursier/inter-project/test | 3 ++ 10 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 plugin/src/sbt-test/sbt-coursier/inter-project/a/src/main/scala/A.scala create mode 100644 plugin/src/sbt-test/sbt-coursier/inter-project/b/src/main/scala/Main.scala create mode 100644 plugin/src/sbt-test/sbt-coursier/inter-project/build.sbt create mode 100644 plugin/src/sbt-test/sbt-coursier/inter-project/project/plugins.sbt create mode 100644 plugin/src/sbt-test/sbt-coursier/inter-project/test diff --git a/README.md b/README.md index 898ac51d9..4a4b257ed 100644 --- a/README.md +++ b/README.md @@ -554,6 +554,8 @@ We're using the `Cache.file` method, that can also be given a `Logger` (for more #### Inter-project repository in the SBT plugin is a bit naive +**Fixed in 1.0.0-M13** + The inter-project repository is the pseudo-repository, nesting the metadata of sub-projects. It gets confused in at least these two cases: diff --git a/doc/README.md b/doc/README.md index d5aafe0b1..299128ef6 100644 --- a/doc/README.md +++ b/doc/README.md @@ -576,6 +576,8 @@ We're using the `Cache.file` method, that can also be given a `Logger` (for more #### Inter-project repository in the SBT plugin is a bit naive +**Fixed in 1.0.0-M13** + The inter-project repository is the pseudo-repository, nesting the metadata of sub-projects. It gets confused in at least these two cases: diff --git a/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala b/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala index bfdf40cf0..745848d75 100644 --- a/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala +++ b/plugin/src/main/scala-2.10/coursier/CoursierPlugin.scala @@ -26,7 +26,7 @@ object CoursierPlugin extends AutoPlugin { val coursierFallbackDependencies = Keys.coursierFallbackDependencies val coursierCache = Keys.coursierCache val coursierProject = Keys.coursierProject - val coursierProjects = Keys.coursierProjects + val coursierInterProjectDependencies = Keys.coursierInterProjectDependencies val coursierPublications = Keys.coursierPublications val coursierSbtClassifiersModule = Keys.coursierSbtClassifiersModule @@ -82,7 +82,7 @@ object CoursierPlugin extends AutoPlugin { ignoreArtifactErrors = true ), coursierProject <<= Tasks.coursierProjectTask, - coursierProjects <<= Tasks.coursierProjectsTask, + coursierInterProjectDependencies <<= Tasks.coursierInterProjectDependenciesTask, coursierPublications <<= Tasks.coursierPublicationsTask, coursierSbtClassifiersModule <<= classifiersModule in updateSbtClassifiers, coursierConfigurations <<= Tasks.coursierConfigurationsTask, diff --git a/plugin/src/main/scala-2.10/coursier/Keys.scala b/plugin/src/main/scala-2.10/coursier/Keys.scala index 3aa4a297c..49d89be75 100644 --- a/plugin/src/main/scala-2.10/coursier/Keys.scala +++ b/plugin/src/main/scala-2.10/coursier/Keys.scala @@ -31,7 +31,7 @@ object Keys { val coursierFallbackDependencies = TaskKey[Seq[(Module, String, URL, Boolean)]]("coursier-fallback-dependencies") val coursierProject = TaskKey[Project]("coursier-project") - val coursierProjects = TaskKey[Seq[Project]]("coursier-projects") + val coursierInterProjectDependencies = TaskKey[Seq[Project]]("coursier-inter-project-dependencies", "Projects the current project depends on, possibly transitively") val coursierPublications = TaskKey[Seq[(String, Publication)]]("coursier-publications") val coursierSbtClassifiersModule = TaskKey[GetClassifiersModule]("coursier-sbt-classifiers-module") diff --git a/plugin/src/main/scala-2.10/coursier/Tasks.scala b/plugin/src/main/scala-2.10/coursier/Tasks.scala index 9e0246c7d..d563814fd 100644 --- a/plugin/src/main/scala-2.10/coursier/Tasks.scala +++ b/plugin/src/main/scala-2.10/coursier/Tasks.scala @@ -96,9 +96,32 @@ object Tasks { } } - def coursierProjectsTask: Def.Initialize[sbt.Task[Seq[Project]]] = - sbt.Keys.state.flatMap { state => - val projects = structure(state).allProjectRefs + def coursierInterProjectDependenciesTask: Def.Initialize[sbt.Task[Seq[Project]]] = + ( + sbt.Keys.state, + sbt.Keys.thisProjectRef + ).flatMap { (state, projectRef) => + + def dependencies(map: Map[String, Seq[String]], id: String): Set[String] = { + + def helper(map: Map[String, Seq[String]], acc: Set[String]): Set[String] = + if (acc.exists(map.contains)) { + val (kept, rem) = map.partition { case (k, _) => acc(k) } + helper(rem, acc ++ kept.valuesIterator.flatten) + } else + acc + + helper(map - id, map.getOrElse(id, Nil).toSet) + } + + val allProjectsDeps = + for (p <- structure(state).allProjects) + yield p.id -> p.dependencies.map(_.project.project) + + val deps = dependencies(allProjectsDeps.toMap, projectRef.project) + + val projects = structure(state).allProjectRefs.filter(p => deps(p.project)) + coursierProject.forAllProjects(state, projects).map(_.values.toVector) } @@ -271,7 +294,7 @@ object Tasks { (proj.copy(publications = publications), fallbackDeps) } - val projects = coursierProjects.value + val interProjectDependencies = coursierInterProjectDependencies.value val parallelDownloads = coursierParallelDownloads.value val checksums = coursierChecksums.value @@ -363,12 +386,12 @@ object Tasks { userForceVersions ++ sourceRepositoriesForcedDependencies ++ forcedScalaModules(so, sv) ++ - projects.map(_.moduleVersion) + interProjectDependencies.map(_.moduleVersion) ) if (verbosityLevel >= 2) { log.info("InterProjectRepository") - for (p <- projects) + for (p <- interProjectDependencies) log.info(s" ${p.module}:${p.version}") } @@ -380,7 +403,7 @@ object Tasks { withArtifacts = false ) - val interProjectRepo = InterProjectRepository(projects) + val interProjectRepo = InterProjectRepository(interProjectDependencies) val ivyProperties = Map( "ivy.home" -> (new File(sys.props("user.home")).toURI.getPath + ".ivy2") diff --git a/plugin/src/sbt-test/sbt-coursier/inter-project/a/src/main/scala/A.scala b/plugin/src/sbt-test/sbt-coursier/inter-project/a/src/main/scala/A.scala new file mode 100644 index 000000000..5308caa95 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/inter-project/a/src/main/scala/A.scala @@ -0,0 +1,6 @@ + +object A { + + def msg = "OK" + +} diff --git a/plugin/src/sbt-test/sbt-coursier/inter-project/b/src/main/scala/Main.scala b/plugin/src/sbt-test/sbt-coursier/inter-project/b/src/main/scala/Main.scala new file mode 100644 index 000000000..624039aa5 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/inter-project/b/src/main/scala/Main.scala @@ -0,0 +1,13 @@ +import java.io.File +import java.nio.file.Files + +import argonaut._, Argonaut._, ArgonautShapeless._ + +object Main extends App { + + case class CC(i: Int, s: String) + + val msg = CC(2, A.msg).asJson.spaces2 + + Files.write(new File("output").toPath, msg.getBytes("UTF-8")) +} diff --git a/plugin/src/sbt-test/sbt-coursier/inter-project/build.sbt b/plugin/src/sbt-test/sbt-coursier/inter-project/build.sbt new file mode 100644 index 000000000..8cb64b323 --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/inter-project/build.sbt @@ -0,0 +1,38 @@ + +lazy val sharedSettings = Seq( + scalaVersion := "2.11.8", + coursierCachePolicies := { + if (sys.props("os.name").startsWith("Windows")) + coursierCachePolicies.value + else + Seq(coursier.CachePolicy.ForceDownload) + } +) + +/** Module with the same Maven coordinates as shapeless 2.3.1 */ +lazy val `shapeless-mock` = project + .settings(sharedSettings) + .settings( + organization := "com.chuusai", + name := "shapeless", + version := "2.3.1" + ) + +lazy val a = project + .settings(sharedSettings) + .settings( + organization := "com.pany", + name := "a", + version := "0.0.1" + ) + +/** Transitively depends on the - real - shapeless 2.3.1 */ +lazy val b = project + .dependsOn(a) + .settings(sharedSettings) + .settings( + organization := "com.pany", + name := "b", + version := "0.0.1", + libraryDependencies += "com.github.alexarchambault" %% "argonaut-shapeless_6.2" % "1.2.0-M1" + ) diff --git a/plugin/src/sbt-test/sbt-coursier/inter-project/project/plugins.sbt b/plugin/src/sbt-test/sbt-coursier/inter-project/project/plugins.sbt new file mode 100644 index 000000000..152225a9e --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/inter-project/project/plugins.sbt @@ -0,0 +1,11 @@ +{ + val pluginVersion = sys.props.getOrElse( + "plugin.version", + throw new RuntimeException( + """|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin + ) + ) + + addSbtPlugin("io.get-coursier" % "sbt-coursier" % pluginVersion) +} diff --git a/plugin/src/sbt-test/sbt-coursier/inter-project/test b/plugin/src/sbt-test/sbt-coursier/inter-project/test new file mode 100644 index 000000000..ea53e1abb --- /dev/null +++ b/plugin/src/sbt-test/sbt-coursier/inter-project/test @@ -0,0 +1,3 @@ +$ delete output +> b/run +$ exists output