improve Setting construction

- make all constructing methods end in = for lowest precedence
- rename Scope constructing method 'apply' to 'in' to allow 'apply' to
    be used on single settings as well as tuples and 'in' reads better
This commit is contained in:
Mark Harrah 2011-02-04 22:02:39 -05:00
parent 8bfe9a0208
commit eb10f7ee94
8 changed files with 165 additions and 143 deletions

View File

@ -26,7 +26,7 @@ object Act
def toAxis[T](opt: Option[T], ifNone: ScopeAxis[T]): ScopeAxis[T] =
opt match { case Some(t) => Select(t); case None => ifNone }
def defaultConfig(data: Settings[Scope])(project: ProjectRef): Option[String] =
ThisProject(project) get data flatMap( _.configurations.headOption.map(_.name))
ThisProject in project get data flatMap( _.configurations.headOption.map(_.name))
def config(confs: Set[String]): Parser[Option[String]] =
token( (ID examples confs) <~ ':' ).?

View File

@ -66,7 +66,6 @@ object EvaluateConfigurations
def evaluateSetting(eval: Eval, name: String, imports: Seq[(String,Int)], expression: String, line: Int): Setting[_] =
{
// TODO: need to persist the results, which is critical for start up time
val result = eval.eval(expression, imports = new EvalImports(imports, name), srcName = name, tpeName = Some("sbt.Project.Setting[_]"), line = line)
result.value.asInstanceOf[Setting[_]]
}
@ -103,32 +102,34 @@ object EvaluateTask
import BuildStreams.{Streams, TaskStreams}
val SystemProcessors = Runtime.getRuntime.availableProcessors
val PluginTaskKey = TaskKey[(Seq[File], Analysis)]("plugin-task")
// TODO: we should use a Seq[Attributed[File]] so that we don't throw away Analysis information
val PluginDefinition = TaskKey[(Seq[File], Analysis)]("plugin-definition")
val (state, dummyState) = dummy[State]("state")
val (streams, dummyStreams) = dummy[TaskStreams]("streams")
def injectSettings: Seq[Project.Setting[_]] = Seq(
state(Scope.GlobalScope) :== dummyState,
streams(Scope.GlobalScope) :== dummyStreams
(state in Scope.GlobalScope) :== dummyState,
(streams in Scope.GlobalScope) :== dummyStreams
)
def dummy[T](name: String): (TaskKey[T], Task[T]) = (TaskKey[T](name), dummyTask(name))
def dummyTask[T](name: String): Task[T] = task( error("Dummy task '" + name + "' did not get converted to a full task.") ) named name
def evalPluginDef(state: State, log: Logger)(pluginDef: BuildStructure): (Seq[File], Analysis) =
def evalPluginDef(log: Logger)(pluginDef: BuildStructure, state: State): (Seq[File], Analysis) =
{
val evaluated = evaluateTask(pluginDef, ScopedKey(Scope.ThisScope, PluginTaskKey.key), state)
val root = ProjectRef(pluginDef.root, Load.getRootProject(pluginDef.units)(pluginDef.root))
val evaluated = evaluateTask(pluginDef, ScopedKey(Scope.ThisScope, PluginDefinition.key), state, root)
val result = evaluated getOrElse error("Plugin task does not exist for plugin definition at " + pluginDef.root)
processResult(result, log)
}
def evaluateTask[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, checkCycles: Boolean = false, maxWorkers: Int = SystemProcessors): Option[Result[T]] =
for( (task, toNode) <- getTask(structure, taskKey, state) ) yield
def evaluateTask[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, thisProject: ProjectRef, checkCycles: Boolean = false, maxWorkers: Int = SystemProcessors): Option[Result[T]] =
for( (task, toNode) <- getTask(structure, taskKey, state, thisProject) ) yield
runTask(task, checkCycles, maxWorkers)(toNode)
def getTask[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State): Option[(Task[T], Execute.NodeView[Task])] =
def getTask[T](structure: BuildStructure, taskKey: ScopedKey[Task[T]], state: State, thisProject: ProjectRef): Option[(Task[T], Execute.NodeView[Task])] =
{
val thisScope = Scope(Select(Project.currentRef(state)), Global, Global, Global)
val thisScope = Scope(Select(thisProject), Global, Global, Global)
val resolvedScope = Scope.replaceThis(thisScope)( taskKey.scope )
for( t <- structure.data.get(resolvedScope, taskKey.key)) yield
(t, nodeView(structure, state))
@ -185,6 +186,7 @@ object Load
import BuildPaths._
import BuildStreams._
// note that there is State is passed in but not pulled out
def defaultLoad(state: State, log: Logger): (() => Eval, BuildStructure) =
{
val stagingDirectory = defaultStaging.getCanonicalFile // TODO: properly configurable
@ -193,11 +195,11 @@ object Load
val provider = state.configuration.provider
val classpath = provider.mainClasspath ++ provider.scalaProvider.jars
val compilers = Compile.compilers(state.configuration, log)
val evalPluginDef = EvaluateTask.evalPluginDef(state, log) _
val evalPluginDef = EvaluateTask.evalPluginDef(log) _
val delegates = memo(defaultDelegates)
val inject: Seq[Project.Setting[_]] = (AppConfig(Scope.GlobalScope) :== state.configuration) +: EvaluateTask.injectSettings
val inject: Seq[Project.Setting[_]] = ((AppConfig in Scope.GlobalScope) :== state.configuration) +: EvaluateTask.injectSettings
val config = new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, delegates, inject, log)
apply(base, config)
apply(base, state, config)
}
def defaultDelegates: LoadedBuild => Scope => Seq[Scope] = (lb: LoadedBuild) => {
val rootProject = getRootProject(lb.units)
@ -224,10 +226,10 @@ object Load
// 6) Load all configurations using build definitions and plugins (their classpaths and loaded instances).
// 7) Combine settings from projects, plugins, and configurations
// 8) Evaluate settings
def apply(rootBase: File, config: LoadBuildConfiguration): (() => Eval, BuildStructure) =
def apply(rootBase: File, s: State, config: LoadBuildConfiguration): (() => Eval, BuildStructure) =
{
// load, which includes some resolution, but can't fill in project IDs yet, so follow with full resolution
val loaded = resolveProjects(load(rootBase, config))
val loaded = resolveProjects(load(rootBase, s, config))
val projects = loaded.units
lazy val rootEval = lazyEval(loaded.units(loaded.root).unit)
val settings = config.injectSettings ++ buildConfigurations(loaded, getRootProject(projects), rootEval)
@ -259,7 +261,7 @@ object Load
val projectSettings = build.defined flatMap { case (id, project) =>
val srcs = configurationSources(project.base)
val ref = ProjectRef(Some(uri), Some(id))
val defineConfig = for(c <- project.configurations) yield (Config(ref, ConfigKey(c.name)) :== c)
val defineConfig = for(c <- project.configurations) yield ( (Config in (ref, ConfigKey(c.name))) :== c)
val settings =
(ThisProject :== project) +:
(ThisProjectRef :== ref) +:
@ -288,7 +290,8 @@ 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, config: LoadBuildConfiguration): LoadedBuild = load(file, uri => loadUnit(uri, RetrieveUnit(config.stagingDirectory, uri), config) )
def load(file: File, s: State, config: LoadBuildConfiguration): LoadedBuild =
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 =
{
@ -402,12 +405,12 @@ object Load
def noProject(uri: URI, id: String) = error("No project '" + id + "' defined in '" + uri + "'.")
def noConfiguration(uri: URI, id: String, conf: String) = error("No configuration '" + conf + "' defined in project '" + id + "' in '" + uri +"'")
def loadUnit(uri: URI, localBase: File, config: LoadBuildConfiguration): BuildUnit =
def loadUnit(uri: URI, localBase: File, s: State, config: LoadBuildConfiguration): BuildUnit =
{
val normBase = localBase.getCanonicalFile
val defDir = selectProjectDir(normBase)
val pluginDir = pluginDirectory(defDir)
val plugs = plugins(pluginDir, config)
val plugs = plugins(pluginDir, s, config)
val defs = definitionSources(defDir)
val target = buildOutputDirectory(defDir, config.compilers)
@ -421,14 +424,17 @@ object Load
new BuildUnit(uri, normBase, loadedDefs, plugs)
}
def plugins(dir: File, config: LoadBuildConfiguration): LoadedPlugins = if(dir.exists) buildPlugins(dir, config) else noPlugins(config)
def plugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins = if(dir.exists) buildPlugins(dir, s, config) else noPlugins(config)
def noPlugins(config: LoadBuildConfiguration): LoadedPlugins = new LoadedPlugins(config.classpath, config.loader, Nil, Nil)
def buildPlugins(dir: File, config: LoadBuildConfiguration): LoadedPlugins =
def buildPlugins(dir: File, s: State, config: LoadBuildConfiguration): LoadedPlugins =
{
val (_,pluginDef) = apply(dir, config)
val (pluginClasspath, pluginAnalysis) = config.evalPluginDef(pluginDef)
val pluginLoader = ClasspathUtilities.toLoader(pluginClasspath, config.loader)
loadPlugins(pluginClasspath, pluginLoader, pluginAnalysis)
val (eval,pluginDef) = apply(dir, s, config)
val pluginState = Project.setProject(Load.initialSession(pluginDef, eval), pluginDef, s)
val (pluginClasspath, pluginAnalysis) = config.evalPluginDef(pluginDef, pluginState)
val definitionClasspath = (pluginClasspath ++ config.classpath).distinct
val pluginLoader = ClasspathUtilities.toLoader(definitionClasspath, config.loader)
loadPlugins(definitionClasspath, pluginLoader, pluginAnalysis)
}
def definitions(base: File, targetBase: File, srcs: Seq[File], plugins: LoadedPlugins, compilers: Compilers, log: Logger, buildBase: File): LoadedDefinitions =
@ -520,7 +526,7 @@ object Load
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])
final class LoadBuildConfiguration(val stagingDirectory: File, val classpath: Seq[File], val loader: ClassLoader, val compilers: Compilers, val evalPluginDef: BuildStructure => (Seq[File], Analysis), val delegates: LoadedBuild => Scope => Seq[Scope], val injectSettings: Seq[Setting[_]], val log: Logger)
final class LoadBuildConfiguration(val stagingDirectory: File, val classpath: Seq[File], val loader: ClassLoader, val compilers: Compilers, val evalPluginDef: (BuildStructure, State) => (Seq[File], Analysis), val delegates: LoadedBuild => Scope => Seq[Scope], val injectSettings: Seq[Setting[_]], val log: Logger)
// information that is not original, but can be reconstructed from the rest of BuildStructure
final class StructureIndex(val keyMap: Map[String, AttributeKey[_]], val taskToKey: Map[Task[_], ScopedKey[Task[_]]], val keyIndex: KeyIndex)

View File

@ -3,6 +3,7 @@ package sbt
import java.io.File
import Scoped.Apply
import Project.{AppConfig, Config, Setting, ThisProject, ThisProjectRef}
import Configurations.{Compile => CompileConf, Test => TestConf}
import Command.HistoryPath
import EvaluateTask.streams
import inc.Analysis
@ -150,54 +151,54 @@ object Default
def core = Seq(
Name :== "test",
Version :== "0.1",
Data :- ( EvaluateTask.state map { state => Project.structure(state).data } )
Data <<= EvaluateTask.state map { state => Project.structure(state).data }
)
def paths = Seq(
Base :- ( ThisProject app (_.base) ),
Target :- Base / "target",
Base <<= ThisProject(_.base),
Target <<= Base / "target",
DefaultExcludes :== (".*" - ".") || HiddenFileFilter,
HistoryPath :- Target.app(t => Some(t / ".history")),
CacheDirectory :- Target / "cache",
Source :- Base / "src",
HistoryPath <<= Target(t => Some(t / ".history")),
CacheDirectory <<= Target / "cache",
Source <<= Base / "src",
SourceFilter :== ("*.java" | "*.scala"),
SourceManaged :- Base / "src_managed"
SourceManaged <<= Base / "src_managed"
)
lazy val configPaths = Seq(
Source :- configSrcSub( Source(Scope(This,Global,This,This)) ),
SourceManaged :- configSrcSub(SourceManaged),
CacheDirectory :- (CacheDirectory, Config) { _ / _.name },
ClassDirectory :- (Target, Config) { (target, conf) => target / (prefix(conf.name) + "classes") },
Sources :- ( (SourceDirectories, SourceFilter, DefaultExcludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles.toSeq } ),
ScalaSource :- Source / "scala",
JavaSource :- Source / "java",
JavaSourceRoots :- toSeq(JavaSource),
ResourceDir :- Source / "resources",
SourceDirectories :- (ScalaSource, JavaSourceRoots) { _ +: _ },
ResourceDirectories :- toSeq(ResourceDir)
Source <<= configSrcSub( Source in Scope(This,Global,This,This) ),
SourceManaged <<= configSrcSub(SourceManaged),
CacheDirectory <<= (CacheDirectory, Config) { _ / _.name },
ClassDirectory <<= (Target, Config) { (target, conf) => target / (prefix(conf.name) + "classes") },
Sources <<= (SourceDirectories, SourceFilter, DefaultExcludes) map { (d,f,excl) => d.descendentsExcept(f,excl).getFiles.toSeq },
ScalaSource <<= Source / "scala",
JavaSource <<= Source / "java",
JavaSourceRoots <<= toSeq(JavaSource),
ResourceDir <<= Source / "resources",
SourceDirectories <<= (ScalaSource, JavaSourceRoots) { _ +: _ },
ResourceDirectories <<= toSeq(ResourceDir)
)
def addBaseSources = Seq(
Sources :- ( (Sources, Base, SourceFilter, DefaultExcludes) map { (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles.toSeq } )
Sources <<= (Sources, Base, SourceFilter, DefaultExcludes) map { (srcs,b,f,excl) => (srcs +++ b * (f -- excl)).getFiles.toSeq }
)
lazy val configTasks = Classpaths.configSettings ++ compileTasks
def webPaths = Seq(
WebappDir :- Source / "webapp"
WebappDir <<= Source / "webapp"
)
def compileBase = Seq(
Compilers :- (ScalaInstance, AppConfig) { (si, app) => Compile.compilers(si)(app, ConsoleLogger()) },
Compilers <<= (ScalaInstance, AppConfig) { (si, app) => Compile.compilers(si)(app, ConsoleLogger()) },
JavacOptions :== Nil,
ScalacOptions :== Nil,
ScalaInstance :- (AppConfig, ScalaVersion){ (app, version) => sbt.ScalaInstance(version, app.provider.scalaProvider) },
ScalaVersion :- AppConfig.app( _.provider.scalaProvider.version)
ScalaInstance <<= (AppConfig, ScalaVersion){ (app, version) => sbt.ScalaInstance(version, app.provider.scalaProvider) },
ScalaVersion <<= AppConfig( _.provider.scalaProvider.version)
)
def compileTasks = Seq(
CompileTask :- compileTask,
CompileInputs :- compileInputsTask
CompileTask <<= compileTask,
CompileInputs <<= compileInputsTask
)
def compileTask = ( (CompileInputs, streams) map { (i,s) => Compile(i,s.log) } )
def compileTask = (CompileInputs, streams) map { (i,s) => Compile(i,s.log) }
def compileInputsTask =
(DependencyClasspath, Sources, JavaSourceRoots, Compilers, JavacOptions, ScalacOptions, CacheDirectory, ClassDirectory, streams) map {
(cp, sources, javaRoots, compilers, scalacOptions, javacOptions, cacheDirectory, classes, s) =>
@ -212,16 +213,20 @@ object Default
def inConfig(conf: Configuration)(ss: Seq[Setting[_]]): Seq[Setting[_]] =
Project.transform(Scope.replaceThis(ThisScope.copy(config = Select(conf))), (Config :== conf) +: ss)
lazy val defaultPaths = paths ++ inConfig(Configurations.Compile)(configPaths ++ addBaseSources) ++ inConfig(Configurations.Test)(configPaths)
lazy val defaultWebPaths = defaultPaths ++ inConfig(Configurations.Compile)(webPaths)
lazy val defaultPaths = paths ++ inConfig(CompileConf)(configPaths ++ addBaseSources) ++ inConfig(TestConf)(configPaths)
lazy val defaultWebPaths = defaultPaths ++ inConfig(CompileConf)(webPaths)
lazy val defaultTasks = inConfig(Configurations.Compile)(configTasks) ++ inConfig(Configurations.Test)(configTasks)
lazy val defaultTasks = inConfig(CompileConf)(configTasks) ++ inConfig(TestConf)(configTasks)
lazy val defaultWebTasks = Nil
lazy val defaultClasspaths = Classpaths.publishSettings ++ Classpaths.baseSettings ++ inConfig(Configurations.Compile)(Classpaths.configSettings) ++ inConfig(Configurations.Test)(Classpaths.configSettings)
def pluginDefinition = Seq(
EvaluateTask.PluginDefinition <<= (FullClasspath in CompileConf,CompileTask in CompileConf) map ( (c,a) => (data(c),a) )
)
lazy val defaultClasspaths = Classpaths.publishSettings ++ Classpaths.baseSettings ++ inConfig(CompileConf)(Classpaths.configSettings) ++ inConfig(TestConf)(Classpaths.configSettings)
lazy val defaultSettings = core ++ defaultPaths ++ defaultClasspaths ++ defaultTasks ++ compileBase
lazy val defaultSettings = core ++ defaultPaths ++ defaultClasspaths ++ defaultTasks ++ compileBase ++ pluginDefinition
lazy val defaultWebSettings = defaultSettings ++ defaultWebPaths ++ defaultWebTasks
}
object Classpaths
@ -231,79 +236,78 @@ object Classpaths
import Keys._
import Scope.ThisScope
import Default._
def attributed[T](in: Seq[T]): Seq[Attributed[T]] = in map Attributed.blank
import Attributed.{blank, blankSeq}
def concat[T](a: ScopedTaskable[Seq[T]], b: ScopedTaskable[Seq[T]]): Apply[Task[Seq[T]]] = (a,b) map (_ ++ _)
val configSettings: Seq[Project.Setting[_]] = Seq(
ExternalDependencyClasspath :- concat(UnmanagedClasspath, ManagedClasspath),
DependencyClasspath :- concat(InternalDependencyClasspath, ExternalDependencyClasspath),
FullClasspath :- concat(DependencyClasspath, Products),
InternalDependencyClasspath :- internalDependencies,
Products :- makeProducts,
ManagedClasspath :- ( (Config, Update) map { (config, up) => attributed(up.getOrElse(config.name, error("Configuration '" + config.name + "' unresolved by 'update'."))) } ),
UnmanagedClasspath :- ( (Config, UnmanagedBase, ClasspathFilter, DefaultExcludes) map { (config, base, filter, excl) =>
attributed( (base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).getFiles.toSeq )
})
ExternalDependencyClasspath <<= concat(UnmanagedClasspath, ManagedClasspath),
DependencyClasspath <<= concat(InternalDependencyClasspath, ExternalDependencyClasspath),
FullClasspath <<= concat(DependencyClasspath, Products),
InternalDependencyClasspath <<= internalDependencies,
Products <<= makeProducts,
ManagedClasspath <<= (Config, Update) map { (config, up) => up.getOrElse(config.name, error("Configuration '" + config.name + "' unresolved by 'update'.")) },
UnmanagedClasspath <<= (Config, UnmanagedBase, ClasspathFilter, DefaultExcludes) map { (config, base, filter, excl) =>
(base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).getFiles.toSeq
}
)
val publishSettings: Seq[Project.Setting[_]] = Seq(
PublishMavenStyle :== true,
PackageToPublish :== nop,
DeliverDepends := (PublishMavenStyle, MakePom.setting, PackageToPublish.setting) { (mavenStyle, makePom, ptp) => if(mavenStyle) makePom else ptp },
MakePom :- ( (IvyModule, MakePomConfig, PackageToPublish) map { (ivyModule, makePomConfig, _) => IvyActions.makePom(ivyModule, makePomConfig); makePomConfig.file } ),
Deliver :- deliver(PublishConfig),
DeliverLocal :- deliver(PublishLocalConfig),
Publish :- publish(PublishConfig, Deliver),
PublishLocal :- publish(PublishLocalConfig, DeliverLocal)
MakePom <<= (IvyModule, MakePomConfig, PackageToPublish) map { (ivyModule, makePomConfig, _) => IvyActions.makePom(ivyModule, makePomConfig); makePomConfig.file },
Deliver <<= deliver(PublishConfig),
DeliverLocal <<= deliver(PublishLocalConfig),
Publish <<= publish(PublishConfig, Deliver),
PublishLocal <<= publish(PublishLocalConfig, DeliverLocal)
)
val baseSettings: Seq[Project.Setting[_]] = Seq(
UnmanagedBase :- Base / "lib",
NormalizedName :- (Name app StringUtilities.normalize),
UnmanagedBase <<= Base / "lib",
NormalizedName <<= Name(StringUtilities.normalize),
Organization :== NormalizedName,
ClasspathFilter :== "*.jar",
Resolvers :- (ProjectResolver,BaseResolvers).map( (pr,rs) => pr +: Resolver.withDefaultResolvers(rs)),
Resolvers <<= (ProjectResolver,BaseResolvers).map( (pr,rs) => pr +: Resolver.withDefaultResolvers(rs)),
Offline :== false,
ModuleName :== NormalizedName,
DefaultConfiguration :== Some(Configurations.Compile),
DefaultConfigurationMapping :- DefaultConfiguration.app{ case Some(d) => "*->" + d.name; case None => "*->*" },
PathsIvy :- Base.app(base => new IvyPaths(base, None)),
DefaultConfigurationMapping <<= DefaultConfiguration{ case Some(d) => "*->" + d.name; case None => "*->*" },
PathsIvy <<= Base(base => new IvyPaths(base, None)),
OtherResolvers :== Nil,
ProjectResolver :- projectResolver,
ProjectDependencies :- projectDependencies,
ProjectResolver <<= projectResolver,
ProjectDependencies <<= projectDependencies,
LibraryDependencies :== Nil,
AllDependencies :- concat(ProjectDependencies,LibraryDependencies),
AllDependencies <<= concat(ProjectDependencies,LibraryDependencies),
IvyLoggingLevel :== UpdateLogging.Quiet,
IvyXML :== NodeSeq.Empty,
IvyValidate :== false,
IvyScalaConfig :== None,
ModuleConfigurations :== Nil,
PublishTo :== None,
PomFile :- (Target, Version, ModuleName)( (target, version, module) => target / (module + "-" + version + ".pom") ),
Artifacts :== Nil,
ProjectID :- (Organization,ModuleName,Version,Artifacts){ (org,module,version,as) => ModuleID(org, module, version).cross(true).artifacts(as : _*) },
PomFile <<= (Target, Version, ModuleName)( (target, version, module) => target / (module + "-" + version + ".pom") ),
Artifacts <<= ModuleName(name => Artifact(name, "jar", "jar") :: Nil),
ProjectID <<= (Organization,ModuleName,Version,Artifacts){ (org,module,version,as) => ModuleID(org, module, version).cross(true).artifacts(as : _*) },
BaseResolvers :== Nil,
ProjectDescriptors :- depMap,
ProjectDescriptors <<= depMap,
RetrievePattern :== "[type]/[organisation]/[module]/[artifact](-[revision])(-[classifier]).[ext]",
UpdateConfig :- (RetrieveConfig, IvyLoggingLevel)((conf,level) => new UpdateConfiguration(conf, level) ),
UpdateConfig <<= (RetrieveConfig, IvyLoggingLevel)((conf,level) => new UpdateConfiguration(conf, level) ),
RetrieveConfig :== None, //Some(new RetrieveConfiguration(managedDependencyPath asFile, retrievePattern, true))
IvyConfig :- ( (Resolvers, PathsIvy, OtherResolvers, ModuleConfigurations, Offline, AppConfig) map { (rs, paths, otherResolvers, moduleConfigurations, offline, app) =>
IvyConfig <<= (Resolvers, PathsIvy, OtherResolvers, ModuleConfigurations, Offline, AppConfig) map { (rs, paths, otherResolvers, moduleConfigurations, offline, app) =>
// todo: pass logger from streams directly to IvyActions
val lock = app.provider.scalaProvider.launcher.globalLock
new InlineIvyConfiguration(paths, rs, otherResolvers, moduleConfigurations, offline, Some(lock), ConsoleLogger())
}),
ModuleSettingsTask :- ( (ProjectID, AllDependencies, IvyXML, ThisProject, DefaultConfiguration, IvyScalaConfig, IvyValidate) map {
},
ModuleSettingsTask <<= (ProjectID, AllDependencies, IvyXML, ThisProject, DefaultConfiguration, IvyScalaConfig, IvyValidate) map {
(pid, deps, ivyXML, project, defaultConf, ivyScala, validate) => new InlineConfiguration(pid, deps, ivyXML, project.configurations, defaultConf, ivyScala, validate)
}),
MakePomConfig :- PomFile.app(pomFile => makePomConfiguration(pomFile)),
PublishConfig :- ( (Target, PublishTo, IvyLoggingLevel) map { (outputDirectory, publishTo, level) => publishConfiguration( publishPatterns(outputDirectory), resolverName = getPublishTo(publishTo).name, logging = level) } ),
PublishLocalConfig :- ( (Target, IvyLoggingLevel) map { (outputDirectory, level) => publishConfiguration( publishPatterns(outputDirectory, true), logging = level ) } ),
IvySbtTask :- ( IvyConfig map { conf => new IvySbt(conf) } ),
IvyModule :- ( (IvySbtTask, ModuleSettingsTask) map { (ivySbt, settings) => new ivySbt.Module(settings) } ),
Update :- ( (IvyModule, UpdateConfig, CacheDirectory, streams) map { (ivyModule, updateConfig, cacheDirectory, s) =>
},
MakePomConfig <<= PomFile(pomFile => makePomConfiguration(pomFile)),
PublishConfig <<= (Target, PublishTo, IvyLoggingLevel) map { (outputDirectory, publishTo, level) => publishConfiguration( publishPatterns(outputDirectory), resolverName = getPublishTo(publishTo).name, logging = level) },
PublishLocalConfig <<= (Target, IvyLoggingLevel) map { (outputDirectory, level) => publishConfiguration( publishPatterns(outputDirectory, true), logging = level ) },
IvySbtTask <<= IvyConfig map { conf => new IvySbt(conf) },
IvyModule <<= (IvySbtTask, ModuleSettingsTask) map { (ivySbt, settings) => new ivySbt.Module(settings) },
Update <<= (IvyModule, UpdateConfig, CacheDirectory, streams) map { (ivyModule, updateConfig, cacheDirectory, s) =>
cachedUpdate(cacheDirectory / "update", ivyModule, updateConfig, s.log)
})
}
)
@ -362,17 +366,17 @@ object Classpaths
def projectDependencies =
(ThisProject, Data) map { (p, data) =>
p.dependencies flatMap { dep => ProjectID(dep.project) get data map { _.copy(configurations = dep.configuration) } }
p.dependencies flatMap { dep => (ProjectID in dep.project) get data map { _.copy(configurations = dep.configuration) } }
}
def depMap: Apply[Task[Map[ModuleRevisionId, ModuleDescriptor]]] =
(ThisProject, ThisProjectRef, Data) flatMap { (root, rootRef, data) =>
val dependencies = (p: (ProjectRef, Project)) => p._2.dependencies.flatMap(pr => ThisProject(pr.project) get data map { (pr.project, _) })
val dependencies = (p: (ProjectRef, Project)) => 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]] =
projects.flatMap { case (p,_) => IvyModule(p) get data }.join.map { mods =>
projects.flatMap { case (p,_) => IvyModule in p get data }.join.map { mods =>
(mods.map{ mod =>
val md = mod.moduleDescriptor
(md.getModuleRevisionId, md)
@ -405,7 +409,7 @@ object Classpaths
for( Project.ClasspathDependency(dep, confMapping) <- project.dependencies)
{
val depProject = ThisProject(dep) get data getOrElse error("Invalid project: " + dep)
val depProject = ThisProject in dep get data getOrElse error("Invalid project: " + dep)
val mapping = mapped(confMapping, masterConfs, configurationNames(depProject), "compile", "*->compile")
// map master configuration 'c' and all extended configurations to the appropriate dependency configuration
for(ac <- applicableConfigs; depConfName <- mapping(ac.name))
@ -462,8 +466,8 @@ object Classpaths
def configuration(ref: ProjectRef, dep: Project, conf: String): Configuration =
dep.configurations.find(_.name == conf) getOrElse missingConfiguration(Project display ref, conf)
def products(dep: ProjectRef, conf: String, data: Settings[Scope]): Task[Classpath] =
Products(dep, ConfigKey(conf)) get data getOrElse const(Nil)
Products in (dep, ConfigKey(conf)) get data getOrElse const(Nil)
def defaultConfiguration(p: ProjectRef, data: Settings[Scope]): Configuration =
flatten(DefaultConfiguration(p) get data) getOrElse Configurations.Default
flatten(DefaultConfiguration in p get data) getOrElse Configurations.Default
def flatten[T](o: Option[Option[T]]): Option[T] = o flatMap identity
}

View File

@ -6,7 +6,6 @@ package sbt
import Execute.NodeView
import complete.HistoryCommands
import HistoryCommands.{Start => HistoryPrefix}
import Project.{SessionKey, StructureKey}
import sbt.build.{AggressiveCompile, Auto, BuildException, LoadCommand, Parse, ParseException, ProjectLoad, SourceLoad}
import compile.EvalImports
import sbt.complete.{DefaultParsers, Parser}
@ -138,7 +137,7 @@ object Commands
}
def reload = Command.command(ReloadCommand, ReloadBrief, ReloadDetailed) { s =>
runExitHooks(s).reload
s.runExitHooks().reload
}
def defaults = Command.command(DefaultsCommand) { s =>
@ -226,7 +225,7 @@ object Commands
{
logger(s).info("Reapplying settings...")
val newStructure = Load.reapply(newSession.mergeSettings, structure)
setProject(newSession, newStructure, s)
Project.setProject(newSession, newStructure, s)
}
def set = Command.single(SetCommand, setBrief, setDetailed) { (s, arg) =>
val extracted = Project extract s
@ -281,7 +280,7 @@ object Commands
def exit = Command.command(TerminateAction, Help(exitBrief) :: Nil ) ( doExit )
def doExit(s: State): State = runExitHooks(s).exit(true)
def doExit(s: State): State = s.runExitHooks().exit(true)
// TODO: tab completion, low priority
def discover = Command.single(Discover, DiscoverBrief, DiscoverDetailed) { (s, arg) =>
@ -304,13 +303,7 @@ object Commands
def loadProject = Command.command(LoadProject, LoadProjectBrief, LoadProjectDetailed) { s =>
val (eval, structure) = Load.defaultLoad(s, logger(s))
val session = Load.initialSession(structure, eval)
setProject(session, structure, s)
}
def setProject(session: SessionSettings, structure: Load.BuildStructure, s: State): State =
{
val newAttrs = s.attributes.put(StructureKey, structure).put(SessionKey, session)
val newState = s.copy(attributes = newAttrs)
Project.updateCurrent(runExitHooks(newState))
Project.setProject(session, structure, s)
}
def handleException(e: Throwable, s: State, trace: Boolean = true): State = {
@ -320,11 +313,6 @@ object Commands
s.fail
}
def runExitHooks(s: State): State = {
ExitHooks.runExitHooks(s.exitHooks.toSeq)
s.copy(exitHooks = Set.empty)
}
// TODO: tab completion, low priority
def loadCommands = Command.single(LoadCommand, Parse.helpBrief(LoadCommand, LoadCommandLabel), Parse.helpDetail(LoadCommand, LoadCommandLabel, true) ) { (s, arg) =>
applyCommands(s, buildCommands(arg, s.configuration))

View File

@ -49,6 +49,13 @@ object Project extends Init[Scope]
case ProjectRef(Some(uri), Some(id)) => (structure.units get uri).flatMap(_.defined get id)
case _ => None
}
def setProject(session: SessionSettings, structure: Load.BuildStructure, s: State): State =
{
val newAttrs = s.attributes.put(StructureKey, structure).put(SessionKey, session)
val newState = s.copy(attributes = newAttrs)
updateCurrent(newState.runExitHooks())
}
def current(state: State): (URI, String) = session(state).current
def currentRef(state: State): ProjectRef =
{
@ -64,7 +71,7 @@ object Project extends Init[Scope]
logger(s).info("Set current project to " + id + " (in build " + uri +")")
val data = structure.data
val historyPath = HistoryPath(ref).get(data).flatMap(identity)
val historyPath = HistoryPath in ref get data flatMap identity
val newAttrs = s.attributes.put(Watch.key, makeWatched(data, ref, project)).put(HistoryPath.key, historyPath)
s.copy(attributes = newAttrs)
}
@ -72,7 +79,7 @@ object Project extends Init[Scope]
def makeWatched(data: Settings[Scope], ref: ProjectRef, project: Project): Watched =
{
def getWatch(ref: ProjectRef) = Watch(ref).get(data)
def getWatch(ref: ProjectRef) = Watch in ref get data
getWatch(ref) match
{
case Some(currentWatch) =>

View File

@ -39,6 +39,7 @@ trait StateOps {
def get[T](key: AttributeKey[T]): Option[T]
def put[T](key: AttributeKey[T], value: T): State
def baseDir: File
def runExitHooks(): State
}
object State
{
@ -74,5 +75,9 @@ object State
else
s.copy(commands = remaining)
}
def runExitHooks(): State = {
ExitHooks.runExitHooks(s.exitHooks.toSeq)
s.copy(exitHooks = Set.empty)
}
}
}

View File

@ -37,6 +37,8 @@ object Scoped
implicit def richSettingScoped[T](s: ScopedSetting[T]): RichSettingScoped[T] = new RichSettingScoped[T](s.scope, s.key)
implicit def richTaskScoped[T](s: ScopedTask[T]): RichTaskScoped[T] = new RichTaskScoped[T](s.scope, s.key)
implicit def richInputScoped[T](s: ScopedInput[T]): RichInputScoped[T] = new RichInputScoped[T](s.scope, s.key)
implicit def richSettingListScoped[T](s: ScopedSetting[Seq[T]]): RichSettingList[T] = new RichSettingList[T](s.scope, s.key)
implicit def richListTaskScoped[T](s: ScopedTask[Seq[T]]): RichListTask[T] = new RichListTask[T](s.scope, s.key)
implicit def taskScoping[T](s: TaskKey[T]): ScopingTask[T] = new ScopingTask[T](s.key)
@ -48,16 +50,16 @@ object Scoped
final class ScopingSetting[T, Result](val key: AttributeKey[T], app0: Scope => Result)
{
def apply(s: Scope): Result = app0(s)
def in(s: Scope): Result = app0(s)
def apply(p: ProjectRef): Result = apply(Select(p), This, This)
def apply(t: TaskKey[_]): Result = apply(This, This, Select(t))
def apply(c: ConfigKey): Result = apply(This, Select(c), This)
def apply(c: ConfigKey, t: TaskKey[_]): Result = apply(This, Select(c), Select(t))
def apply(p: ProjectRef, c: ConfigKey): Result = apply(Select(p), Select(c), This)
def apply(p: ProjectRef, t: TaskKey[_]): Result = apply(Select(p), This, Select(t))
def apply(p: ProjectRef, c: ConfigKey, t: TaskKey[_]): Result = apply(Select(p), Select(c), Select(t))
def apply(p: ScopeAxis[ProjectRef], c: ScopeAxis[ConfigKey], t: ScopeAxis[TaskKey[_]]): Result = apply( Scope(p, c, convert(t), This) )
def in(p: ProjectRef): Result = in(Select(p), This, This)
def in(t: TaskKey[_]): Result = in(This, This, Select(t))
def in(c: ConfigKey): Result = in(This, Select(c), This)
def in(c: ConfigKey, t: TaskKey[_]): Result = in(This, Select(c), Select(t))
def in(p: ProjectRef, c: ConfigKey): Result = in(Select(p), Select(c), This)
def in(p: ProjectRef, t: TaskKey[_]): Result = in(Select(p), This, Select(t))
def in(p: ProjectRef, c: ConfigKey, t: TaskKey[_]): Result = in(Select(p), Select(c), Select(t))
def in(p: ScopeAxis[ProjectRef], c: ScopeAxis[ConfigKey], t: ScopeAxis[TaskKey[_]]): Result = in( Scope(p, c, convert(t), This) )
private def convert(tk: ScopeAxis[TaskKey[_]]): ScopeAxis[AttributeKey[_]] =
tk match {
case Select(t) => Select(t.key)
@ -71,14 +73,24 @@ object Scoped
final class ScopingTask[T](taskKey: AttributeKey[Task[T]])
{
def apply(p: ProjectRef): RichTaskScoped[T] = apply(Select(p), This)
def apply(c: ConfigKey): RichTaskScoped[T] = apply(This, Select(c))
def apply(p: ProjectRef, c: ConfigKey): RichTaskScoped[T] = apply(Select(p), Select(c))
def apply(p: ScopeAxis[ProjectRef], c: ScopeAxis[ConfigKey]): ScopedTask[T] = apply(Scope(p, c, This, This))
def apply(s: Scope): ScopedTask[T] = scopedTask(s, taskKey)
def in(p: ProjectRef): ScopedTask[T] = in(Select(p), This)
def in(c: ConfigKey): ScopedTask[T] = in(This, Select(c))
def in(p: ProjectRef, c: ConfigKey): ScopedTask[T] = in(Select(p), Select(c))
def in(p: ScopeAxis[ProjectRef], c: ScopeAxis[ConfigKey]): ScopedTask[T] = in(Scope(p, c, This, This))
def in(s: Scope): ScopedTask[T] = scopedTask(s, taskKey)
}
private[this] def scopedTask[T](s: Scope, k: AttributeKey[Task[T]]): ScopedTask[T] = new ScopedTask[T] { val scope = s; val key = k }
final class RichSettingList[S](scope: Scope, key: AttributeKey[Seq[S]])
{
def += (value: => S): Setting[Seq[S]] = ++=(value :: Nil)
def ++=(values: => Seq[S]): Setting[Seq[S]] = (new RichSettingScoped(scope, key)) ~= (_ ++ values )
}
final class RichListTask[S](scope: Scope, key: AttributeKey[Task[Seq[S]]])
{
def += (value: => S): Setting[Task[Seq[S]]] = ++=(value :: Nil)
def ++=(values: => Seq[S]): Setting[Task[Seq[S]]] = (new RichTaskScoped(scope, key)) ~= (_ ++ values )
}
sealed abstract class RichBaseScoped[S]
{
def scope: Scope
@ -87,13 +99,12 @@ object Scoped
protected final val scopedList = scoped :^: KNil
final def :==(value: S): Setting[S] = :=(value)
final def :==(value: SettingKey[S]): Setting[S] = :-(value app identity)
final def :==(value: SettingKey[S]): Setting[S] = <<=(value(identity))
final def := (value: => S): Setting[S] = Project.value(scoped)(value)
final def :~ (f: S => S): Setting[S] = Project.update(scoped)(f)
final def :- (app: Apply[S]): Setting[S] = app toSetting scoped
final def ~= (f: S => S): Setting[S] = Project.update(scoped)(f)
final def <<= (app: Apply[S]): Setting[S] = app toSetting scoped
final def apply[T](f: S => T): Apply[T] = Apply.mk(scopedList)(hl => f(hl.head))
final def app[T](f: S => T): Apply[T] = apply(f)
final def get(settings: Settings[Scope]): Option[S] = settings.get(scope, key)
}
@ -110,10 +121,10 @@ object Scoped
def :==(value: Task[S]): ScS = Project.value(scoped)( value )
def := (value: => S): ScS = :==(task(value))
def :== (v: TaskKey[S]): ScS = Project.app(scoped, ScopedKey(scope, v.key) :^: KNil)(_.head)
def :== (v: SettingKey[S]): ScS = :-( v app const )
def :~ (f: S => S): ScS = Project.update(scoped)( _ map f )
def :== (v: SettingKey[S]): ScS = <<=( v(const))
def ~= (f: S => S): ScS = Project.update(scoped)( _ map f )
def :- (app: App[S]): ScS = app toSetting scoped
def <<= (app: App[S]): ScS = app toSetting scoped
def setting: ScopedSetting[Task[S]] = scopedSetting(scope, key)
def get(settings: Settings[Scope]): Option[Task[S]] = settings.get(scope, key)

View File

@ -65,5 +65,6 @@ final case class Attributed[D](data: D)(val metadata: AttributeMap)
}
object Attributed
{
implicit def blankSeq[T](in: Seq[T]): Seq[Attributed[T]] = in map blank
implicit def blank[T](data: T): Attributed[T] = Attributed(data)(AttributeMap.empty)
}