diff --git a/main/CommandSupport.scala b/main/CommandSupport.scala index cfb720f8a..3951885a9 100644 --- a/main/CommandSupport.scala +++ b/main/CommandSupport.scala @@ -106,7 +106,7 @@ InspectCommand + """ [tree] "Related" shows all of the scopes in which the key is defined.""" val SetCommand = "set" - val setBrief = (SetCommand + " ", "Evaluates the given Setting and applies it to the current project.") + val setBrief = (SetCommand + "[every] ", "Evaluates the given Setting and applies it to the current project.") val setDetailed = SetCommand + """ @@ -117,7 +117,12 @@ SetCommand + """ 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 + " ", "Manipulates session settings. For details, run 'help " + SessionCommand + "'.") diff --git a/main/Load.scala b/main/Load.scala index e3eac3e4b..ca2a52e7e 100644 --- a/main/Load.scala +++ b/main/Load.scala @@ -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] = { diff --git a/main/Main.scala b/main/Main.scala index 29a2a5901..787dbdd83 100644 --- a/main/Main.scala +++ b/main/Main.scala @@ -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(), "", 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))) diff --git a/main/Project.scala b/main/Project.scala index 3882634d3..68746e6b9 100755 --- a/main/Project.scala +++ b/main/Project.scala @@ -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 } diff --git a/main/SessionSettings.scala b/main/SessionSettings.scala index 260bda9c6..659d1ead2 100644 --- a/main/SessionSettings.scala +++ b/main/SessionSettings.scala @@ -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 =