Better inter-project dependencies handling

This commit is contained in:
Alexandre Archambault 2016-07-24 14:32:33 +02:00
parent 5ac4efc661
commit 22c7340f6f
No known key found for this signature in database
GPG Key ID: 14640A6839C263A9
10 changed files with 108 additions and 10 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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,

View File

@ -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")

View File

@ -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")

View File

@ -0,0 +1,6 @@
object A {
def msg = "OK"
}

View File

@ -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"))
}

View File

@ -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"
)

View File

@ -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)
}

View File

@ -0,0 +1,3 @@
$ delete output
> b/run
$ exists output