Ensure unique project Id in composite projects

This commit is contained in:
Alistair Johnson 2018-04-04 21:01:05 +02:00
parent 77b536b25f
commit 03fc4ac686
11 changed files with 78 additions and 45 deletions

View File

@ -125,6 +125,27 @@ trait CompositeProject {
def componentProjects: Seq[Project]
}
object CompositeProject {
/**
* If two projects with the same id appear in `compositeProjects` and
* in `compositeProjects.map(_.componentProjects)`, the one in
* `compositeProjects` wins.
* This is necessary for backward compatibility with the idiom:
* lazy val foo = crossProject
* lazy val fooJVM = foo.jvm.setting
*/
def uniqueId(compositeProjects: Seq[Project]): Seq[Project] = {
for (p <- compositeProjects.flatMap(_.componentProjects)) yield {
compositeProjects.find(_.id == p.id) match {
case Some(overridingProject) => overridingProject
case None => p
}
}
}
}
sealed trait Project extends ProjectDefinition[ProjectReference] with CompositeProject {
def componentProjects: Seq[Project] = this :: Nil

View File

@ -18,7 +18,9 @@ import sbt.internal.inc.ReflectUtilities
trait BuildDef {
def projectDefinitions(@deprecated("unused", "") baseDirectory: File): Seq[Project] = projects
def projects: Seq[Project] =
ReflectUtilities.allVals[CompositeProject](this).values.toSeq.flatMap(_.componentProjects)
CompositeProject.uniqueId(
ReflectUtilities.allVals[CompositeProject](this).values.toSeq.flatMap(_.componentProjects))
// TODO: Should we grab the build core settings here or in a plugin?
def settings: Seq[Setting[_]] = Defaults.buildCore
def buildLoaders: Seq[BuildLoader.Components] = Nil

View File

@ -151,11 +151,13 @@ private[sbt] object EvaluateConfigurations {
val allGeneratedFiles = (definitions.generated ++ dslEntries.flatMap(_.generated))
loader =>
{
val projects =
definitions.values(loader).flatMap {
val projects = {
val compositeProjects = definitions.values(loader).flatMap {
case p: CompositeProject => p.componentProjects.map(resolveBase(file.getParentFile, _))
case _ => Nil
}
CompositeProject.uniqueId(compositeProjects)
}
val (settingsRaw, manipulationsRaw) =
dslEntries map (_.result apply loader) partition {
case DslEntry.ProjectSettings(_) => true

View File

@ -1,2 +0,0 @@
val aa = taskKey[Unit]("A task in the 'a' project")
aa := println("Hello.")

View File

@ -1,2 +0,0 @@
val h = taskKey[Unit]("A task in project 'b'")
h := println("Hello.")

View File

@ -4,21 +4,29 @@ import sbt.CompositeProject
lazy val check = taskKey[Unit]("check")
// Based on sbt-file-projects test
lazy val cross = new CompositeProject
lazy val foo = new CompositeProject
{
val p1 = Project.apply("a", new File("a"))
val p2 = Project.apply("b", new File("b"))
def componentProjects: Seq[Project] = Seq(p1, p2)
val jvm = Project.apply("jvm", new File("jvm"))
val js = Project.apply("js", new File("js"))
def componentProjects: Seq[Project] = Seq(jvm, js)
}
lazy val fooJVM = foo.jvm
lazy val bar = project
.dependsOn(foo.jvm)
val g = taskKey[Unit]("A task in the root project")
g := println("Hello.")
check := {
val verP1 = (version in cross.p1).?.value
assert (verP1 == Some("0.1.0-SNAPSHOT"))
val verJvm = (version in foo.jvm).?.value
assert (verJvm == Some("0.1.0-SNAPSHOT"))
val verP2 = (version in cross.p2).?.value
assert (verP2 == Some("0.1.0-SNAPSHOT"))
val verFooJvm = (version in fooJVM).?.value
assert (verFooJvm == Some("0.1.0-SNAPSHOT"))
val verJs = (version in foo.js).?.value
assert (verJs == Some("0.1.0-SNAPSHOT"))
}

View File

@ -3,38 +3,30 @@ import sbt.CompositeProject
lazy val check = taskKey[Unit]("check")
lazy val a = (project in file("a"))
.settings(
version := "0.2.0"
)
// Based on sbt-file-projects test
lazy val cross = new CompositeProject
lazy val foo = new CompositeProject
{
val p1 = Project.apply("a", new File("a"))
val p2 = Project.apply("b", new File("b"))
def componentProjects: Seq[Project] = Seq(p1, p2)
val jvm = Project.apply("jvm", new File("jvm"))
val js = Project.apply("js", new File("js"))
def componentProjects: Seq[Project] = Seq(jvm, js)
}
lazy val b = (project in file("b"))
.settings(
version := "0.2.0"
)
lazy val fooJVM = foo.jvm.settings(version := "0.2.0") // this one needs to win
lazy val bar = project
.dependsOn(foo.jvm)
val g = taskKey[Unit]("A task in the root project")
g := println("Hello.")
check := {
val verP1 = (version in cross.p1).?.value
assert (verP1 == Some("0.2.0"))//Some("0.1.0-SNAPSHOT"))
val verJvm = (version in foo.jvm).?.value
assert (verJvm == Some("0.2.0"))
val verP2 = (version in cross.p2).?.value
assert (verP2 == Some("0.1.0-SNAPSHOT"))
val verFooJvm = (version in fooJVM).?.value
assert (verFooJvm == Some("0.2.0"))
val verA = (version in a).?.value
assert (verA == Some("0.2.0"))
val verB = (version in b).?.value
assert (verA == Some("0.2.0"))
val verJs = (version in foo.js).?.value
assert (verJs == Some("0.1.0-SNAPSHOT"))
}

View File

@ -0,0 +1,2 @@
val h = taskKey[Unit]("A task in project 'js'")
h := println("Hello.")

View File

@ -0,0 +1,2 @@
val aa = taskKey[Unit]("A task in the 'jvm' project")
aa := println("Hello.")

View File

@ -1,22 +1,30 @@
> g
-> root/compile
> a/compile
> a/aa
> b/compile
> b/h
> jvm/compile
> jvm/aa
> js/compile
> js/h
> c/compile
> bar/compile
$ copy-file changes/basic.sbt basic.sbt
> reload
> g
> root/compile
> a/compile
> a/aa
> b/compile
> b/h
> jvm/compile
> jvm/aa
> js/compile
> js/h
> c/compile
> bar/compile
> check
$ copy-file changes/shadow.sbt build.sbt
> reload
> jvm/compile
> jvm/aa
> js/compile
> js/h
> c/compile
> bar/compile
> check