From 98bd962952831bbf74e9a9ac71a9107054948f94 Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sun, 27 Feb 2011 16:28:00 -0500 Subject: [PATCH] make "globals" per-build definition --- main/Build.scala | 21 +++++++++++++-------- main/Default.scala | 35 +++++++++++++++-------------------- main/Project.scala | 8 ++++++++ main/Scope.scala | 10 ++++++++-- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/main/Build.scala b/main/Build.scala index c6f67f0a0..a8599122f 100644 --- a/main/Build.scala +++ b/main/Build.scala @@ -10,16 +10,18 @@ package sbt import scala.annotation.tailrec import collection.mutable import Compile.{Compilers,Inputs} - import Project.{ScopedKey, ScopeLocal, Setting} + import Project.{inScope, ScopedKey, ScopeLocal, Setting} import Keys.{AppConfig, Config, ThisProject, ThisProjectRef} import TypeFunctions.{Endo,Id} import tools.nsc.reporters.ConsoleReporter import Build.{analyzed, data} + import Scope.{GlobalScope, ThisScope} // name is more like BuildDefinition, but that is too long trait Build { def projects: Seq[Project] + def settings: Seq[Setting[_]] = Default.buildCore } trait Plugin { @@ -114,8 +116,8 @@ object EvaluateTask private[sbt] val parseResult: TaskKey[_] = TaskKey("$parse-result") def injectSettings: Seq[Project.Setting[_]] = Seq( - (state in Scope.GlobalScope) ::= dummyState, - (streamsManager in Scope.GlobalScope) ::= dummyStreamsManager + (state in GlobalScope) ::= dummyState, + (streamsManager in GlobalScope) ::= dummyStreamsManager ) def dummy[T](name: String): (TaskKey[T], Task[T]) = (TaskKey[T](name), dummyTask(name)) @@ -221,7 +223,7 @@ object Load val compilers = Compile.compilers(state.configuration, log) val evalPluginDef = EvaluateTask.evalPluginDef(log) _ val delegates = memo(defaultDelegates) - val inject: Seq[Project.Setting[_]] = ((AppConfig in Scope.GlobalScope) :== state.configuration) +: EvaluateTask.injectSettings + val inject: Seq[Project.Setting[_]] = ((AppConfig in GlobalScope) :== state.configuration) +: EvaluateTask.injectSettings val config = new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, delegates, EvaluateTask.injectStreams, inject, log) apply(base, state, config) } @@ -312,7 +314,8 @@ object Load // map This to thisScope, Select(p) to mapRef(uri, rootProject, p) transformSettings(projectScope(uri, id), uri, rootProject, settings) } - pluginGlobal ++ projectSettings + val buildScope = ThisScope.copy(project = Select(ProjectRef(Some(uri), None))) + pluginGlobal ++ inScope(buildScope)(build.buildSettings) ++ projectSettings } def transformSettings(thisScope: Scope, uri: URI, rootProject: URI => String, settings: Seq[Setting[_]]): Seq[Setting[_]] = Project.transform(Scope.resolveScope(thisScope, uri, rootProject), settings) @@ -354,8 +357,10 @@ object Load val externals = referenced(defined).toList val projectsInRoot = defined.filter(isRoot).map(_.id) val rootProjects = if(projectsInRoot.isEmpty) defined.head.id :: Nil else projectsInRoot - (new LoadedBuildUnit(unit, defined.map(d => (d.id, d)).toMap, rootProjects), externals) + (new LoadedBuildUnit(unit, defined.map(d => (d.id, d)).toMap, rootProjects, buildSettings(unit)), externals) } + def buildSettings(unit: BuildUnit): Seq[Setting[_]] = + unit.definitions.builds.flatMap(_.settings) @tailrec def loadAll(bases: List[URI], references: Map[URI, List[ProjectRef]], externalLoader: URI => BuildUnit, builds: Map[URI, LoadedBuildUnit]): (Map[URI, List[ProjectRef]], Map[URI, LoadedBuildUnit]) = bases match @@ -419,7 +424,7 @@ object Load { IO.assertAbsolute(uri) val resolve = resolveProject(ref => Scope.mapRef(uri, rootProject, ref)) - new LoadedBuildUnit(unit.unit, unit.defined mapValues resolve, unit.rootProjects) + new LoadedBuildUnit(unit.unit, unit.defined mapValues resolve, unit.rootProjects, unit.buildSettings) } def resolveProject(resolveRef: ProjectRef => ProjectRef): Project => Project = { @@ -557,7 +562,7 @@ object Load } final class LoadedBuild(val root: URI, val units: Map[URI, LoadedBuildUnit]) - final class LoadedBuildUnit(val unit: BuildUnit, val defined: Map[String, Project], val rootProjects: Seq[String]) + final class LoadedBuildUnit(val unit: BuildUnit, val defined: Map[String, Project], val rootProjects: Seq[String], val buildSettings: Seq[Setting[_]]) { assert(!rootProjects.isEmpty, "No root projects defined for build unit " + unit) def localBase = unit.localBase diff --git a/main/Default.scala b/main/Default.scala index d681fa823..018e43010 100755 --- a/main/Default.scala +++ b/main/Default.scala @@ -5,8 +5,8 @@ package sbt import java.io.File import Build.data - import Scope.{GlobalScope,ThisScope} - import Project.{Initialize, ScopedKey, Setting} + import Scope.{GlobalScope, ThisScope} + import Project.{inConfig, Initialize, inScope, inTask, ScopedKey, Setting} import Configurations.{Compile => CompileConf, Test => TestConf} import EvaluateTask.{resolvedScoped, streams} import complete._ @@ -53,19 +53,21 @@ object Default def analysisMap[T](cp: Seq[Attributed[T]]): Map[T, inc.Analysis] = (cp map extractAnalysis).toMap - def core: Seq[Setting[_]] = Seq( - JavaHome in GlobalScope :== None, - OutputStrategy in GlobalScope :== None, - Fork in GlobalScope :== false, - JavaOptions in GlobalScope :== Nil, + def buildCore: Seq[Setting[_]] = inScope(GlobalScope)(Seq( + JavaHome :== None, + OutputStrategy :== None, + Fork :== false, + JavaOptions :== Nil, CrossPaths :== true, - ShellPrompt in GlobalScope :== (_ => "> "), - Aggregate in GlobalScope :== Aggregation.Enabled, - Name <<= ThisProject(_.id), - Version :== "0.1", - MaxErrors in GlobalScope :== 100, + ShellPrompt :== (_ => "> "), + Aggregate :== Aggregation.Enabled, + MaxErrors :== 100, Commands :== Nil, Data <<= EvaluateTask.state map { state => Project.structure(state).data } + )) + def projectCore: Seq[Setting[_]] = Seq( + Name <<= ThisProject(_.id), + Version :== "0.1" ) def paths = Seq( Base <<= ThisProject(_.base), @@ -303,13 +305,6 @@ object Default val CompletionsID = "completions" - def inConfig(conf: Configuration)(ss: Seq[Setting[_]]): Seq[Setting[_]] = - inScope(ThisScope.copy(config = Select(conf)) )( (Config :== conf) +: ss) - def inTask(t: Scoped)(ss: Seq[Setting[_]]): Seq[Setting[_]] = - inScope(ThisScope.copy(task = Select(t.key)) )( ss ) - def inScope(scope: Scope)(ss: Seq[Setting[_]]): Seq[Setting[_]] = - Project.transform(Scope.replaceThis(scope), ss) - lazy val defaultWebPaths = inConfig(CompileConf)(webPaths) def noAggregation = Seq(RunTask, ConsoleTask, ConsoleQuick) @@ -330,7 +325,7 @@ object Default lazy val itSettings = inConfig(Configurations.IntegrationTest)(testSettings) lazy val defaultConfigs = inConfig(CompileConf)(compileSettings) ++ inConfig(TestConf)(testSettings) - lazy val defaultSettings: Seq[Setting[_]] = core ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ defaultConfigs ++ disableAggregation + lazy val defaultSettings: Seq[Setting[_]] = projectCore ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ defaultConfigs ++ disableAggregation lazy val defaultWebSettings = defaultSettings ++ defaultWebPaths ++ defaultWebTasks } object Classpaths diff --git a/main/Project.scala b/main/Project.scala index a731936de..5219ad7c7 100644 --- a/main/Project.scala +++ b/main/Project.scala @@ -8,6 +8,7 @@ package sbt import Project._ import Types.Endo import Keys.{AppConfig, Commands, Config, HistoryPath, ProjectCommand, SessionKey, ShellPrompt, StructureKey, ThisProject, ThisProjectRef, Watch} + import Scope.ThisScope import CommandSupport.logger import compile.Eval @@ -153,6 +154,13 @@ object Project extends Init[Scope] } def reverseDependencies(cMap: CompiledMap, scoped: ScopedKey[_]): Iterable[ScopedKey[_]] = for( (key,compiled) <- cMap; dep <- compiled.dependencies if dep == scoped) yield key + + def inConfig(conf: Configuration)(ss: Seq[Setting[_]]): Seq[Setting[_]] = + inScope(ThisScope.copy(config = Select(conf)) )( (Config :== conf) +: ss) + def inTask(t: Scoped)(ss: Seq[Setting[_]]): Seq[Setting[_]] = + inScope(ThisScope.copy(task = Select(t.key)) )( ss ) + def inScope(scope: Scope)(ss: Seq[Setting[_]]): Seq[Setting[_]] = + Project.transform(Scope.replaceThis(scope), ss) } import SessionSettings._ diff --git a/main/Scope.scala b/main/Scope.scala index 2e73e0ea5..f6a934f15 100644 --- a/main/Scope.scala +++ b/main/Scope.scala @@ -98,10 +98,16 @@ object Scope } yield Scope(Select(proj),c,t,e) val projI = - linearize(scope.project)(projectInherit) map { p => scope.copy(project = p) } + withRawBuilds(linearize(scope.project)(projectInherit)) map { p => scope.copy(project = p) } - (prod ++ projI :+ GlobalScope).toList.removeDuplicates + (prod ++ projI :+ GlobalScope).distinct } + def withRawBuilds(ps: Seq[ScopeAxis[ProjectRef]]): Seq[ScopeAxis[ProjectRef]] = + ps ++ ps.flatMap(rawBuilds).distinct.map(Select.apply) + + def rawBuilds(ps: ScopeAxis[ProjectRef]): Seq[ProjectRef] = ps match { case Select(ref) => rawBuilds(ref); case _ => Nil } + def rawBuilds(ps: ProjectRef): Seq[ProjectRef] = ps.uri.map(uri => ProjectRef(Some(uri), None)).toList + def linearize[T](axis: ScopeAxis[T])(inherit: T => Seq[T]): Seq[ScopeAxis[T]] = axis match {