mirror of https://github.com/sbt/sbt.git
add build level configuration
made ProjectRef semantics explicit
This commit is contained in:
parent
70972c6499
commit
60d9355b54
|
|
@ -14,10 +14,10 @@ package sbt
|
|||
object Act
|
||||
{
|
||||
// this does not take delegation into account
|
||||
def scopedKey(index: KeyIndex, currentBuild: URI, currentProject: String, defaultConfig: ProjectRef => Option[String], keyMap: Map[String, AttributeKey[_]]): Parser[ScopedKey[_]] =
|
||||
def scopedKey(index: KeyIndex, current: ProjectRef, defaultConfig: ProjectRef => Option[String], keyMap: Map[String, AttributeKey[_]]): Parser[ScopedKey[_]] =
|
||||
{
|
||||
for {
|
||||
proj <- optProjectRef(index, currentBuild, currentProject)
|
||||
proj <- optProjectRef(index, current)
|
||||
confAmb <- config( index configs proj )
|
||||
(key, conf) <- key(index, proj, configs(confAmb, defaultConfig, proj), keyMap) }
|
||||
yield
|
||||
|
|
@ -59,10 +59,10 @@ object Act
|
|||
def projectID(uri: URI) = token( examplesStrict(ID, index projects uri) <~ '/' )
|
||||
|
||||
for(uri <- build; id <- projectID(uri)) yield
|
||||
ProjectRef(Some(uri), Some(id))
|
||||
ProjectRef(uri, id)
|
||||
}
|
||||
def optProjectRef(index: KeyIndex, currentBuild: URI, currentProject: String) =
|
||||
projectRef(index, currentBuild) ?? ProjectRef(Some(currentBuild), Some(currentProject))
|
||||
def optProjectRef(index: KeyIndex, current: ProjectRef) =
|
||||
projectRef(index, current.build) ?? current
|
||||
|
||||
def actParser(s: State): Parser[() => State] = requireSession(s, actParser0(s))
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ object Act
|
|||
{
|
||||
import extracted._
|
||||
val defaultConf = (ref: ProjectRef) => if(Project.getProject(ref, structure).isDefined) defaultConfig(structure.data)(ref) else None
|
||||
scopedKey(structure.index.keyIndex, curi, cid, defaultConf, structure.index.keyMap)
|
||||
scopedKey(structure.index.keyIndex, currentRef, defaultConf, structure.index.keyMap)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ package sbt
|
|||
import EvaluateTask.parseResult
|
||||
import Keys.aggregate
|
||||
import sbt.complete.Parser
|
||||
import java.net.URI
|
||||
import Parser._
|
||||
|
||||
sealed trait Aggregation
|
||||
|
|
@ -19,7 +20,7 @@ final object Aggregation
|
|||
val Enabled = new Implicit(true)
|
||||
val Disabled = new Implicit(false)
|
||||
final case class Implicit(enabled: Boolean) extends Aggregation
|
||||
final class Explicit(val dependencies: Seq[ProjectRef], val transitive: Boolean) extends Aggregation
|
||||
final class Explicit(val dependencies: Seq[ProjectReference], val transitive: Boolean) extends Aggregation
|
||||
|
||||
final case class KeyValue[+T](key: ScopedKey[_], value: T)
|
||||
def getTasks[T](key: ScopedKey[T], structure: BuildStructure, transitive: Boolean): Seq[KeyValue[T]] =
|
||||
|
|
@ -29,7 +30,7 @@ final object Aggregation
|
|||
}
|
||||
def projectAggregate(key: ScopedKey[_], structure: BuildStructure): Seq[ProjectRef] =
|
||||
{
|
||||
val project = key.scope.project.toOption.flatMap { p => Project.getProject(p, structure) }
|
||||
val project = key.scope.project.toOption.flatMap { ref => Project.getProjectForReference(ref, structure) }
|
||||
project match { case Some(p) => p.aggregate; case None => Nil }
|
||||
}
|
||||
def aggregateDeps[T](key: ScopedKey[T], structure: BuildStructure): Seq[KeyValue[T]] =
|
||||
|
|
@ -37,24 +38,24 @@ final object Aggregation
|
|||
val aggregated = aggregate in Scope.fillTaskAxis(key.scope, key.key) get structure.data getOrElse Enabled
|
||||
val (agg, transitive) =
|
||||
aggregated match
|
||||
{
|
||||
case Implicit(false) => (Nil, false)
|
||||
case Implicit(true) => (projectAggregate(key, structure), true)
|
||||
case e: Explicit => (subCurrentBuild(key, e.dependencies), e.transitive)
|
||||
{
|
||||
case Implicit(false) => (Nil, false)
|
||||
case Implicit(true) => (projectAggregate(key, structure), true)
|
||||
case e: Explicit => (e.dependencies, e.transitive)
|
||||
}
|
||||
|
||||
val currentBuild = key.scope.project.toOption.flatMap { case ProjectRef(uri, _) => Some(uri); case BuildRef(ref) => Some(ref); case _ => None }
|
||||
agg flatMap { a =>
|
||||
val newKey = ScopedKey(key.scope.copy(project = Select(a)), key.key)
|
||||
val resolved = subCurrentBuild(a, currentBuild)
|
||||
val newKey = ScopedKey(key.scope.copy(project = Select(resolved)), key.key)
|
||||
getTasks(newKey, structure, transitive)
|
||||
}
|
||||
}
|
||||
private def subCurrentBuild(key: ScopedKey[_], refs: Seq[ProjectRef]): Seq[ProjectRef] =
|
||||
key.scope.project match
|
||||
private def subCurrentBuild(ref: Reference, currentBuild: Option[URI]): Reference =
|
||||
currentBuild match
|
||||
{
|
||||
case Select(ProjectRef(Some(current), _)) => refs map { ref => Scope.mapRefBuild(current, ref) }
|
||||
case _ => refs
|
||||
case None => ref
|
||||
case Some(current) => Scope.resolveBuildOnly(current, ref)
|
||||
}
|
||||
|
||||
|
||||
def printSettings[T](xs: Seq[KeyValue[T]], log: Logger) =
|
||||
xs match
|
||||
|
|
|
|||
112
main/Build.scala
112
main/Build.scala
|
|
@ -145,7 +145,7 @@ object EvaluateTask
|
|||
|
||||
def getTask[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, streams: Streams, ref: ProjectRef): Option[(Task[T], Execute.NodeView[Task])] =
|
||||
{
|
||||
val thisScope = Scope(Select(ref), Global, Global, Global)
|
||||
val thisScope = Load.projectScope(ref)
|
||||
val resolvedScope = Scope.replaceThis(thisScope)( taskKey.scope )
|
||||
for( t <- structure.data.get(resolvedScope, taskKey.key)) yield
|
||||
(t, nodeView(state, streams))
|
||||
|
|
@ -229,19 +229,31 @@ object Load
|
|||
}
|
||||
def defaultDelegates: LoadedBuild => Scope => Seq[Scope] = (lb: LoadedBuild) => {
|
||||
val rootProject = getRootProject(lb.units)
|
||||
def resolveRef(project: ProjectRef) = Scope.resolveRef(lb.root, rootProject, project)
|
||||
def resolveRef(project: Reference): ResolvedReference = Scope.resolveReference(lb.root, rootProject, project)
|
||||
Scope.delegates(
|
||||
project => projectInherit(lb, resolveRef(project)),
|
||||
(project, config) => configInherit(lb, resolveRef(project), config),
|
||||
(project, config) => configInherit(lb, resolveRef(project), config, rootProject),
|
||||
(project, task) => Nil,
|
||||
(project, extra) => Nil
|
||||
)
|
||||
}
|
||||
def configInherit(lb: LoadedBuild, ref: (URI, String), config: ConfigKey): Seq[ConfigKey] =
|
||||
getConfiguration(lb.units, ref._1, ref._2, config).extendsConfigs.map(c => ConfigKey(c.name))
|
||||
|
||||
def projectInherit(lb: LoadedBuild, ref: (URI, String)): Seq[ProjectRef] =
|
||||
getProject(lb.units, ref._1, ref._2).delegates
|
||||
def configInherit(lb: LoadedBuild, ref: ResolvedReference, config: ConfigKey, rootProject: URI => String): Seq[ConfigKey] =
|
||||
ref match
|
||||
{
|
||||
case pr: ProjectRef => configInheritRef(lb, pr, config)
|
||||
case BuildRef(uri) => configInheritRef(lb, ProjectRef(uri, rootProject(uri)), config)
|
||||
}
|
||||
def configInheritRef(lb: LoadedBuild, ref: ProjectRef, config: ConfigKey): Seq[ConfigKey] =
|
||||
getConfiguration(lb.units, ref.build, ref.project, config).extendsConfigs.map(c => ConfigKey(c.name))
|
||||
|
||||
def projectInherit(lb: LoadedBuild, ref: ResolvedReference): Seq[ProjectRef] =
|
||||
ref match
|
||||
{
|
||||
case pr: ProjectRef => projectInheritRef(lb, pr)
|
||||
case BuildRef(uri) => Nil
|
||||
}
|
||||
def projectInheritRef(lb: LoadedBuild, ref: ProjectRef): Seq[ProjectRef] =
|
||||
getProject(lb.units, ref.build, ref.project).delegates
|
||||
|
||||
// build, load, and evaluate all units.
|
||||
// 1) Compile all plugin definitions
|
||||
|
|
@ -296,7 +308,7 @@ object Load
|
|||
new BuildStructure(units = structure.units, root = structure.root, settings = newSettings, data = newData, index = newIndex, streams = newStreams, delegates = structure.delegates, scopeLocal = structure.scopeLocal)
|
||||
}
|
||||
|
||||
def isProjectThis(s: Setting[_]) = s.key.scope.project == This
|
||||
def isProjectThis(s: Setting[_]) = s.key.scope.project match { case This | Select(ThisProject) => true; case _ => false }
|
||||
def buildConfigurations(loaded: LoadedBuild, rootProject: URI => String, rootEval: () => Eval): Seq[Setting[_]] =
|
||||
loaded.units.toSeq flatMap { case (uri, build) =>
|
||||
val eval = if(uri == loaded.root) rootEval else lazyEval(build.unit)
|
||||
|
|
@ -304,7 +316,7 @@ object Load
|
|||
val (pluginThisProject, pluginGlobal) = pluginSettings partition isProjectThis
|
||||
val projectSettings = build.defined flatMap { case (id, project) =>
|
||||
val srcs = configurationSources(project.base)
|
||||
val ref = ProjectRef(Some(uri), Some(id))
|
||||
val ref = ProjectRef(uri, id)
|
||||
val defineConfig = for(c <- project.configurations) yield ( (configuration in (ref, ConfigKey(c.name))) :== c)
|
||||
val settings =
|
||||
(thisProject :== project) +:
|
||||
|
|
@ -312,15 +324,14 @@ object Load
|
|||
(defineConfig ++ project.settings ++ pluginThisProject ++ configurations(srcs, eval, build.imports))
|
||||
|
||||
// map This to thisScope, Select(p) to mapRef(uri, rootProject, p)
|
||||
transformSettings(projectScope(uri, id), uri, rootProject, settings)
|
||||
transformSettings(projectScope(ref), uri, rootProject, settings)
|
||||
}
|
||||
val buildScope = ThisScope.copy(project = Select(ProjectRef(Some(uri), None)))
|
||||
val buildScope = Scope(Select(BuildRef(uri)), Global, Global, Global)
|
||||
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)
|
||||
def projectScope(uri: URI, id: String): Scope = projectScope(ProjectRef(uri, id))
|
||||
def projectScope(project: ProjectRef): Scope = Scope(Select(project), Global, Global, Global)
|
||||
def projectScope(project: Reference): Scope = Scope(Select(project), Global, Global, Global)
|
||||
|
||||
|
||||
def lazyEval(unit: BuildUnit): () => Eval =
|
||||
|
|
@ -335,17 +346,17 @@ object Load
|
|||
def configurations(srcs: Seq[File], eval: () => Eval, imports: Seq[String]): Seq[Setting[_]] =
|
||||
if(srcs.isEmpty) Nil else EvaluateConfigurations(eval(), srcs, imports)
|
||||
|
||||
def load(file: File, s: State, config: LoadBuildConfiguration): LoadedBuild =
|
||||
def load(file: File, s: State, config: LoadBuildConfiguration): PartBuild =
|
||||
load(file, uri => loadUnit(uri, RetrieveUnit(config.stagingDirectory, uri), s, config) )
|
||||
def load(file: File, loader: URI => BuildUnit): LoadedBuild = loadURI(IO.directoryURI(file), loader)
|
||||
def loadURI(uri: URI, loader: URI => BuildUnit): LoadedBuild =
|
||||
def load(file: File, loader: URI => BuildUnit): PartBuild = loadURI(IO.directoryURI(file), loader)
|
||||
def loadURI(uri: URI, loader: URI => BuildUnit): PartBuild =
|
||||
{
|
||||
IO.assertAbsolute(uri)
|
||||
val (referenced, map) = loadAll(uri :: Nil, Map.empty, loader, Map.empty)
|
||||
checkAll(referenced, map)
|
||||
new LoadedBuild(uri, map)
|
||||
new PartBuild(uri, map)
|
||||
}
|
||||
def loaded(unit: BuildUnit): (LoadedBuildUnit, List[ProjectRef]) =
|
||||
def loaded(unit: BuildUnit): (PartBuildUnit, List[ProjectReference]) =
|
||||
{
|
||||
val defined = projects(unit)
|
||||
if(defined.isEmpty) error("No projects defined in build unit " + unit)
|
||||
|
|
@ -357,12 +368,12 @@ 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, buildSettings(unit)), externals)
|
||||
(new PartBuildUnit(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]) =
|
||||
@tailrec def loadAll(bases: List[URI], references: Map[URI, List[ProjectReference]], externalLoader: URI => BuildUnit, builds: Map[URI, PartBuildUnit]): (Map[URI, List[ProjectReference]], Map[URI, PartBuildUnit]) =
|
||||
bases match
|
||||
{
|
||||
case b :: bs =>
|
||||
|
|
@ -371,8 +382,8 @@ object Load
|
|||
else
|
||||
{
|
||||
val (loadedBuild, refs) = loaded(externalLoader(b))
|
||||
checkBuildBase(loadedBuild.localBase)
|
||||
loadAll(refs.flatMap(_.uri) reverse_::: bs, references.updated(b, refs), externalLoader, builds.updated(b, loadedBuild))
|
||||
checkBuildBase(loadedBuild.unit.localBase)
|
||||
loadAll(refs.flatMap(Reference.uri) reverse_::: bs, references.updated(b, refs), externalLoader, builds.updated(b, loadedBuild))
|
||||
}
|
||||
case Nil => (references, builds)
|
||||
}
|
||||
|
|
@ -390,12 +401,19 @@ object Load
|
|||
else if(!base.exists)
|
||||
IO createDirectory base
|
||||
}
|
||||
def checkAll(referenced: Map[URI, List[ProjectRef]], builds: Map[URI, LoadedBuildUnit])
|
||||
def resolveAll(builds: Map[URI, PartBuildUnit]): Map[URI, LoadedBuildUnit] =
|
||||
{
|
||||
val rootProject = getRootProject(builds)
|
||||
builds map { case (uri,unit) =>
|
||||
(uri, unit.resolveRefs( ref => Scope.resolveProjectRef(uri, rootProject, ref) ))
|
||||
} toMap;
|
||||
}
|
||||
def checkAll(referenced: Map[URI, List[ProjectReference]], builds: Map[URI, PartBuildUnit])
|
||||
{
|
||||
val rootProject = getRootProject(builds)
|
||||
for( (uri, refs) <- referenced; ref <- refs)
|
||||
{
|
||||
val (refURI, refID) = Scope.resolveRef(uri, rootProject, ref)
|
||||
val ProjectRef(refURI, refID) = Scope.resolveProjectRef(uri, rootProject, ref)
|
||||
val loadedUnit = builds(refURI)
|
||||
if(! (loadedUnit.defined contains refID) )
|
||||
error("No project '" + refID + "' in '" + refURI + "'")
|
||||
|
|
@ -412,42 +430,36 @@ object Load
|
|||
}
|
||||
p => p.copy(base = resolve(p.base))
|
||||
}
|
||||
def resolveProjects(loaded: LoadedBuild): LoadedBuild =
|
||||
def resolveProjects(loaded: PartBuild): LoadedBuild =
|
||||
{
|
||||
val rootProject = getRootProject(loaded.units)
|
||||
new LoadedBuild(loaded.root, loaded.units.map { case (uri, unit) =>
|
||||
new LoadedBuild(loaded.root, loaded.units map { case (uri, unit) =>
|
||||
IO.assertAbsolute(uri)
|
||||
(uri, resolveProjects(uri, unit, rootProject))
|
||||
})
|
||||
}
|
||||
def resolveProjects(uri: URI, unit: LoadedBuildUnit, rootProject: URI => String): LoadedBuildUnit =
|
||||
def resolveProjects(uri: URI, unit: PartBuildUnit, rootProject: URI => String): LoadedBuildUnit =
|
||||
{
|
||||
IO.assertAbsolute(uri)
|
||||
val resolve = resolveProject(ref => Scope.mapRef(uri, rootProject, ref))
|
||||
val resolve = (_: Project).resolve(ref => Scope.resolveProjectRef(uri, rootProject, ref))
|
||||
new LoadedBuildUnit(unit.unit, unit.defined mapValues resolve, unit.rootProjects, unit.buildSettings)
|
||||
}
|
||||
def resolveProject(resolveRef: ProjectRef => ProjectRef): Project => Project =
|
||||
{
|
||||
def resolveRefs(prs: Seq[ProjectRef]) = prs map resolveRef
|
||||
def resolveDeps(ds: Seq[Project.ClasspathDependency]) = ds map resolveDep
|
||||
def resolveDep(d: Project.ClasspathDependency) = d.copy(project = resolveRef(d.project))
|
||||
p => p.copy(aggregate = resolveRefs(p.aggregate), dependencies = resolveDeps(p.dependencies), delegates = resolveRefs(p.delegates))
|
||||
}
|
||||
def projects(unit: BuildUnit): Seq[Project] =
|
||||
{
|
||||
// we don't have the complete build graph loaded, so we don't have the rootProject function yet.
|
||||
// Therefore, we use mapRefBuild instead of mapRef. After all builds are loaded, we can fully resolve ProjectRefs.
|
||||
val resolve = resolveProject(ref => Scope.mapRefBuild(unit.uri, ref)) compose resolveBase(unit.localBase)
|
||||
// Therefore, we use resolveProjectBuild instead of resolveProjectRef. After all builds are loaded, we can fully resolve ProjectReferences.
|
||||
val resolveBuild = (_: Project).resolveBuild(ref => Scope.resolveProjectBuild(unit.uri, ref))
|
||||
val resolve = resolveBuild compose resolveBase(unit.localBase)
|
||||
unit.definitions.builds.flatMap(_.projects map resolve)
|
||||
}
|
||||
def getRootProject(map: Map[URI, LoadedBuildUnit]): URI => String =
|
||||
def getRootProject(map: Map[URI, BuildUnitBase]): URI => String =
|
||||
uri => getBuild(map, uri).rootProjects.headOption getOrElse emptyBuild(uri)
|
||||
def getConfiguration(map: Map[URI, LoadedBuildUnit], uri: URI, id: String, conf: ConfigKey): Configuration =
|
||||
getProject(map, uri, id).configurations.find(_.name == conf.name) getOrElse noConfiguration(uri, id, conf.name)
|
||||
|
||||
def getProject(map: Map[URI, LoadedBuildUnit], uri: URI, id: String): Project =
|
||||
def getProject(map: Map[URI, LoadedBuildUnit], uri: URI, id: String): ResolvedProject =
|
||||
getBuild(map, uri).defined.getOrElse(id, noProject(uri, id))
|
||||
def getBuild(map: Map[URI, LoadedBuildUnit], uri: URI): LoadedBuildUnit =
|
||||
def getBuild[T](map: Map[URI, T], uri: URI): T =
|
||||
map.getOrElse(uri, noBuild(uri))
|
||||
|
||||
def emptyBuild(uri: URI) = error("No root project defined for build unit '" + uri + "'")
|
||||
|
|
@ -562,7 +574,14 @@ 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], val buildSettings: Seq[Setting[_]])
|
||||
final class PartBuild(val root: URI, val units: Map[URI, PartBuildUnit])
|
||||
sealed trait BuildUnitBase { def rootProjects: Seq[String]; def buildSettings: Seq[Setting[_]] }
|
||||
final class PartBuildUnit(val unit: BuildUnit, val defined: Map[String, Project], val rootProjects: Seq[String], val buildSettings: Seq[Setting[_]]) extends BuildUnitBase
|
||||
{
|
||||
def resolve(f: Project => ResolvedProject): LoadedBuildUnit = new LoadedBuildUnit(unit, defined mapValues f, rootProjects, buildSettings)
|
||||
def resolveRefs(f: ProjectReference => ProjectRef): LoadedBuildUnit = resolve(_ resolve f)
|
||||
}
|
||||
final class LoadedBuildUnit(val unit: BuildUnit, val defined: Map[String, ResolvedProject], val rootProjects: Seq[String], val buildSettings: Seq[Setting[_]]) extends BuildUnitBase
|
||||
{
|
||||
assert(!rootProjects.isEmpty, "No root projects defined for build unit " + unit)
|
||||
def localBase = unit.localBase
|
||||
|
|
@ -573,10 +592,7 @@ object Load
|
|||
}
|
||||
def getImports(unit: BuildUnit) = baseImports ++ importAll(unit.plugins.pluginNames ++ unit.definitions.buildNames)
|
||||
|
||||
// these are unresolved references
|
||||
def referenced(definitions: Seq[Project]): Seq[ProjectRef] = definitions flatMap referenced
|
||||
def referenced(definition: Project): Seq[ProjectRef] = definition.delegates ++ definition.aggregate ++ definition.dependencies.map(_.project)
|
||||
|
||||
def referenced[PR <: ProjectReference](definitions: Seq[ProjectDefinition[PR]]): Seq[PR] = definitions flatMap { _.referenced }
|
||||
|
||||
final class BuildStructure(val units: Map[URI, LoadedBuildUnit], val root: URI, val settings: Seq[Setting[_]], val data: Settings[Scope], val index: StructureIndex, val streams: Streams, val delegates: Scope => Seq[Scope], val scopeLocal: ScopeLocal)
|
||||
final class LoadBuildConfiguration(val stagingDirectory: File, val classpath: Seq[File], val loader: ClassLoader, val compilers: Compilers, val evalPluginDef: (BuildStructure, State) => Seq[Attributed[File]], val delegates: LoadedBuild => Scope => Seq[Scope], val scopeLocal: ScopeLocal, val injectSettings: Seq[Setting[_]], val log: Logger)
|
||||
|
|
@ -598,6 +614,7 @@ object BuildStreams
|
|||
type Streams = std.Streams[ScopedKey[_]]
|
||||
type TaskStreams = std.TaskStreams[ScopedKey[_]]
|
||||
val GlobalPath = "$global"
|
||||
val BuildUnitPath = "$build"
|
||||
|
||||
def mkStreams(units: Map[URI, LoadedBuildUnit], root: URI, data: Settings[Scope], logRelativePath: Seq[String] = defaultLogPath): Streams =
|
||||
std.Streams( path(units, root, logRelativePath), display, LogManager.construct(data) )
|
||||
|
|
@ -631,7 +648,8 @@ object BuildStreams
|
|||
scoped.scope.project match
|
||||
{
|
||||
case Global => (units(root).localBase, GlobalPath :: Nil)
|
||||
case Select(ProjectRef(Some(uri), Some(id))) => (units(uri).defined(id).base, Nil)
|
||||
case Select(BuildRef(uri)) => (units(uri).localBase, BuildUnitPath :: Nil)
|
||||
case Select(ProjectRef(uri, id)) => (units(uri).defined(id).base, Nil)
|
||||
case Select(pr) => error("Unresolved project reference (" + pr + ") in " + display(scoped))
|
||||
case This => error("Unresolved project reference (This) in " + display(scoped))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ object Default
|
|||
fork :== false,
|
||||
javaOptions :== Nil,
|
||||
crossPaths :== true,
|
||||
shellPrompt :== (_ => "> "),
|
||||
// shellPrompt :== (_ => "> "),
|
||||
aggregate :== Aggregation.Enabled,
|
||||
maxErrors :== 100,
|
||||
commands :== Nil,
|
||||
|
|
@ -281,7 +281,7 @@ object Default
|
|||
def discoverMainClasses(analysis: inc.Analysis): Seq[String] =
|
||||
Discovery.applications(Test.allDefs(analysis)) collect { case (definition, discovered) if(discovered.hasMain) => definition.name }
|
||||
|
||||
def consoleProjectTask = (EvaluateTask.state, streams, initialCommands in consoleProject) map { (state, s, extra) => Console.sbt(state, extra)(s.log) }
|
||||
def consoleProjectTask = (EvaluateTask.state, streams, initialCommands in consoleProject) map { (state, s, extra) => Console.sbt(state, extra)(s.log); println() }
|
||||
def consoleTask: Initialize[Task[Unit]] = consoleTask(fullClasspath, console)
|
||||
def consoleQuickTask = consoleTask(externalDependencyClasspath, consoleQuick)
|
||||
def consoleTask(classpath: TaskKey[Classpath], task: TaskKey[_]): Initialize[Task[Unit]] = (compilers, classpath, scalacOptions in task, initialCommands in task, streams) map {
|
||||
|
|
@ -341,14 +341,14 @@ object Default
|
|||
}
|
||||
def inAllDeps[T](base: ProjectRef, deps: ProjectRef => Seq[ProjectRef], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
|
||||
inAllProjects(Dag.topologicalSort(base)(deps), key, data)
|
||||
def inAllProjects[T](allProjects: Seq[ProjectRef], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
|
||||
def inAllProjects[T](allProjects: Seq[Reference], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
|
||||
allProjects.flatMap { p => key in p get data }
|
||||
|
||||
val CompletionsID = "completions"
|
||||
|
||||
lazy val defaultWebPaths = inConfig(CompileConf)(webPaths)
|
||||
|
||||
def noAggregation = Seq(run, console, consoleQuick)
|
||||
def noAggregation = Seq(run, console, consoleQuick, consoleProject)
|
||||
lazy val disableAggregation = noAggregation map disableAggregate
|
||||
def disableAggregate(k: Scoped) =
|
||||
aggregate in Scope.GlobalScope.copy(task = Select(k.key)) :== false
|
||||
|
|
@ -519,11 +519,11 @@ object Classpaths
|
|||
|
||||
def depMap: Initialize[Task[Map[ModuleRevisionId, ModuleDescriptor]]] =
|
||||
(thisProject, thisProjectRef, settings) flatMap { (root, rootRef, data) =>
|
||||
val dependencies = (p: (ProjectRef, Project)) => p._2.dependencies.flatMap(pr => thisProject in pr.project get data map { (pr.project, _) })
|
||||
val dependencies = (p: (ProjectRef, ResolvedProject)) => p._2.dependencies.flatMap(pr => thisProject in pr.project get data map { (pr.project, _) })
|
||||
depMap(Dag.topologicalSort((rootRef,root))(dependencies).dropRight(1), data)
|
||||
}
|
||||
|
||||
def depMap(projects: Seq[(ProjectRef,Project)], data: Settings[Scope]): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
||||
def depMap(projects: Seq[(ProjectRef,ResolvedProject)], data: Settings[Scope]): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
||||
projects.flatMap { case (p,_) => ivyModule in p get data }.join.map { mods =>
|
||||
(mods.map{ mod =>
|
||||
val md = mod.moduleDescriptor
|
||||
|
|
@ -547,17 +547,17 @@ object Classpaths
|
|||
|
||||
import java.util.LinkedHashSet
|
||||
import collection.JavaConversions.asScalaSet
|
||||
def interSort(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope]): Seq[(ProjectRef,String)] =
|
||||
def interSort(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Seq[(ProjectRef,String)] =
|
||||
{
|
||||
val visited = asScalaSet(new LinkedHashSet[(ProjectRef,String)])
|
||||
def visit(p: ProjectRef, project: Project, c: Configuration)
|
||||
def visit(p: ProjectRef, project: ResolvedProject, c: Configuration)
|
||||
{
|
||||
val applicableConfigs = allConfigs(c)
|
||||
for(ac <- applicableConfigs) // add all configurations in this project
|
||||
visited add (p, ac.name)
|
||||
val masterConfs = configurationNames(project)
|
||||
|
||||
for( Project.ClasspathDependency(dep, confMapping) <- project.dependencies)
|
||||
for( Project.ResolvedClasspathDependency(dep, confMapping) <- project.dependencies)
|
||||
{
|
||||
val depProject = thisProject in dep get data getOrElse error("Invalid project: " + dep)
|
||||
val mapping = mapped(confMapping, masterConfs, configurationNames(depProject), "compile", "*->compile")
|
||||
|
|
@ -573,17 +573,17 @@ object Classpaths
|
|||
visit(projectRef, project, conf)
|
||||
visited.toSeq
|
||||
}
|
||||
def unmanagedDependencies0(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
||||
def unmanagedDependencies0(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
||||
interDependencies(projectRef, project, conf, data, true, unmanagedLibs)
|
||||
def internalDependencies0(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
||||
def internalDependencies0(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
|
||||
interDependencies(projectRef, project, conf, data, false, productsTask)
|
||||
def interDependencies(projectRef: ProjectRef, project: Project, conf: Configuration, data: Settings[Scope], includeSelf: Boolean,
|
||||
def interDependencies(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope], includeSelf: Boolean,
|
||||
f: (ProjectRef, String, Settings[Scope]) => Task[Classpath]): Task[Classpath] =
|
||||
{
|
||||
val visited = interSort(projectRef, project, conf, data)
|
||||
val tasks = asScalaSet(new LinkedHashSet[Task[Classpath]])
|
||||
for( (dep, c) <- visited )
|
||||
if(includeSelf || (dep != projectRef) || conf.name != c )
|
||||
if(includeSelf || (dep != projectRef) || conf.name != c )
|
||||
tasks += f(dep, c, data)
|
||||
|
||||
(tasks.toSeq.join).map(_.flatten.distinct)
|
||||
|
|
@ -611,7 +611,7 @@ object Classpaths
|
|||
def union[A,B](maps: Seq[A => Seq[B]]): A => Seq[B] =
|
||||
a => (Seq[B]() /: maps) { _ ++ _(a) } distinct;
|
||||
|
||||
def configurationNames(p: Project): Seq[String] = p.configurations.map( _.name)
|
||||
def configurationNames(p: ResolvedProject): Seq[String] = p.configurations.map( _.name)
|
||||
def parseList(s: String, allConfs: Seq[String]): Seq[String] = (trim(s split ",") flatMap replaceWildcard(allConfs)).distinct
|
||||
def replaceWildcard(allConfs: Seq[String])(conf: String): Seq[String] =
|
||||
if(conf == "") Nil else if(conf == "*") allConfs else conf :: Nil
|
||||
|
|
@ -622,15 +622,15 @@ object Classpaths
|
|||
def allConfigs(conf: Configuration): Seq[Configuration] =
|
||||
Dag.topologicalSort(conf)(_.extendsConfigs)
|
||||
|
||||
def getConfiguration(ref: ProjectRef, dep: Project, conf: String): Configuration =
|
||||
def getConfiguration(ref: ProjectRef, dep: ResolvedProject, conf: String): Configuration =
|
||||
dep.configurations.find(_.name == conf) getOrElse missingConfiguration(Project display ref, conf)
|
||||
def productsTask(dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
|
||||
def productsTask(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
||||
getClasspath(products, dep, conf, data)
|
||||
def unmanagedLibs(dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
|
||||
def unmanagedLibs(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
||||
getClasspath(unmanagedJars, dep, conf, data)
|
||||
def getClasspath(key: TaskKey[Classpath], dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
|
||||
def getClasspath(key: TaskKey[Classpath], dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
|
||||
( key in (dep, ConfigKey(conf)) ) get data getOrElse const(Nil)
|
||||
def defaultConfigurationTask(p: ProjectRef, data: Settings[Scope]): Configuration =
|
||||
def defaultConfigurationTask(p: ResolvedReference, data: Settings[Scope]): Configuration =
|
||||
flatten(defaultConfiguration in p get data) getOrElse Configurations.Default
|
||||
def flatten[T](o: Option[Option[T]]): Option[T] = o flatMap identity
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ object KeyIndex
|
|||
def combine(indices: Seq[KeyIndex]): KeyIndex = new KeyIndex {
|
||||
def buildURIs = concat(_.buildURIs)
|
||||
def projects(uri: URI) = concat(_.projects(uri))
|
||||
def configs(proj: ProjectRef) = concat(_.configs(proj))
|
||||
def keys(proj: ProjectRef, conf: Option[String]) = concat(_.keys(proj, conf))
|
||||
def configs(proj: ResolvedReference) = concat(_.configs(proj))
|
||||
def keys(proj: ResolvedReference, conf: Option[String]) = concat(_.keys(proj, conf))
|
||||
def concat[T](f: KeyIndex => Set[T]): Set[T] =
|
||||
(Set.empty[T] /: indices)( (s,k) => s ++ f(k) )
|
||||
}
|
||||
|
|
@ -25,25 +25,25 @@ trait KeyIndex
|
|||
{
|
||||
def buildURIs: Set[URI]
|
||||
def projects(uri: URI): Set[String]
|
||||
def configs(proj: ProjectRef): Set[String]
|
||||
def keys(proj: ProjectRef, conf: Option[String]): Set[String]
|
||||
def configs(proj: ResolvedReference): Set[String]
|
||||
def keys(proj: ResolvedReference, conf: Option[String]): Set[String]
|
||||
}
|
||||
trait ExtendableKeyIndex extends KeyIndex
|
||||
{
|
||||
def add(scoped: ScopedKey[_]): ExtendableKeyIndex
|
||||
}
|
||||
private final class KeyIndex0(val data: Map[URI, Map[String, Map[ Option[String], Set[String]] ]]) extends ExtendableKeyIndex
|
||||
private final class KeyIndex0(val data: Map[URI, Map[Option[String], Map[ Option[String], Set[String]] ]]) extends ExtendableKeyIndex
|
||||
{
|
||||
def buildURIs: Set[URI] = data.keys.toSet
|
||||
def projects(uri: URI): Set[String] = get(data, uri).keys.toSet
|
||||
def configs(project: ProjectRef): Set[String] = confMap(project).keys.flatten.toSet
|
||||
def keys(project: ProjectRef, conf: Option[String]): Set[String] = get(confMap(project), conf)
|
||||
def projects(uri: URI): Set[String] = get(data, uri).keys.flatten.toSet
|
||||
def configs(project: ResolvedReference): Set[String] = confMap(project).keys.flatten.toSet
|
||||
def keys(project: ResolvedReference, conf: Option[String]): Set[String] = get(confMap(project), conf)
|
||||
|
||||
def confMap(proj: ProjectRef): Map[Option[String], Set[String]] =
|
||||
def confMap(proj: ResolvedReference): Map[Option[String], Set[String]] =
|
||||
proj match
|
||||
{
|
||||
case ProjectRef(Some(uri), Some(id)) => get( get(data, uri), id)
|
||||
case _ => Map.empty
|
||||
case ProjectRef(uri, id) => get( get(data, uri), Some(id))
|
||||
case BuildRef(uri) => get( get(data, uri), None)
|
||||
}
|
||||
|
||||
private[this] def get[A,B,C](m: Map[A,Map[B,C]], key: A): Map[B,C] = getOr(m, key, Map.empty)
|
||||
|
|
@ -53,12 +53,18 @@ private final class KeyIndex0(val data: Map[URI, Map[String, Map[ Option[String]
|
|||
def add(scoped: ScopedKey[_]): ExtendableKeyIndex =
|
||||
scoped.scope match
|
||||
{
|
||||
case Scope(Select(ProjectRef(Some(uri), Some(id))), config, _, _) => add(uri, id, config, scoped.key)
|
||||
case Scope(Select(ref: ResolvedReference), config, _, _) => addRef(ref, config, scoped.key)
|
||||
case _ => this
|
||||
}
|
||||
def add(uri: URI, id: String, config: ScopeAxis[ConfigKey], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
def addRef(ref: ResolvedReference, config: ScopeAxis[ConfigKey], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
ref match
|
||||
{
|
||||
case BuildRef(uri) => add(uri, None, config, key)
|
||||
case ProjectRef(uri, id) => add(uri, Some(id), config, key)
|
||||
}
|
||||
def add(uri: URI, id: Option[String], config: ScopeAxis[ConfigKey], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
add(uri, id, config match { case Select(c) => Some(c.name); case _ => None }, key)
|
||||
def add(uri: URI, id: String, config: Option[String], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
def add(uri: URI, id: Option[String], config: Option[String], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
{
|
||||
val projectMap = get(data, uri)
|
||||
val configMap = get(projectMap, id)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ object Keys
|
|||
val sessionSettings = AttributeKey[SessionSettings]("session-settings")
|
||||
val buildStructure = AttributeKey[Load.BuildStructure]("build-structure")
|
||||
val appConfiguration = SettingKey[xsbti.AppConfiguration]("app-configuration")
|
||||
val thisProject = SettingKey[Project]("this-project")
|
||||
val thisProject = SettingKey[ResolvedProject]("this-project")
|
||||
val thisProjectRef = SettingKey[ProjectRef]("this-project-ref")
|
||||
val configuration = SettingKey[Configuration]("configuration")
|
||||
val commands = SettingKey[Seq[Command]]("commands")
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ object BuiltinCommands
|
|||
val extracted = Project extract s
|
||||
import extracted._
|
||||
val setting = EvaluateConfigurations.evaluateSetting(session.currentEval(), "<set>", imports(extracted), arg, 0)
|
||||
val append = Load.transformSettings(Load.projectScope(curi, cid), curi, rootProject, setting :: Nil)
|
||||
val append = Load.transformSettings(Load.projectScope(currentRef), curi, rootProject, setting :: Nil)
|
||||
val newSession = session.appendSettings( append map (a => (a, arg)))
|
||||
reapply(newSession, structure, s)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,30 +12,60 @@ package sbt
|
|||
import CommandSupport.logger
|
||||
import compiler.Eval
|
||||
|
||||
final case class Project(id: String, base: File, aggregate: Seq[ProjectRef] = Nil, dependencies: Seq[Project.ClasspathDependency] = Nil, delegates: Seq[ProjectRef] = Nil,
|
||||
settings: Seq[Project.Setting[_]] = Project.defaultSettings, configurations: Seq[Configuration] = Configurations.default)
|
||||
sealed trait ProjectDefinition[PR <: ProjectReference]
|
||||
{
|
||||
def id: String
|
||||
def base: File
|
||||
def configurations: Seq[Configuration]
|
||||
def settings: Seq[Project.Setting[_]]
|
||||
def aggregate: Seq[PR]
|
||||
def delegates: Seq[PR]
|
||||
def dependencies: Seq[Project.ClasspathDep[PR]]
|
||||
def uses: Seq[PR] = aggregate ++ dependencies.map(_.project)
|
||||
def referenced: Seq[PR] = delegates ++ uses
|
||||
}
|
||||
final case class ResolvedProject(id: String, base: File, aggregate: Seq[ProjectRef], dependencies: Seq[Project.ResolvedClasspathDependency], delegates: Seq[ProjectRef],
|
||||
settings: Seq[Project.Setting[_]], configurations: Seq[Configuration]) extends ProjectDefinition[ProjectRef]
|
||||
|
||||
final case class Project(id: String, base: File, aggregate: Seq[ProjectReference] = Nil, dependencies: Seq[Project.ClasspathDependency] = Nil, delegates: Seq[ProjectReference] = Nil,
|
||||
settings: Seq[Project.Setting[_]] = Project.defaultSettings, configurations: Seq[Configuration] = Configurations.default) extends ProjectDefinition[ProjectReference]
|
||||
{
|
||||
def dependsOn(deps: Project.ClasspathDependency*): Project = copy(dependencies = dependencies ++ deps)
|
||||
def delegates(from: ProjectRef*): Project = copy(delegates = delegates ++ from)
|
||||
def aggregate(refs: ProjectRef*): Project = copy(aggregate = aggregate ++ refs)
|
||||
def delegates(from: ProjectReference*): Project = copy(delegates = delegates ++ from)
|
||||
def aggregate(refs: ProjectReference*): Project = copy(aggregate = aggregate ++ refs)
|
||||
def configs(cs: Configuration*): Project = copy(configurations = configurations ++ cs)
|
||||
def settings(ss: Project.Setting[_]*): Project = copy(settings = settings ++ ss)
|
||||
|
||||
def uses = aggregate ++ dependencies.map(_.project)
|
||||
def resolve(resolveRef: ProjectReference => ProjectRef): ResolvedProject =
|
||||
{
|
||||
def resolveRefs(prs: Seq[ProjectReference]) = prs map resolveRef
|
||||
def resolveDeps(ds: Seq[Project.ClasspathDependency]) = ds map resolveDep
|
||||
def resolveDep(d: Project.ClasspathDependency) = Project.ResolvedClasspathDependency(resolveRef(d.project), d.configuration)
|
||||
ResolvedProject(id, base, aggregate = resolveRefs(aggregate), dependencies = resolveDeps(dependencies), delegates = resolveRefs(delegates), settings, configurations)
|
||||
}
|
||||
def resolveBuild(resolveRef: ProjectReference => ProjectReference): Project =
|
||||
{
|
||||
def resolveRefs(prs: Seq[ProjectReference]) = prs map resolveRef
|
||||
def resolveDeps(ds: Seq[Project.ClasspathDependency]) = ds map resolveDep
|
||||
def resolveDep(d: Project.ClasspathDependency) = Project.ClasspathDependency(resolveRef(d.project), d.configuration)
|
||||
copy(aggregate = resolveRefs(aggregate), dependencies = resolveDeps(dependencies), delegates = resolveRefs(delegates))
|
||||
}
|
||||
}
|
||||
final case class Extracted(structure: Load.BuildStructure, session: SessionSettings, curi: URI, cid: String, rootProject: URI => String)
|
||||
final case class Extracted(structure: Load.BuildStructure, session: SessionSettings, currentRef: ProjectRef, rootProject: URI => String)
|
||||
{
|
||||
lazy val currentUnit = structure units curi
|
||||
lazy val currentProject = currentUnit defined cid
|
||||
lazy val currentRef = ProjectRef(Some(curi), Some(cid))
|
||||
def curi = currentRef.build
|
||||
def cid = currentRef.project
|
||||
}
|
||||
|
||||
object Project extends Init[Scope]
|
||||
{
|
||||
def defaultSettings: Seq[Setting[_]] = Default.defaultSettings
|
||||
|
||||
final case class ClasspathDependency(project: ProjectRef, configuration: Option[String])
|
||||
final class Constructor(p: ProjectRef) {
|
||||
sealed trait ClasspathDep[PR <: ProjectReference] { def project: PR; def configuration: Option[String] }
|
||||
final case class ResolvedClasspathDependency(project: ProjectRef, configuration: Option[String]) extends ClasspathDep[ProjectRef]
|
||||
final case class ClasspathDependency(project: ProjectReference, configuration: Option[String]) extends ClasspathDep[ProjectReference]
|
||||
final class Constructor(p: ProjectReference) {
|
||||
def %(conf: String): ClasspathDependency = new ClasspathDependency(p, Some(conf))
|
||||
}
|
||||
|
||||
|
|
@ -45,16 +75,14 @@ object Project extends Init[Scope]
|
|||
def extract(state: State): Extracted =
|
||||
{
|
||||
val se = session(state)
|
||||
val (curi, cid) = se.current
|
||||
val st = structure(state)
|
||||
Extracted(st, se, curi, cid, Load.getRootProject(st.units))
|
||||
Extracted(st, se, se.current, Load.getRootProject(st.units))
|
||||
}
|
||||
|
||||
def getProject(ref: ProjectRef, structure: Load.BuildStructure): Option[Project] =
|
||||
ref match {
|
||||
case ProjectRef(Some(uri), Some(id)) => (structure.units get uri).flatMap(_.defined get id)
|
||||
case _ => None
|
||||
}
|
||||
def getProjectForReference(ref: Reference, structure: Load.BuildStructure): Option[ResolvedProject] =
|
||||
ref match { case pr: ProjectRef => getProject(pr, structure); case _ => None }
|
||||
def getProject(ref: ProjectRef, structure: Load.BuildStructure): Option[ResolvedProject] =
|
||||
(structure.units get ref.build).flatMap(_.defined get ref.project)
|
||||
|
||||
def setProject(session: SessionSettings, structure: Load.BuildStructure, s: State): State =
|
||||
{
|
||||
|
|
@ -62,19 +90,13 @@ object Project extends Init[Scope]
|
|||
val newState = s.copy(attributes = newAttrs)
|
||||
updateCurrent(newState.runExitHooks())
|
||||
}
|
||||
def current(state: State): (URI, String) = session(state).current
|
||||
def currentRef(state: State): ProjectRef =
|
||||
{
|
||||
val (unit, it) = current(state)
|
||||
ProjectRef(Some(unit), Some(it))
|
||||
}
|
||||
def current(state: State): ProjectRef = session(state).current
|
||||
def updateCurrent(s: State): State =
|
||||
{
|
||||
val structure = Project.structure(s)
|
||||
val (uri, id) = Project.current(s)
|
||||
val ref = ProjectRef(uri, id)
|
||||
val project = Load.getProject(structure.units, uri, id)
|
||||
logger(s).info("Set current project to " + id + " (in build " + uri +")")
|
||||
val ref = Project.current(s)
|
||||
val project = Load.getProject(structure.units, ref.build, ref.project)
|
||||
logger(s).info("Set current project to " + ref.project + " (in build " + ref.build +")")
|
||||
def get[T](k: SettingKey[T]): Option[T] = k in ref get structure.data
|
||||
|
||||
val history = get(historyPath) flatMap identity
|
||||
|
|
@ -91,7 +113,26 @@ object Project extends Init[Scope]
|
|||
translateUninitialized( make(settings)(delegates, scopeLocal) )
|
||||
|
||||
def display(scoped: ScopedKey[_]): String = Scope.display(scoped.scope, scoped.key.label)
|
||||
def display(ref: ProjectRef): String = "(" + (ref.uri map (_.toString) getOrElse "<this>") + ")" + (ref.id getOrElse "<root>")
|
||||
def display(ref: Reference): String =
|
||||
ref match
|
||||
{
|
||||
case pr: ProjectReference => display(pr)
|
||||
case br: BuildReference => display(br)
|
||||
}
|
||||
def display(ref: BuildReference) =
|
||||
ref match
|
||||
{
|
||||
case ThisBuild => "<this>"
|
||||
case BuildRef(uri) => "[" + uri + "]"
|
||||
}
|
||||
def display(ref: ProjectReference) =
|
||||
ref match
|
||||
{
|
||||
case ThisProject => "(<this>)<this>"
|
||||
case LocalProject(id) => "(<this>)" + id
|
||||
case RootProject(uri) => "(" + uri + ")<root>"
|
||||
case ProjectRef(uri, id) => "(" + uri + ")" + id
|
||||
}
|
||||
|
||||
def fillTaskAxis(scoped: ScopedKey[_]): ScopedKey[_] =
|
||||
ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key)
|
||||
|
|
@ -159,7 +200,7 @@ final case class SessionSettings(currentBuild: URI, currentProject: Map[URI, Str
|
|||
{
|
||||
assert(currentProject contains currentBuild, "Current build (" + currentBuild + ") not associated with a current project.")
|
||||
def setCurrent(build: URI, project: String, eval: () => Eval): SessionSettings = copy(currentBuild = build, currentProject = currentProject.updated(build, project), currentEval = eval)
|
||||
def current: (URI, String) = (currentBuild, currentProject(currentBuild))
|
||||
def current: ProjectRef = ProjectRef(currentBuild, currentProject(currentBuild))
|
||||
def appendSettings(s: Seq[SessionSetting]): SessionSettings = copy(append = modify(append, _ ++ s))
|
||||
def prependSettings(s: Seq[SessionSetting]): SessionSettings = copy(prepend = modify(prepend, s ++ _))
|
||||
def mergeSettings: Seq[Setting[_]] = merge(prepend) ++ original ++ merge(append)
|
||||
|
|
@ -175,7 +216,7 @@ final case class SessionSettings(currentBuild: URI, currentProject: Map[URI, Str
|
|||
object SessionSettings
|
||||
{
|
||||
type SessionSetting = (Setting[_], String)
|
||||
type SessionMap = Map[(URI, String), Seq[SessionSetting]]
|
||||
type SessionMap = Map[ProjectRef, Seq[SessionSetting]]
|
||||
|
||||
def reapply(session: SessionSettings, s: State): State =
|
||||
BuiltinCommands.reapply(session, Project.structure(s), s)
|
||||
|
|
@ -209,16 +250,16 @@ object SessionSettings
|
|||
val newAppend = session.append.updated(current, removeRanges(session.append.getOrElse(current, Nil), ranges))
|
||||
reapply(session.copy( append = newAppend ), s)
|
||||
}
|
||||
def saveAllSettings(s: State): State = saveSomeSettings(s)((_,_) => true)
|
||||
def saveAllSettings(s: State): State = saveSomeSettings(s)(_ => true)
|
||||
def saveSettings(s: State): State =
|
||||
{
|
||||
val (curi,cid) = Project.session(s).current
|
||||
saveSomeSettings(s)( (uri,id) => uri == curi && id == cid)
|
||||
val current = Project.session(s).current
|
||||
saveSomeSettings(s)( _ == current)
|
||||
}
|
||||
def saveSomeSettings(s: State)(include: (URI,String) => Boolean): State =
|
||||
def saveSomeSettings(s: State)(include: ProjectRef => Boolean): State =
|
||||
withSettings(s){session =>
|
||||
for( ((uri,id), settings) <- session.append if !settings.isEmpty && include(uri,id) )
|
||||
writeSettings(ProjectRef(uri, id), settings, Project.structure(s))
|
||||
for( (ref, settings) <- session.append if !settings.isEmpty && include(ref) )
|
||||
writeSettings(ref, settings, Project.structure(s))
|
||||
reapply(session.copy(original = session.mergeSettings, append = Map.empty, prepend = Map.empty), s)
|
||||
}
|
||||
def writeSettings(pref: ProjectRef, settings: Seq[SessionSetting], structure: Load.BuildStructure)
|
||||
|
|
@ -226,14 +267,14 @@ object SessionSettings
|
|||
val project = Project.getProject(pref, structure).getOrElse(error("Invalid project reference " + pref))
|
||||
val appendTo: File = BuildPaths.configurationSources(project.base).headOption.getOrElse(new File(project.base, "build.sbt"))
|
||||
val baseAppend = settingStrings(settings).flatMap("" :: _ :: Nil)
|
||||
val adjustedLines = if(appendTo.isFile && hasTrailingBlank(IO.readLines(appendTo)) ) baseAppend else "" +: baseAppend
|
||||
val adjustedLines = if(appendTo.isFile && hasTrailingBlank(IO readLines appendTo) ) baseAppend else "" +: baseAppend
|
||||
IO.writeLines(appendTo, adjustedLines, append = true)
|
||||
}
|
||||
def hasTrailingBlank(lines: Seq[String]) = lines.takeRight(1).exists(_.trim.isEmpty)
|
||||
def printAllSettings(s: State): State =
|
||||
withSettings(s){ session =>
|
||||
for( ((uri,id), settings) <- session.append if !settings.isEmpty) {
|
||||
println("In " + Project.display(ProjectRef(uri,id)))
|
||||
for( (ref, settings) <- session.append if !settings.isEmpty) {
|
||||
println("In " + Project.display(ref))
|
||||
printSettings(settings)
|
||||
}
|
||||
s
|
||||
|
|
@ -307,26 +348,7 @@ save, save-all
|
|||
|
||||
trait ProjectConstructors
|
||||
{
|
||||
implicit def configDependencyConstructor[T <% ProjectRef](p: T): Project.Constructor = new Project.Constructor(p)
|
||||
implicit def classpathDependency[T <% ProjectRef](p: T): Project.ClasspathDependency = new Project.ClasspathDependency(p, None)
|
||||
implicit def configDependencyConstructor[T <% ProjectReference](p: T): Project.Constructor = new Project.Constructor(p)
|
||||
implicit def classpathDependency[T <% ProjectReference](p: T): Project.ClasspathDependency = new Project.ClasspathDependency(p, None)
|
||||
}
|
||||
// the URI must be resolved and normalized before it is definitive
|
||||
final case class ProjectRef(uri: Option[URI], id: Option[String])
|
||||
object ProjectRef
|
||||
{
|
||||
def apply(base: URI, id: String): ProjectRef = ProjectRef(Some(base), Some(id))
|
||||
/** Reference to the project with 'id' in the current build unit.*/
|
||||
def apply(id: String): ProjectRef = ProjectRef(None, Some(id))
|
||||
def apply(base: File, id: String): ProjectRef = ProjectRef(Some(IO.toURI(base)), Some(id))
|
||||
/** Reference to the root project at 'base'.*/
|
||||
def apply(base: URI): ProjectRef = ProjectRef(Some(base), None)
|
||||
/** Reference to the root project at 'base'.*/
|
||||
def apply(base: File): ProjectRef = ProjectRef(Some(IO.toURI(base)), None)
|
||||
/** Reference to the root project in the current build unit.*/
|
||||
def root = ProjectRef(None, None)
|
||||
|
||||
implicit def stringToRef(s: String): ProjectRef = ProjectRef(s)
|
||||
implicit def projectToRef(p: Project): ProjectRef = ProjectRef(p.id)
|
||||
implicit def uriToRef(u: URI): ProjectRef = ProjectRef(u)
|
||||
implicit def fileToRef(f: File): ProjectRef = ProjectRef(f)
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2011 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import java.io.File
|
||||
import java.net.URI
|
||||
|
||||
// in all of these, the URI must be resolved and normalized before it is definitive
|
||||
|
||||
sealed trait Reference
|
||||
sealed trait ResolvedReference extends Reference
|
||||
|
||||
sealed trait BuildReference extends Reference
|
||||
final case object ThisBuild extends BuildReference
|
||||
final case class BuildRef(build: URI) extends BuildReference with ResolvedReference
|
||||
|
||||
sealed trait ProjectReference extends Reference
|
||||
final case class ProjectRef(build: URI, project: String) extends ProjectReference with ResolvedReference
|
||||
final case class LocalProject(project: String) extends ProjectReference
|
||||
final case class RootProject(build: URI) extends ProjectReference
|
||||
final case object ThisProject extends ProjectReference
|
||||
|
||||
object ProjectRef
|
||||
{
|
||||
def apply(base: File, id: String): ProjectRef = ProjectRef(IO toURI base, id)
|
||||
}
|
||||
object RootProject
|
||||
{
|
||||
/** Reference to the root project at 'base'.*/
|
||||
def apply(base: File): RootProject = RootProject(IO toURI base)
|
||||
}
|
||||
object Reference
|
||||
{
|
||||
def uri(ref: Reference): Option[URI] = ref match {
|
||||
case RootProject(b) => Some(b)
|
||||
case ProjectRef(b, _) => Some(b)
|
||||
case BuildRef(b) => Some(b)
|
||||
case _ => None
|
||||
}
|
||||
implicit def uriToRef(u: URI): ProjectReference = RootProject(u)
|
||||
implicit def fileToRef(f: File): ProjectReference = RootProject(f)
|
||||
implicit def stringToReference(s: String): ProjectReference = LocalProject(s)
|
||||
implicit def projectToRef(p: Project): ProjectReference = LocalProject(p.id)
|
||||
}
|
||||
115
main/Scope.scala
115
main/Scope.scala
|
|
@ -6,7 +6,7 @@ package sbt
|
|||
import java.io.File
|
||||
import java.net.URI
|
||||
|
||||
final case class Scope(project: ScopeAxis[ProjectRef], config: ScopeAxis[ConfigKey], task: ScopeAxis[AttributeKey[_]], extra: ScopeAxis[AttributeMap])
|
||||
final case class Scope(project: ScopeAxis[Reference], config: ScopeAxis[ConfigKey], task: ScopeAxis[AttributeKey[_]], extra: ScopeAxis[AttributeMap])
|
||||
object Scope
|
||||
{
|
||||
val ThisScope = Scope(This, This, This, This)
|
||||
|
|
@ -30,28 +30,54 @@ object Scope
|
|||
|
||||
def resolveProject(uri: URI, rootProject: URI => String): Scope => Scope =
|
||||
{
|
||||
case Scope(Select(ref), a,b,c) =>
|
||||
Scope(Select(mapRef(uri, rootProject, ref)), a,b,c)
|
||||
case Scope(Select(ref), a,b,c) => Scope(Select(resolveReference(uri, rootProject, ref)), a,b,c)
|
||||
case x => x
|
||||
}
|
||||
|
||||
def mapRef(current: URI, rootProject: URI => String, ref: ProjectRef): ProjectRef =
|
||||
{
|
||||
val (uri, id) = resolveRef(current, rootProject, ref)
|
||||
ProjectRef(Some(uri), Some(id))
|
||||
}
|
||||
def mapRefBuild(current: URI, ref: ProjectRef): ProjectRef = ProjectRef(Some(resolveBuild(current, ref)), ref.id)
|
||||
|
||||
def resolveBuild(current: URI, ref: ProjectRef): URI =
|
||||
ref.uri match { case Some(u) => resolveBuild(current, u); case None => current }
|
||||
def resolveBuildOnly(current: URI, ref: Reference): Reference =
|
||||
ref match
|
||||
{
|
||||
case br: BuildReference => resolveBuild(current, br)
|
||||
case pr: ProjectReference => resolveProjectBuild(current, pr)
|
||||
}
|
||||
def resolveBuild(current: URI, ref: BuildReference): BuildReference =
|
||||
ref match
|
||||
{
|
||||
case ThisBuild => BuildRef(current)
|
||||
case BuildRef(uri) => BuildRef(resolveBuild(current, uri))
|
||||
}
|
||||
def resolveProjectBuild(current: URI, ref: ProjectReference): ProjectReference =
|
||||
ref match
|
||||
{
|
||||
case ThisProject => RootProject(current)
|
||||
case LocalProject(id) => ProjectRef(current, id)
|
||||
case RootProject(uri) => RootProject(resolveBuild(current, uri))
|
||||
case ProjectRef(uri, id) => ProjectRef(resolveBuild(current, uri), id)
|
||||
}
|
||||
def resolveBuild(current: URI, uri: URI): URI =
|
||||
IO.directoryURI(current resolve uri)
|
||||
|
||||
def resolveRef(current: URI, rootProject: URI => String, ref: ProjectRef): (URI, String) =
|
||||
{
|
||||
val uri = resolveBuild(current, ref)
|
||||
(uri, ref.id getOrElse rootProject(uri) )
|
||||
}
|
||||
def resolveReference(current: URI, rootProject: URI => String, ref: Reference): ResolvedReference =
|
||||
ref match
|
||||
{
|
||||
case br: BuildReference => resolveBuildRef(current, br)
|
||||
case pr: ProjectReference => resolveProjectRef(current, rootProject, pr)
|
||||
}
|
||||
|
||||
def resolveProjectRef(current: URI, rootProject: URI => String, ref: ProjectReference): ProjectRef =
|
||||
ref match
|
||||
{
|
||||
case ThisProject => ProjectRef(current, rootProject(current))
|
||||
case LocalProject(id) => ProjectRef(current, id)
|
||||
case RootProject(uri) => val res = resolveBuild(current, uri); ProjectRef(res, rootProject(res))
|
||||
case ProjectRef(uri, id) => ProjectRef(resolveBuild(current, uri), id)
|
||||
}
|
||||
def resolveBuildRef(current: URI, ref: BuildReference): BuildRef =
|
||||
ref match
|
||||
{
|
||||
case ThisBuild => BuildRef(current)
|
||||
case BuildRef(uri) => BuildRef(resolveBuild(current, uri))
|
||||
}
|
||||
|
||||
def display(config: ConfigKey): String = if(config.name == "compile") "" else config.name + ":"
|
||||
def display(scope: Scope, sep: String): String =
|
||||
|
|
@ -69,7 +95,7 @@ object Scope
|
|||
def parseScopedKey(command: String): (Scope, String) =
|
||||
{
|
||||
val ScopedKeyRegex(_, projectID, _, config, key) = command
|
||||
val pref = if(projectID eq null) This else Select(ProjectRef(None, Some(projectID)))
|
||||
val pref = if(projectID eq null) This else Select(LocalProject(projectID))
|
||||
val conf = if(config eq null) This else Select(ConfigKey(config))
|
||||
(Scope(pref, conf, This, This), transformTaskName(key))
|
||||
}
|
||||
|
|
@ -82,37 +108,40 @@ object Scope
|
|||
}
|
||||
|
||||
// *Inherit functions should be immediate delegates and not include argument itself. Transitivity will be provided by this method
|
||||
def delegates(projectInherit: ProjectRef => Seq[ProjectRef],
|
||||
configInherit: (ProjectRef, ConfigKey) => Seq[ConfigKey],
|
||||
taskInherit: (ProjectRef, AttributeKey[_]) => Seq[AttributeKey[_]],
|
||||
extraInherit: (ProjectRef, AttributeMap) => Seq[AttributeMap])(scope: Scope): Seq[Scope] =
|
||||
scope.project match
|
||||
def delegates(projectInherit: Reference => Seq[Reference],
|
||||
configInherit: (Reference, ConfigKey) => Seq[ConfigKey],
|
||||
taskInherit: (Reference, AttributeKey[_]) => Seq[AttributeKey[_]],
|
||||
extraInherit: (Reference, AttributeMap) => Seq[AttributeMap])(rawScope: Scope): Seq[Scope] =
|
||||
{
|
||||
case Global | This => scope :: GlobalScope :: Nil
|
||||
case Select(proj) =>
|
||||
val prod =
|
||||
for {
|
||||
c <- linearize(scope.config)(configInherit(proj, _))
|
||||
t <- linearize(scope.task)(taskInherit(proj,_))
|
||||
e <- linearize(scope.extra)(extraInherit(proj,_))
|
||||
} yield
|
||||
Scope(Select(proj),c,t,e)
|
||||
val projI =
|
||||
withRawBuilds(linearize(scope.project)(projectInherit)) map { p => scope.copy(project = p) }
|
||||
|
||||
(prod ++ projI :+ GlobalScope).distinct
|
||||
val scope = Scope.replaceThis(GlobalScope)(rawScope)
|
||||
scope.project match
|
||||
{
|
||||
case Global => scope :: GlobalScope :: Nil
|
||||
case This => scope.copy(project = Global) :: GlobalScope :: Nil
|
||||
case Select(proj) =>
|
||||
val prod =
|
||||
for {
|
||||
c <- linearize(scope.config)(configInherit(proj, _))
|
||||
t <- linearize(scope.task)(taskInherit(proj,_))
|
||||
e <- linearize(scope.extra)(extraInherit(proj,_))
|
||||
} yield
|
||||
Scope(Select(proj),c,t,e)
|
||||
val projI =
|
||||
withRawBuilds(linearize(scope.project, Nil)(projectInherit)) map { p => scope.copy(project = p) }
|
||||
(prod ++ projI :+ GlobalScope).distinct
|
||||
}
|
||||
}
|
||||
def withRawBuilds(ps: Seq[ScopeAxis[ProjectRef]]): Seq[ScopeAxis[ProjectRef]] =
|
||||
ps ++ ps.flatMap(rawBuilds).distinct.map(Select.apply)
|
||||
def withRawBuilds(ps: Seq[ScopeAxis[Reference]]): Seq[ScopeAxis[Reference]] =
|
||||
(ps ++ (ps flatMap rawBuilds).map(Select.apply) :+ Global).distinct
|
||||
|
||||
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 rawBuilds(ps: ScopeAxis[Reference]): Seq[Reference] = ps match { case Select(ref) => rawBuilds(ref); case _ => Nil }
|
||||
def rawBuilds(ps: Reference): Seq[Reference] = (Reference.uri(ps) map BuildRef.apply).toList
|
||||
|
||||
def linearize[T](axis: ScopeAxis[T])(inherit: T => Seq[T]): Seq[ScopeAxis[T]] =
|
||||
def linearize[T](axis: ScopeAxis[T], append: Seq[ScopeAxis[T]] = Global :: Nil)(inherit: T => Seq[T]): Seq[ScopeAxis[T]] =
|
||||
axis match
|
||||
{
|
||||
case Select(x) => (Global +: Dag.topologicalSort(x)(inherit).map(Select.apply) ).reverse
|
||||
case Global | This => Global :: Nil
|
||||
case Select(x) => Dag.topologicalSort(x)(inherit).map(Select.apply).reverse ++ append
|
||||
case Global | This => append
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,14 +96,14 @@ object Scoped
|
|||
{
|
||||
def in(s: Scope): Result = app0(s)
|
||||
|
||||
def in(p: ProjectRef): Result = in(Select(p), This, This)
|
||||
def in(p: Reference): Result = in(Select(p), This, This)
|
||||
def in(t: Scoped): Result = in(This, This, Select(t.key))
|
||||
def in(c: ConfigKey): Result = in(This, Select(c), This)
|
||||
def in(c: ConfigKey, t: Scoped): Result = in(This, Select(c), Select(t.key))
|
||||
def in(p: ProjectRef, c: ConfigKey): Result = in(Select(p), Select(c), This)
|
||||
def in(p: ProjectRef, t: Scoped): Result = in(Select(p), This, Select(t.key))
|
||||
def in(p: ProjectRef, c: ConfigKey, t: Scoped): Result = in(Select(p), Select(c), Select(t.key))
|
||||
def in(p: ScopeAxis[ProjectRef], c: ScopeAxis[ConfigKey], t: ScopeAxis[AttributeKey[_]]): Result = in( Scope(p, c, t, This) )
|
||||
def in(p: Reference, c: ConfigKey): Result = in(Select(p), Select(c), This)
|
||||
def in(p: Reference, t: Scoped): Result = in(Select(p), This, Select(t.key))
|
||||
def in(p: Reference, c: ConfigKey, t: Scoped): Result = in(Select(p), Select(c), Select(t.key))
|
||||
def in(p: ScopeAxis[Reference], c: ScopeAxis[ConfigKey], t: ScopeAxis[AttributeKey[_]]): Result = in( Scope(p, c, t, This) )
|
||||
}
|
||||
|
||||
private[this] def scopedSetting[T](s: Scope, k: AttributeKey[T]): ScopedSetting[T] = new ScopedSetting[T] { val scope = s; val key = k }
|
||||
|
|
@ -407,21 +407,6 @@ object Scoped
|
|||
def apply[T](z: (A,B,C,D,E,F,G) => T) =
|
||||
Apply(t7._1 :^: t7._2 :^: t7._3 :^: t7._4 :^: t7._5 :^: t7._6 :^: t7._7 :^: KNil){ case a :+: b :+: c :+: d :+: e :+: f :+: g :+: HNil => z(a,b,c,d,e,f,g) }
|
||||
}
|
||||
|
||||
/*def unresolved(scope: Scope): Seq[String] = unresolvedProject(scope.project) ++ unresolvedThis(scope)
|
||||
def unresolvedProject(ps: ScopeAxis[ProjectRef]): Seq[String] = ps match {
|
||||
case Select(p) => ifEmpty(p.unit, "Unspecified build unit") ++ ifEmpty(p.id, "Unspecified project ID")
|
||||
case _ => Nil
|
||||
}
|
||||
def ifEmpty(p: Option[URI], msg: String): Seq[String] = if(p.isEmpty) msg :: Nil else Nil
|
||||
def unresolvedThis(scope: Scope): Seq[String] =
|
||||
unresolvedThis(scope.project, "project") ++
|
||||
unresolvedThis(scope.config, "configuration") ++
|
||||
unresolvedThis(scope.task, "task") ++
|
||||
unresolvedThis(scope.extra, "extra")
|
||||
|
||||
def unresolvedThis(axis: ScopeAxis[_], label: String): Seq[String] =
|
||||
if(axis == This) ("Unresolved This for " + label + " axis.") :: Nil else Nil*/
|
||||
}
|
||||
object InputKey
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue