Ensure precedence of top level Projects over ComponentProjects

This commit is contained in:
Alistair Johnson 2018-04-07 01:04:45 +02:00
parent 03fc4ac686
commit 68c005e4b5
8 changed files with 107 additions and 25 deletions

View File

@ -125,25 +125,35 @@ trait CompositeProject {
def componentProjects: Seq[Project]
}
object CompositeProject {
private[sbt] 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:
* Expand user defined `projects` with the component projects of `compositeProjects`.
*
* If two projects with the same id appear in the user defined `projects` and
* in `compositeProjects.componentProjects`, the one in `projects` wins.
* This is necessary for backward compatibility with the idioms:
* {{{
* lazy val foo = crossProject
* lazy val fooJVM = foo.jvm.setting
* lazy val fooJS = foo.js.settings(...)
* lazy val fooJVM = foo.jvm.settings(...)
* }}}
* and the rarer:
* {{{
* lazy val fooJS = foo.js.settings(...)
* lazy val foo = crossProject
* lazy val fooJVM = foo.jvm.settings(...)
* }}}
*/
def uniqueId(compositeProjects: Seq[Project]): Seq[Project] = {
def expand(projects: Seq[Project], compositeProjects: Seq[CompositeProject]): Seq[Project] = {
for (p <- compositeProjects.flatMap(_.componentProjects)) yield {
compositeProjects.find(_.id == p.id) match {
projects.find(_.id == p.id) match {
case Some(overridingProject) => overridingProject
case None => p
}
}
}
}
sealed trait Project extends ProjectDefinition[ProjectReference] with CompositeProject {

View File

@ -17,10 +17,11 @@ import sbt.internal.inc.ReflectUtilities
trait BuildDef {
def projectDefinitions(@deprecated("unused", "") baseDirectory: File): Seq[Project] = projects
def projects: Seq[Project] =
CompositeProject.uniqueId(
ReflectUtilities.allVals[CompositeProject](this).values.toSeq.flatMap(_.componentProjects))
def projects: Seq[Project] = {
val projects = ReflectUtilities.allVals[Project](this).values.toSeq
val compositeProjects = ReflectUtilities.allVals[CompositeProject](this).values.toSeq
CompositeProject.expand(projects, compositeProjects)
}
// 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

@ -152,11 +152,18 @@ private[sbt] object EvaluateConfigurations {
loader =>
{
val projects = {
val compositeProjects = definitions.values(loader).flatMap {
case p: CompositeProject => p.componentProjects.map(resolveBase(file.getParentFile, _))
case _ => Nil
val projects = definitions.values(loader).collect {
case p: Project => p
}
CompositeProject.uniqueId(compositeProjects)
val compositeProjects = definitions.values(loader).collect {
case p: CompositeProject => p
}
CompositeProject
.expand(projects, compositeProjects)
.map(resolveBase(file.getParentFile, _))
}
val (settingsRaw, manipulationsRaw) =
dslEntries map (_.result apply loader) partition {

View File

@ -0,0 +1,9 @@
[#3042]: https://github.com/sbt/sbt/issues/3042
[#4056]: https://github.com/sbt/sbt/pull/4056
### Introduce CompositeProject
### Improvements
- Support for: `lazy val foo = someCompositeProject` (e.g.`CrossProject`) [#3042][]/[#4056][]

View File

@ -6,11 +6,12 @@ lazy val check = taskKey[Unit]("check")
// Based on sbt-file-projects test
lazy val foo = new CompositeProject
{
val jvm = Project.apply("jvm", new File("jvm"))
val js = Project.apply("js", new File("js"))
val jvm = Project.apply("jvm", new File("jvm")).settings(version := "0.1.0") // this one needs to win
val js = Project.apply("js", new File("js")).settings(version := "0.1.0") // this one needs to win
def componentProjects: Seq[Project] = Seq(jvm, js)
}
lazy val fooJS = foo.js
lazy val fooJVM = foo.jvm
lazy val bar = project
@ -22,11 +23,14 @@ g := println("Hello.")
check := {
val verJvm = (version in foo.jvm).?.value
assert (verJvm == Some("0.1.0-SNAPSHOT"))
assert (verJvm == Some("0.1.0"))
val verFooJvm = (version in fooJVM).?.value
assert (verFooJvm == Some("0.1.0-SNAPSHOT"))
assert (verFooJvm == Some("0.1.0"))
val verJs = (version in foo.js).?.value
assert (verJs == Some("0.1.0-SNAPSHOT"))
assert (verJs == Some("0.1.0"))
val verFooJs = (version in fooJS).?.value
assert (verFooJs == Some("0.1.0"))
}

View File

@ -6,11 +6,12 @@ lazy val check = taskKey[Unit]("check")
// Based on sbt-file-projects test
lazy val foo = new CompositeProject
{
val jvm = Project.apply("jvm", new File("jvm"))
val js = Project.apply("js", new File("js"))
val jvm = Project.apply("jvm", new File("jvm")).settings(version := "0.1.0")
val js = Project.apply("js", new File("js")).settings(version := "0.1.0") // this one needs to win
def componentProjects: Seq[Project] = Seq(jvm, js)
}
lazy val fooJS = foo.js
lazy val fooJVM = foo.jvm.settings(version := "0.2.0") // this one needs to win
lazy val bar = project
@ -28,5 +29,8 @@ check := {
assert (verFooJvm == Some("0.2.0"))
val verJs = (version in foo.js).?.value
assert (verJs == Some("0.1.0-SNAPSHOT"))
assert (verJs == Some("0.1.0"))
val verFooJs = (version in fooJS).?.value
assert (verFooJs == Some("0.1.0"))
}

View File

@ -0,0 +1,37 @@
import sbt.internal.AddSettings
import sbt.CompositeProject
lazy val check = taskKey[Unit]("check")
lazy val fooJS = foo.js.settings(version := "0.2.1") // this one needs to win
// Based on sbt-file-projects test
lazy val foo = new CompositeProject
{
val jvm = Project.apply("jvm", new File("jvm")).settings(version := "0.1.0")
val js = Project.apply("js", new File("js")).settings(version := "0.1.0")
def componentProjects: Seq[Project] = Seq(jvm, js)
}
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 verJvm = (version in foo.jvm).?.value
assert (verJvm == Some("0.2.0"))
val verFooJvm = (version in fooJVM).?.value
assert (verFooJvm == Some("0.2.0"))
val verJs = (version in foo.js).?.value
assert (verJs == Some("0.2.1"))
val verFooJs = (version in fooJS).?.value
assert (verFooJs == Some("0.2.1"))
}

View File

@ -28,3 +28,13 @@ $ copy-file changes/shadow.sbt build.sbt
> c/compile
> bar/compile
> check
$ copy-file changes/shadowLazy.sbt build.sbt
> reload
> jvm/compile
> jvm/aa
> js/compile
> js/h
> c/compile
> bar/compile
> check