'set every <setting>' for overriding every definition of a key. fixes #154

This commit is contained in:
Mark Harrah 2011-12-13 17:29:08 -05:00
parent 454bc6095b
commit 7347e89f73
5 changed files with 44 additions and 9 deletions

View File

@ -106,7 +106,7 @@ InspectCommand + """ [tree] <key>
"Related" shows all of the scopes in which the key is defined."""
val SetCommand = "set"
val setBrief = (SetCommand + " <setting-expression>", "Evaluates the given Setting and applies it to the current project.")
val setBrief = (SetCommand + "[every] <setting-expression>", "Evaluates the given Setting and applies it to the current project.")
val setDetailed =
SetCommand + """ <setting-expression>
@ -117,7 +117,12 @@ SetCommand + """ <setting-expression>
This command does not rebuild the build definitions, plugins, or configurations.
It does not automatically persist the setting(s) either.
To persist the setting(s), run 'session save' or 'session save-all'."""
To persist the setting(s), run 'session save' or 'session save-all'.
If 'every' is specified, the setting is evaluated in the current context
and the resulting value is used in every scope. This overrides the value
bound to the key everywhere.
"""
def SessionCommand = "session"
def sessionBrief = (SessionCommand + " <session-command>", "Manipulates session settings. For details, run 'help " + SessionCommand + "'.")

View File

@ -519,7 +519,7 @@ object Load
}
def initialSession(structure: BuildStructure, rootEval: () => Eval): SessionSettings =
new SessionSettings(structure.root, rootProjectMap(structure.units), structure.settings, Map.empty, rootEval)
new SessionSettings(structure.root, rootProjectMap(structure.units), structure.settings, Map.empty, Nil, rootEval)
def rootProjectMap(units: Map[URI, LoadedBuildUnit]): Map[URI, String] =
{

View File

@ -387,14 +387,19 @@ object BuiltinCommands
val newStructure = Load.reapply(newSession.mergeSettings, structure)( Project.showContextKey(newSession, structure) )
Project.setProject(newSession, newStructure, s)
}
def set = Command.single(SetCommand, setBrief, setDetailed) { (s, arg) =>
def set = Command(SetCommand, setBrief, setDetailed)(setParser) { case (s, (all, arg)) =>
val extracted = Project extract s
import extracted._
val settings = EvaluateConfigurations.evaluateSetting(session.currentEval(), "<set>", imports(extracted), arg, 0)(currentLoader)
val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, settings)
val newSession = session.appendSettings( append map (a => (a, arg)))
val newSession = if(all) Project.setAll(extracted, settings) else setThis(s, extracted, settings, arg)
reapply(newSession, structure, s)
}
def setThis(s: State, extracted: Extracted, settings: Seq[Project.Setting[_]], arg: String) =
{
import extracted._
val append = Load.transformSettings(Load.projectScope(currentRef), currentRef.build, rootProject, settings)
session.appendSettings( append map (a => (a, arg)))
}
def inspect = Command(InspectCommand, inspectBrief, inspectDetailed)(inspectParser) { case (s, (option, sk)) =>
logger(s).info(inspectOutput(s, option, sk))
s
@ -430,6 +435,9 @@ object BuiltinCommands
val ext = Project.extract(s)
(ext.structure, Select(ext.currentRef), ext.showKey)
}
def setParser = (s: State) => token(Space ~> flag("every" ~ Space)) ~ token(any.+.string)
import InspectOption._
def inspectParser = (s: State) => spacedInspectOptionParser(s) flatMap {
case opt @ (Uses | Definitions) => allKeyParser(s).map(key => (opt, Project.ScopedKey(Global, key)))

View File

@ -317,6 +317,27 @@ object Project extends Init[Scope] with ProjectExtra
def reverseDependencies(cMap: Map[ScopedKey[_],Flattened], scoped: ScopedKey[_]): Iterable[ScopedKey[_]] =
for( (key,compiled) <- cMap; dep <- compiled.dependencies if dep == scoped) yield key
def setAll(extracted: Extracted, settings: Seq[Setting[_]]) =
{
import extracted._
val allDefs = relation(extracted.structure, true)._1s.toSeq
val projectScope = Load.projectScope(currentRef)
def resolve(s: Setting[_]): Seq[Setting[_]] = Load.transformSettings(projectScope, currentRef.build, rootProject, s :: Nil)
def rescope[T](setting: Setting[T]): Seq[Setting[_]] =
{
val akey = setting.key.key
val global = ScopedKey(Global, akey)
val globalSetting = resolve( Project.setting(global, setting.init) )
globalSetting ++ allDefs.flatMap { d =>
if(d.key == akey)
Seq( SettingKey(akey) in d.scope <<= global)
else
Nil
}
}
extracted.session.appendRaw(settings flatMap { x => rescope(x) } )
}
object LoadAction extends Enumeration {
val Return, Current, Plugins = Value
}

View File

@ -11,14 +11,15 @@ package sbt
import SessionSettings._
final case class SessionSettings(currentBuild: URI, currentProject: Map[URI, String], original: Seq[Setting[_]], append: SessionMap, currentEval: () => Eval)
final case class SessionSettings(currentBuild: URI, currentProject: Map[URI, String], original: Seq[Setting[_]], append: SessionMap, rawAppend: Seq[Setting[_]], currentEval: () => Eval)
{
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: ProjectRef = ProjectRef(currentBuild, currentProject(currentBuild))
def appendSettings(s: Seq[SessionSetting]): SessionSettings = copy(append = modify(append, _ ++ s))
def mergeSettings: Seq[Setting[_]] = original ++ merge(append)
def clearExtraSettings: SessionSettings = copy(append = Map.empty)
def appendRaw(ss: Seq[Setting[_]]): SessionSettings = copy(rawAppend = rawAppend ++ ss)
def mergeSettings: Seq[Setting[_]] = original ++ merge(append) ++ rawAppend
def clearExtraSettings: SessionSettings = copy(append = Map.empty, rawAppend = Nil)
private[this] def merge(map: SessionMap): Seq[Setting[_]] = map.values.toSeq.flatten[SessionSetting].map(_._1)
private[this] def modify(map: SessionMap, onSeq: Endo[Seq[SessionSetting]]): SessionMap =