mirror of https://github.com/sbt/sbt.git
provide access to per-build and build-global keys from command line
[build-uri]/key for per-build */key for build-global
This commit is contained in:
parent
135609e5b0
commit
aa395583b5
|
|
@ -15,7 +15,7 @@ object Act
|
|||
val GlobalString = "*"
|
||||
|
||||
// this does not take aggregation into account
|
||||
def scopedKey(index: KeyIndex, current: ProjectRef, defaultConfigs: ProjectRef => Seq[String], keyMap: Map[String, AttributeKey[_]]): Parser[ScopedKey[_]] =
|
||||
def scopedKey(index: KeyIndex, current: ProjectRef, defaultConfigs: Option[ResolvedReference] => Seq[String], keyMap: Map[String, AttributeKey[_]]): Parser[ScopedKey[_]] =
|
||||
{
|
||||
for {
|
||||
proj <- optProjectRef(index, current)
|
||||
|
|
@ -25,7 +25,7 @@ object Act
|
|||
yield {
|
||||
val (key, conf) = keyConf
|
||||
val (task, extra) = taskExtra
|
||||
ScopedKey( Scope( Select(proj), toAxis(conf map ConfigKey.apply, Global), task, extra), key )
|
||||
ScopedKey( Scope( toAxis(proj, Global), toAxis(conf map ConfigKey.apply, Global), task, extra), key )
|
||||
}
|
||||
}
|
||||
def examplesStrict(p: Parser[String], exs: Set[String]): Parser[String] =
|
||||
|
|
@ -41,7 +41,7 @@ object Act
|
|||
def config(confs: Set[String]): Parser[Option[String]] =
|
||||
token( (examplesStrict(ID, confs) | GlobalString) <~ ':' ).?
|
||||
|
||||
def configs(explicit: Option[String], defaultConfigs: ProjectRef => Seq[String], proj: ProjectRef): List[Option[String]] =
|
||||
def configs(explicit: Option[String], defaultConfigs: Option[ResolvedReference] => Seq[String], proj: Option[ResolvedReference]): List[Option[String]] =
|
||||
explicit match
|
||||
{
|
||||
case None => None :: defaultConfigs(proj).map(c => Some(c)).toList
|
||||
|
|
@ -49,7 +49,7 @@ object Act
|
|||
case Some(_) => explicit :: Nil
|
||||
}
|
||||
|
||||
def key(index: KeyIndex, proj: ProjectRef, confs: Seq[Option[String]], keyMap: Map[String,AttributeKey[_]]): Parser[(AttributeKey[_], Option[String])] =
|
||||
def key(index: KeyIndex, proj: Option[ResolvedReference], confs: Seq[Option[String]], keyMap: Map[String,AttributeKey[_]]): Parser[(AttributeKey[_], Option[String])] =
|
||||
{
|
||||
val confMap = confs map { conf => (conf, index.keys(proj, conf)) } toMap;
|
||||
val allKeys = (Set.empty[String] /: confMap.values)(_ ++ _)
|
||||
|
|
@ -103,17 +103,22 @@ object Act
|
|||
def knownIDParser[T](knownKeys: Map[String, T]): Parser[T] =
|
||||
token(examplesStrict(ID, knownKeys.keys.toSet)) map knownKeys
|
||||
|
||||
def projectRef(index: KeyIndex, currentBuild: URI): Parser[ProjectRef] =
|
||||
def projectRef(index: KeyIndex, currentBuild: URI): Parser[Option[ResolvedReference]] =
|
||||
{
|
||||
val uris = index.buildURIs
|
||||
val build = token( '(' ~> Uri(uris).map(uri => Scope.resolveBuild(currentBuild, uri)) <~ ')') ?? currentBuild
|
||||
def projectID(uri: URI) = token( examplesStrict(ID, index projects uri) <~ '/' )
|
||||
def some[T](p: Parser[T]): Parser[Option[T]] = p map { v => Some(v) }
|
||||
|
||||
for(uri <- build; id <- projectID(uri)) yield
|
||||
ProjectRef(uri, id)
|
||||
val uris = index.buildURIs
|
||||
val resolvedURI = Uri(uris).map(uri => Scope.resolveBuild(currentBuild, uri))
|
||||
val buildRef = token( '[' ~> resolvedURI <~ "]/" ) map { uri => BuildRef(uri) }
|
||||
val global = token(GlobalString <~ '/') ^^^ None
|
||||
val build = token( '(' ~> resolvedURI <~ ')') ?? currentBuild
|
||||
val projectRef = for(uri <- build; id <- projectID(uri)) yield ProjectRef(uri, id)
|
||||
|
||||
global | some(buildRef) | some(projectRef)
|
||||
}
|
||||
def optProjectRef(index: KeyIndex, current: ProjectRef) =
|
||||
projectRef(index, current.build) ?? current
|
||||
def optProjectRef(index: KeyIndex, current: ProjectRef): Parser[Option[ResolvedReference]] =
|
||||
projectRef(index, current.build) ?? Some(current)
|
||||
|
||||
def actParser(s: State): Parser[() => State] = requireSession(s, actParser0(s))
|
||||
|
||||
|
|
@ -129,11 +134,15 @@ object Act
|
|||
def scopedKeyParser(extracted: Extracted): Parser[ScopedKey[_]] =
|
||||
{
|
||||
import extracted._
|
||||
val defaultConfs = (ref: ProjectRef) => if(Project.getProject(ref, structure).isDefined) defaultConfigs(structure.data)(ref) else Nil
|
||||
def confs(uri: URI) = if(structure.units.contains(uri)) defaultConfigs(structure.data)(ProjectRef(uri, rootProject(uri))) else Nil
|
||||
val defaultConfs: Option[ResolvedReference] => Seq[String] = {
|
||||
case None => confs(structure.root)
|
||||
case Some(BuildRef(uri)) => confs(uri)
|
||||
case Some(ref: ProjectRef) => if(Project.getProject(ref, structure).isDefined) defaultConfigs(structure.data)(ref) else Nil
|
||||
}
|
||||
scopedKey(structure.index.keyIndex, currentRef, defaultConfs, structure.index.keyMap)
|
||||
}
|
||||
|
||||
|
||||
def requireSession[T](s: State, p: => Parser[T]): Parser[T] =
|
||||
if(s get sessionSettings isEmpty) failure("No project loaded") else p
|
||||
}
|
||||
|
|
@ -9,70 +9,84 @@ package sbt
|
|||
|
||||
object KeyIndex
|
||||
{
|
||||
def empty: ExtendableKeyIndex = new KeyIndex0(Map.empty)
|
||||
def empty: ExtendableKeyIndex = new KeyIndex0(emptyBuildIndex)
|
||||
def apply(known: Seq[ScopedKey[_]]): ExtendableKeyIndex =
|
||||
(empty /: known) { _ add _ }
|
||||
def combine(indices: Seq[KeyIndex]): KeyIndex = new KeyIndex {
|
||||
def buildURIs = concat(_.buildURIs)
|
||||
def projects(uri: URI) = concat(_.projects(uri))
|
||||
def configs(proj: ResolvedReference) = concat(_.configs(proj))
|
||||
def keys(proj: ResolvedReference, conf: Option[String]) = concat(_.keys(proj, conf))
|
||||
def configs(proj: Option[ResolvedReference]) = concat(_.configs(proj))
|
||||
def keys(proj: Option[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) )
|
||||
}
|
||||
private[sbt] def getOr[A,B](m: Map[A,B], key: A, or: B): B = m.getOrElse(key, or)
|
||||
private[sbt] def keySet[A,B](m: Map[Option[A],B]): Set[A] = m.keys.flatten.toSet
|
||||
private[sbt] val emptyAKeyIndex = new AKeyIndex(Map.empty)
|
||||
private[sbt] val emptyProjectIndex = new ProjectIndex(Map.empty)
|
||||
private[sbt] val emptyBuildIndex = new BuildIndex(Map.empty)
|
||||
}
|
||||
import KeyIndex._
|
||||
|
||||
trait KeyIndex
|
||||
{
|
||||
def buildURIs: Set[URI]
|
||||
def projects(uri: URI): Set[String]
|
||||
def configs(proj: ResolvedReference): Set[String]
|
||||
def keys(proj: ResolvedReference, conf: Option[String]): Set[String]
|
||||
def configs(proj: Option[ResolvedReference]): Set[String]
|
||||
def keys(proj: Option[ResolvedReference], conf: Option[String]): Set[String]
|
||||
}
|
||||
trait ExtendableKeyIndex extends KeyIndex
|
||||
{
|
||||
def add(scoped: ScopedKey[_]): ExtendableKeyIndex
|
||||
}
|
||||
private final class KeyIndex0(val data: Map[URI, Map[Option[String], Map[ Option[String], Set[String]] ]]) extends ExtendableKeyIndex
|
||||
private final class AKeyIndex(val data: Map[ Option[String], Set[String]])
|
||||
{
|
||||
def buildURIs: Set[URI] = data.keys.toSet
|
||||
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 add(config: Option[String], key: AttributeKey[_]): AKeyIndex =
|
||||
new AKeyIndex(data updated (config, keys(config) + key.label))
|
||||
def keys(conf: Option[String]): Set[String] = getOr(data, conf, Set.empty)
|
||||
def configs: Set[String] = keySet(data)
|
||||
}
|
||||
private final class ProjectIndex(val data: Map[Option[String], AKeyIndex])
|
||||
{
|
||||
def add(id: Option[String], config: Option[String], key: AttributeKey[_]): ProjectIndex =
|
||||
new ProjectIndex( data updated(id, confIndex(id).add(config, key) ))
|
||||
def confIndex(id: Option[String]): AKeyIndex = getOr(data, id, emptyAKeyIndex)
|
||||
def projects: Set[String] = keySet(data)
|
||||
}
|
||||
private final class BuildIndex(val data: Map[Option[URI], ProjectIndex])
|
||||
{
|
||||
def add(build: Option[URI], project: Option[String], config: Option[String], key: AttributeKey[_]): BuildIndex =
|
||||
new BuildIndex( data updated(build, projectIndex(build).add(project,config,key) ) )
|
||||
def projectIndex(build: Option[URI]): ProjectIndex = getOr(data, build, emptyProjectIndex)
|
||||
def builds: Set[URI] = keySet(data)
|
||||
}
|
||||
private final class KeyIndex0(val data: BuildIndex) extends ExtendableKeyIndex
|
||||
{
|
||||
def buildURIs: Set[URI] = data.builds
|
||||
def projects(uri: URI): Set[String] = data.projectIndex(Some(uri)).projects
|
||||
def configs(project: Option[ResolvedReference]): Set[String] = confIndex(project).configs
|
||||
def keys(project: Option[ResolvedReference], conf: Option[String]): Set[String] = confIndex(project).keys(conf)
|
||||
|
||||
def confMap(proj: ResolvedReference): Map[Option[String], Set[String]] =
|
||||
def confIndex(proj: Option[ResolvedReference]): AKeyIndex =
|
||||
{
|
||||
val (build, project) = parts(proj)
|
||||
data.projectIndex(build).confIndex(project)
|
||||
}
|
||||
def parts(proj: Option[Reference]): (Option[URI], Option[String]) =
|
||||
proj match
|
||||
{
|
||||
case ProjectRef(uri, id) => get( get(data, uri), Some(id))
|
||||
case BuildRef(uri) => get( get(data, uri), None)
|
||||
case Some(ProjectRef(uri, id)) => (Some(uri), Some(id))
|
||||
case Some(BuildRef(uri)) => (Some(uri), None)
|
||||
case _ => (None, None)
|
||||
}
|
||||
|
||||
private[this] def get[A,B,C](m: Map[A,Map[B,C]], key: A): Map[B,C] = getOr(m, key, Map.empty)
|
||||
private[this] def get[A,B](m: Map[A,Set[B]], key: A): Set[B] = getOr(m, key, Set.empty)
|
||||
private[this] def getOr[A,B](m: Map[A,B], key: A, or: B): B = m.getOrElse(key, or)
|
||||
|
||||
def add(scoped: ScopedKey[_]): ExtendableKeyIndex =
|
||||
if(validID(scoped.key.label)) add0(scoped) else this
|
||||
private[this] def add0(scoped: ScopedKey[_]): ExtendableKeyIndex =
|
||||
scoped.scope match
|
||||
{
|
||||
case Scope(Select(ref: ResolvedReference), config, _, _) => addRef(ref, config, scoped.key)
|
||||
case _ => this
|
||||
}
|
||||
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: Option[String], config: Option[String], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
{
|
||||
val projectMap = get(data, uri)
|
||||
val configMap = get(projectMap, id)
|
||||
val newSet = get(configMap, config) + key.label
|
||||
val newProjectMap = projectMap.updated(id, configMap.updated(config, newSet))
|
||||
new KeyIndex0( data.updated(uri, newProjectMap) )
|
||||
val (build, project) = parts(scoped.scope.project.toOption)
|
||||
add(build, project, scoped.scope.config, scoped.key)
|
||||
}
|
||||
def add(uri: Option[URI], id: Option[String], config: ScopeAxis[ConfigKey], key: AttributeKey[_]): ExtendableKeyIndex =
|
||||
new KeyIndex0( data.add(uri, id, config match { case Select(c) => Some(c.name); case _ => None }, key) )
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue