reimplement lighter support for controlling aggregation

This commit is contained in:
Mark Harrah 2012-01-09 08:00:29 -05:00
parent 82326cc899
commit 795b924f46
10 changed files with 67 additions and 60 deletions

View File

@ -26,7 +26,7 @@ object Act
// the index should be an aggregated index for proper tab completion
def scopedKeyAggregated(current: ProjectRef, defaultConfigs: Option[ResolvedReference] => Seq[String], structure: BuildStructure): KeysParser =
for(selected <- scopedKeySelected(structure.index.aggregateKeyIndex, current, defaultConfigs, structure.index.keyMap, structure.data) ) yield
Resolve.aggregateDeps(selected.key, selected.mask, structure.extra)
Aggregation.aggregate(selected.key, selected.mask, structure.extra)
def scopedKeySelected(index: KeyIndex, current: ProjectRef, defaultConfigs: Option[ResolvedReference] => Seq[String],
keyMap: Map[String, AttributeKey[_]], data: Settings[Scope]): Parser[ParsedKey] =

View File

@ -4,7 +4,7 @@
package sbt
import Project.ScopedKey
import Load.BuildStructure
import Load.{BuildStructure,LoadedBuildUnit}
import Keys.{aggregate, showSuccess, showTiming, timingFormat}
import sbt.complete.Parser
import java.net.URI
@ -14,13 +14,6 @@ package sbt
sealed trait Aggregation
final object Aggregation
{
def apply(dependencies: Seq[ProjectReference], transitive: Boolean = true): Aggregation = new Explicit(dependencies, transitive)
implicit def fromBoolean(b: Boolean): Aggregation = if(b) Enabled else Disabled
val Enabled = new Implicit(true)
val Disabled = new Implicit(false)
final case class Implicit(enabled: 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 printSettings[T](xs: Seq[KeyValue[T]], log: Logger)(implicit display: Show[ScopedKey[_]]) =
@ -118,4 +111,56 @@ final object Aggregation
}
private[this] def maps[T, S](vs: Values[T])(f: T => S): Values[S] =
vs map { case KeyValue(k,v) => KeyValue(k, f(v)) }
def projectAggregates[Proj](proj: Option[Reference], extra: BuildUtil[Proj], reverse: Boolean): Seq[ProjectRef] =
{
val resRef = proj.map(p => extra.projectRefFor(extra.resolveRef(p)))
resRef.toList.flatMap(ref =>
if(reverse) extra.aggregates.reverse(ref) else extra.aggregates.forward(ref)
)
}
def aggregate[T, Proj](key: ScopedKey[T], rawMask: ScopeMask, extra: BuildUtil[Proj], reverse: Boolean = false): Seq[ScopedKey[T]] =
{
val mask = rawMask.copy(project = true)
Dag.topologicalSort(key) { k =>
if(reverse)
reverseAggregatedKeys(k, extra, mask)
else if(aggregationEnabled(key, extra.data))
aggregatedKeys(k, extra, mask)
else
Nil
}
}
def reverseAggregatedKeys[T](key: ScopedKey[T], extra: BuildUtil[_], mask: ScopeMask): Seq[ScopedKey[T]] =
projectAggregates(key.scope.project.toOption, extra, reverse = true) flatMap { ref =>
val toResolve = key.scope.copy(project = Select(ref))
val resolved = Resolve(extra, Global, key.key, mask)(toResolve)
val skey = ScopedKey(resolved, key.key)
if( aggregationEnabled(skey, extra.data) ) skey :: Nil else Nil
}
def aggregatedKeys[T](key: ScopedKey[T], extra: BuildUtil[_], mask: ScopeMask): Seq[ScopedKey[T]] =
projectAggregates(key.scope.project.toOption, extra, reverse = false) map { ref =>
val toResolve = key.scope.copy(project = Select(ref))
val resolved = Resolve(extra, Global, key.key, mask)(toResolve)
ScopedKey(resolved, key.key)
}
def aggregationEnabled(key: ScopedKey[_], data: Settings[Scope]): Boolean =
Keys.aggregate in Scope.fillTaskAxis(key.scope, key.key) get data getOrElse true
def relation(units: Map[URI, LoadedBuildUnit]): Relation[ProjectRef, ProjectRef] =
{
val depPairs =
for {
(uri, unit) <- units.toIterable
project <- unit.defined.values
ref = ProjectRef(uri, project.id)
agg <- project.aggregate
} yield
(ref, agg)
Relation.empty ++ depPairs
}
}

View File

@ -4,6 +4,7 @@ import java.net.URI
final class BuildUtil[Proj](
val keyIndex: KeyIndex,
val data: Settings[Scope],
val root: URI,
val rootProjectID: URI => String,
val project: (URI, String) => Proj,

View File

@ -95,7 +95,7 @@ object Defaults extends BuildCommon
sbtPlugin :== false,
crossPaths :== true,
classpathTypes :== Set("jar", "bundle"),
aggregate :== Aggregation.Enabled,
aggregate :== true,
maxErrors :== 100,
showTiming :== true,
timingFormat :== Aggregation.defaultFormat,

View File

@ -118,7 +118,7 @@ private final class KeyIndex0(val data: BuildIndex) extends ExtendableKeyIndex
def addAggregated(scoped: ScopedKey[_], extra: BuildUtil[_]): ExtendableKeyIndex =
if(validID(scoped.key.label))
{
val aggregateProjects = Resolve.aggregateDeps(scoped, ScopeMask(), extra, reverse = true)
val aggregateProjects = Aggregation.aggregate(scoped, ScopeMask(), extra, reverse = true)
((this: ExtendableKeyIndex) /: aggregateProjects)(_ add _)
}
else

View File

@ -149,7 +149,7 @@ object Keys
val definesClass = TaskKey[DefinesClass]("defines-class", "Internal use: provides a function that determines whether the provided file contains a given class.")
val doc = TaskKey[File]("doc", "Generates API documentation.")
val copyResources = TaskKey[Seq[(File,File)]]("copy-resources", "Copies resources to the output directory.")
val aggregate = SettingKey[Aggregation]("aggregate", "Configures task aggregation.")
val aggregate = SettingKey[Boolean]("aggregate", "Configures task aggregation.")
// package keys
val packageBin = TaskKey[File]("package-bin", "Produces a main artifact, such as a binary jar.")

View File

@ -121,7 +121,7 @@ object Load
val settings = finalTransforms(buildConfigurations(loaded, getRootProject(projects), rootEval, config.injectSettings))
val delegates = config.delegates(loaded)
val data = Project.makeSettings(settings, delegates, config.scopeLocal)( Project.showLoadingKey( loaded ) )
val index = structureIndex(data, settings, loaded.extra)
val index = structureIndex(data, settings, loaded.extra(data))
val streams = mkStreams(projects, loaded.root, data)
(rootEval, new BuildStructure(projects, loaded.root, settings, data, index, streams, delegates, config.scopeLocal))
}
@ -175,7 +175,7 @@ object Load
{
val transformed = finalTransforms(newSettings)
val newData = Project.makeSettings(transformed, structure.delegates, structure.scopeLocal)
val newIndex = structureIndex(newData, transformed, index => buildUtil(structure.root, structure.units, index))
val newIndex = structureIndex(newData, transformed, index => buildUtil(structure.root, structure.units, index, newData))
val newStreams = mkStreams(structure.units, structure.root, newData)
new BuildStructure(units = structure.units, root = structure.root, settings = transformed, data = newData, index = newIndex, streams = newStreams, delegates = structure.delegates, scopeLocal = structure.scopeLocal)
}
@ -547,7 +547,7 @@ object Load
{
checkCycles(units)
def allProjectRefs: Seq[(ProjectRef, ResolvedProject)] = for( (uri, unit) <- units.toSeq; (id, proj) <- unit.defined ) yield ProjectRef(uri, id) -> proj
def extra(keyIndex: KeyIndex): BuildUtil[ResolvedProject] = buildUtil(root, units, keyIndex)
def extra(data: Settings[Scope])(keyIndex: KeyIndex): BuildUtil[ResolvedProject] = buildUtil(root, units, keyIndex, data)
}
def checkCycles(units: Map[URI, LoadedBuildUnit])
{
@ -588,15 +588,15 @@ object Load
def allProjects(build: URI): Seq[ResolvedProject] = units(build).defined.values.toSeq
def allProjectRefs: Seq[ProjectRef] = units.toSeq flatMap { case (build, unit) => refs(build, unit.defined.values.toSeq) }
def allProjectRefs(build: URI): Seq[ProjectRef] = refs(build, allProjects(build))
val extra: BuildUtil[ResolvedProject] = buildUtil(root, units, index.keyIndex)
val extra: BuildUtil[ResolvedProject] = buildUtil(root, units, index.keyIndex, data)
private[this] def refs(build: URI, projects: Seq[ResolvedProject]): Seq[ProjectRef] = projects.map { p => ProjectRef(build, p.id) }
}
def buildUtil(root: URI, units: Map[URI, LoadedBuildUnit], keyIndex: KeyIndex): BuildUtil[ResolvedProject] =
def buildUtil(root: URI, units: Map[URI, LoadedBuildUnit], keyIndex: KeyIndex, data: Settings[Scope]): BuildUtil[ResolvedProject] =
{
val getp = (build: URI, project: String) => Load.getProject(units, build, project)
val configs = (_: ResolvedProject).configurations.map(c => ConfigKey(c.name))
val aggregates = Resolve.aggregates(units)
new BuildUtil(keyIndex, root, Load getRootProject units, getp, configs, aggregates)
val aggregates = Aggregation.relation(units)
new BuildUtil(keyIndex, data, root, Load getRootProject units, getp, configs, aggregates)
}
final case class LoadBuildConfiguration(stagingDirectory: File, classpath: Seq[Attributed[File]], loader: ClassLoader, compilers: Compilers, evalPluginDef: (BuildStructure, State) => Seq[Attributed[File]], definesClass: DefinesClass, delegates: LoadedBuild => Scope => Seq[Scope], scopeLocal: ScopeLocal, injectSettings: InjectSettings, globalPlugin: Option[GlobalPlugin], log: Logger)
{

View File

@ -85,7 +85,7 @@ final case class Extracted(structure: BuildStructure, session: SessionSettings,
def runAggregated[T](key: TaskKey[T], state: State): State =
{
val rkey = resolve(key.scopedKey)
val keys = Resolve.aggregateDeps(rkey, ScopeMask(), structure.extra)
val keys = Aggregation.aggregate(rkey, ScopeMask(), structure.extra)
val tasks = Act.keyValues(structure)(keys)
Aggregation.runTasks(state, structure, tasks, Aggregation.Dummies(KNil, HNil), show = false )(showKey)
}

View File

@ -1,7 +1,6 @@
package sbt
import java.net.URI
import Load.LoadedBuildUnit
object Resolve
{
@ -43,42 +42,4 @@ object Resolve
val config: ScopeAxis[ConfigKey] = (Global +: projectConfigs) find definesKey getOrElse Global
scope.copy(config = config)
}
import Load.BuildStructure
import Project.ScopedKey
def projectAggregate[Proj](proj: Option[Reference], extra: BuildUtil[Proj], reverse: Boolean): Seq[ProjectRef] =
{
val resRef = proj.map(p => extra.projectRefFor(extra.resolveRef(p)))
resRef.toList.flatMap(ref =>
if(reverse) extra.aggregates.reverse(ref) else extra.aggregates.forward(ref)
)
}
def aggregateDeps[T, Proj](key: ScopedKey[T], rawMask: ScopeMask, extra: BuildUtil[Proj], reverse: Boolean = false): Seq[ScopedKey[T]] =
{
val mask = rawMask.copy(project = true)
Dag.topologicalSort(key) { k =>
val kref = k.scope.project
for( ref <- projectAggregate(kref.toOption, extra, reverse)) yield
{
val toResolve = k.scope.copy(project = Select(ref))
val resolved = apply(extra, Global, k.key, mask)(toResolve)
ScopedKey(resolved, k.key)
}
}
}
def aggregates(units: Map[URI, LoadedBuildUnit]): Relation[ProjectRef, ProjectRef] =
{
val depPairs =
for {
(uri, unit) <- units.toIterable
project <- unit.defined.values
ref = ProjectRef(uri, project.id)
agg <- project.aggregate
} yield
(ref, agg)
Relation.empty ++ depPairs
}
}

View File

@ -56,7 +56,7 @@ object TestBuild
val extra: BuildUtil[Proj] =
{
val getp = (build: URI, project: String) => env.buildMap(build).projectMap(project)
new BuildUtil(keyIndex, env.root.uri, env.rootProject, getp, _.configurations.map(c => ConfigKey(c.name)), const(Nil))
new BuildUtil(keyIndex, data, env.root.uri, env.rootProject, getp, _.configurations.map(c => ConfigKey(c.name)), Relation.empty)
}
lazy val allAttributeKeys: Set[AttributeKey[_]] = data.data.values.flatMap(_.keys).toSet