2011-01-19 00:24:11 +01:00
|
|
|
/* sbt -- Simple Build Tool
|
|
|
|
|
* Copyright 2011 Mark Harrah
|
|
|
|
|
*/
|
|
|
|
|
package sbt
|
|
|
|
|
|
|
|
|
|
import java.io.File
|
|
|
|
|
import java.net.URI
|
|
|
|
|
import Project._
|
2012-07-31 17:52:10 +02:00
|
|
|
import Keys.{appConfiguration, stateBuildStructure, commands, configuration, historyPath, projectCommand, sessionSettings, shellPrompt, thisProject, thisProjectRef, watch}
|
2011-03-21 03:54:01 +01:00
|
|
|
import Scope.{GlobalScope,ThisScope}
|
2012-07-31 17:52:10 +02:00
|
|
|
import Def.{Flattened, Initialize, ScopedKey, Setting}
|
|
|
|
|
import Types.idFun
|
2011-11-20 05:56:30 +01:00
|
|
|
import complete.DefaultParsers
|
2011-01-19 00:24:11 +01:00
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
sealed trait ProjectDefinition[PR <: ProjectReference]
|
|
|
|
|
{
|
|
|
|
|
def id: String
|
|
|
|
|
def base: File
|
|
|
|
|
def configurations: Seq[Configuration]
|
2012-07-31 17:52:10 +02:00
|
|
|
def settings: Seq[Setting[_]]
|
2011-03-03 12:44:19 +01:00
|
|
|
def aggregate: Seq[PR]
|
2012-10-29 17:34:47 +01:00
|
|
|
@deprecated("Delegation between projects should be replaced by directly sharing settings.", "0.13.0")
|
2011-03-03 12:44:19 +01:00
|
|
|
def delegates: Seq[PR]
|
2011-04-08 04:48:01 +02:00
|
|
|
def dependencies: Seq[ClasspathDep[PR]]
|
2011-03-03 12:44:19 +01:00
|
|
|
def uses: Seq[PR] = aggregate ++ dependencies.map(_.project)
|
|
|
|
|
def referenced: Seq[PR] = delegates ++ uses
|
2012-11-16 15:56:49 +01:00
|
|
|
def auto: AddSettings
|
2011-03-03 12:44:19 +01:00
|
|
|
|
2011-06-16 01:08:49 +02:00
|
|
|
override final def hashCode: Int = id.hashCode ^ base.hashCode ^ getClass.hashCode
|
2011-04-08 04:48:01 +02:00
|
|
|
override final def equals(o: Any) = o match {
|
2011-06-16 01:08:49 +02:00
|
|
|
case p: ProjectDefinition[_] => p.getClass == this.getClass && p.id == id && p.base == base
|
2011-04-08 04:48:01 +02:00
|
|
|
case _ => false
|
|
|
|
|
}
|
2012-10-29 17:34:47 +01:00
|
|
|
override def toString = "Project(id: " + id + ", base: " + base + ", aggregate: " + aggregate + ", dependencies: " + dependencies + ", configurations: " + configurations + ")"
|
2011-04-08 04:48:01 +02:00
|
|
|
}
|
|
|
|
|
sealed trait Project extends ProjectDefinition[ProjectReference]
|
2011-01-19 00:24:11 +01:00
|
|
|
{
|
2012-11-16 15:56:49 +01:00
|
|
|
def copy(id: String = id, base: File = base, aggregate: => Seq[ProjectReference] = aggregate, dependencies: => Seq[ClasspathDep[ProjectReference]] = dependencies,
|
2012-07-31 17:52:10 +02:00
|
|
|
delegates: => Seq[ProjectReference] = delegates, settings: => Seq[Setting[_]] = settings, configurations: Seq[Configuration] = configurations,
|
2012-11-16 15:56:49 +01:00
|
|
|
auto: AddSettings = auto): Project =
|
|
|
|
|
Project(id, base, aggregate = aggregate, dependencies = dependencies, delegates = delegates, settings, configurations, auto)
|
2011-04-08 04:48:01 +02:00
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def resolve(resolveRef: ProjectReference => ProjectRef): ResolvedProject =
|
|
|
|
|
{
|
|
|
|
|
def resolveRefs(prs: Seq[ProjectReference]) = prs map resolveRef
|
2011-04-08 04:48:01 +02:00
|
|
|
def resolveDeps(ds: Seq[ClasspathDep[ProjectReference]]) = ds map resolveDep
|
|
|
|
|
def resolveDep(d: ClasspathDep[ProjectReference]) = ResolvedClasspathDependency(resolveRef(d.project), d.configuration)
|
2012-11-16 15:56:49 +01:00
|
|
|
resolved(id, base, aggregate = resolveRefs(aggregate), dependencies = resolveDeps(dependencies), delegates = resolveRefs(delegates), settings, configurations, auto)
|
2011-03-03 12:44:19 +01:00
|
|
|
}
|
|
|
|
|
def resolveBuild(resolveRef: ProjectReference => ProjectReference): Project =
|
|
|
|
|
{
|
|
|
|
|
def resolveRefs(prs: Seq[ProjectReference]) = prs map resolveRef
|
2011-04-08 04:48:01 +02:00
|
|
|
def resolveDeps(ds: Seq[ClasspathDep[ProjectReference]]) = ds map resolveDep
|
|
|
|
|
def resolveDep(d: ClasspathDep[ProjectReference]) = ClasspathDependency(resolveRef(d.project), d.configuration)
|
2012-11-16 15:56:49 +01:00
|
|
|
apply(id, base, aggregate = resolveRefs(aggregate), dependencies = resolveDeps(dependencies), delegates = resolveRefs(delegates), settings, configurations, auto)
|
2011-03-03 12:44:19 +01:00
|
|
|
}
|
2011-04-08 04:48:01 +02:00
|
|
|
|
2011-07-09 22:54:41 +02:00
|
|
|
def overrideConfigs(cs: Configuration*): Project = copy(configurations = Defaults.overrideConfigs(cs : _*)(configurations))
|
2011-04-08 04:48:01 +02:00
|
|
|
def dependsOn(deps: ClasspathDep[ProjectReference]*): Project = copy(dependencies = dependencies ++ deps)
|
2012-10-29 17:34:47 +01:00
|
|
|
@deprecated("Delegation between projects should be replaced by directly sharing settings.", "0.13.0")
|
2011-04-08 04:48:01 +02:00
|
|
|
def delegateTo(from: ProjectReference*): Project = copy(delegates = delegates ++ from)
|
|
|
|
|
def aggregate(refs: ProjectReference*): Project = copy(aggregate = (aggregate: Seq[ProjectReference]) ++ refs)
|
|
|
|
|
def configs(cs: Configuration*): Project = copy(configurations = configurations ++ cs)
|
2012-07-31 17:52:10 +02:00
|
|
|
def settings(ss: Setting[_]*): Project = copy(settings = (settings: Seq[Setting[_]]) ++ ss)
|
2012-11-16 15:56:49 +01:00
|
|
|
def autoSettings(select: AddSettings*): Project = copy(auto = AddSettings.seq(select : _*))
|
2011-01-19 00:24:11 +01:00
|
|
|
}
|
2011-04-08 04:48:01 +02:00
|
|
|
sealed trait ResolvedProject extends ProjectDefinition[ProjectRef]
|
|
|
|
|
|
|
|
|
|
sealed trait ClasspathDep[PR <: ProjectReference] { def project: PR; def configuration: Option[String] }
|
|
|
|
|
final case class ResolvedClasspathDependency(project: ProjectRef, configuration: Option[String]) extends ClasspathDep[ProjectRef]
|
|
|
|
|
final case class ClasspathDependency(project: ProjectReference, configuration: Option[String]) extends ClasspathDep[ProjectReference]
|
|
|
|
|
|
2012-07-31 17:52:10 +02:00
|
|
|
object Project extends ProjectExtra
|
2011-01-19 00:24:11 +01:00
|
|
|
{
|
2011-08-04 13:20:25 +02:00
|
|
|
def showContextKey(state: State): Show[ScopedKey[_]] =
|
2012-05-20 00:20:19 +02:00
|
|
|
showContextKey(state, None)
|
|
|
|
|
|
|
|
|
|
def showContextKey(state: State, keyNameColor: Option[String]): Show[ScopedKey[_]] =
|
2012-07-31 17:52:10 +02:00
|
|
|
if(isProjectLoaded(state)) showContextKey( session(state), structure(state), keyNameColor ) else Def.showFullKey
|
2012-05-20 00:20:19 +02:00
|
|
|
|
|
|
|
|
def showContextKey(session: SessionSettings, structure: BuildStructure, keyNameColor: Option[String] = None): Show[ScopedKey[_]] =
|
2012-07-31 17:52:10 +02:00
|
|
|
Def.showRelativeKey(session.current, structure.allProjects.size > 1, keyNameColor)
|
2012-05-20 00:20:19 +02:00
|
|
|
|
2012-07-31 17:52:10 +02:00
|
|
|
def showLoadingKey(loaded: LoadedBuild, keyNameColor: Option[String] = None): Show[ScopedKey[_]] =
|
|
|
|
|
Def.showRelativeKey( ProjectRef(loaded.root, loaded.units(loaded.root).rootProjects.head), loaded.allProjectRefs.size > 1, keyNameColor)
|
2011-08-04 13:20:25 +02:00
|
|
|
|
2012-11-16 15:56:49 +01:00
|
|
|
private abstract class ProjectDef[PR <: ProjectReference](val id: String, val base: File, aggregate0: => Seq[PR], dependencies0: => Seq[ClasspathDep[PR]],
|
|
|
|
|
delegates0: => Seq[PR], settings0: => Seq[Setting[_]], val configurations: Seq[Configuration], val auto: AddSettings) extends ProjectDefinition[PR]
|
2011-04-08 04:48:01 +02:00
|
|
|
{
|
|
|
|
|
lazy val aggregate = aggregate0
|
|
|
|
|
lazy val dependencies = dependencies0
|
|
|
|
|
lazy val delegates = delegates0
|
2011-06-15 01:31:54 +02:00
|
|
|
lazy val settings = settings0
|
2011-04-28 02:40:52 +02:00
|
|
|
|
|
|
|
|
Dag.topologicalSort(configurations)(_.extendsConfigs) // checks for cyclic references here instead of having to do it in Scope.delegates
|
2011-04-08 04:48:01 +02:00
|
|
|
}
|
|
|
|
|
|
2012-11-16 15:56:49 +01:00
|
|
|
def apply(id: String, base: File, aggregate: => Seq[ProjectReference] = Nil, dependencies: => Seq[ClasspathDep[ProjectReference]] = Nil,
|
|
|
|
|
delegates: => Seq[ProjectReference] = Nil, settings: => Seq[Setting[_]] = defaultSettings, configurations: Seq[Configuration] = Configurations.default,
|
|
|
|
|
auto: AddSettings = AddSettings.allDefaults): Project =
|
2011-11-20 05:56:30 +01:00
|
|
|
{
|
2012-03-09 13:08:38 +01:00
|
|
|
DefaultParsers.parse(id, DefaultParsers.ID).left.foreach(errMsg => error("Invalid project ID: " + errMsg))
|
2012-11-16 15:56:49 +01:00
|
|
|
new ProjectDef[ProjectReference](id, base, aggregate, dependencies, delegates, settings, configurations, auto) with Project
|
2011-11-20 05:56:30 +01:00
|
|
|
}
|
2011-04-08 04:48:01 +02:00
|
|
|
|
|
|
|
|
def resolved(id: String, base: File, aggregate: => Seq[ProjectRef], dependencies: => Seq[ResolvedClasspathDependency], delegates: => Seq[ProjectRef],
|
2012-11-16 15:56:49 +01:00
|
|
|
settings: Seq[Setting[_]], configurations: Seq[Configuration], auto: AddSettings): ResolvedProject =
|
|
|
|
|
new ProjectDef[ProjectRef](id, base, aggregate, dependencies, delegates, settings, configurations, auto) with ResolvedProject
|
2011-04-08 04:48:01 +02:00
|
|
|
|
2011-03-05 14:25:17 +01:00
|
|
|
def defaultSettings: Seq[Setting[_]] = Defaults.defaultSettings
|
2011-01-19 00:24:11 +01:00
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
final class Constructor(p: ProjectReference) {
|
2011-12-12 17:08:18 +01:00
|
|
|
def %(conf: Configuration): ClasspathDependency = %(conf.name)
|
|
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def %(conf: String): ClasspathDependency = new ClasspathDependency(p, Some(conf))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def getOrError[T](state: State, key: AttributeKey[T], msg: String): T = state get key getOrElse error(msg)
|
2011-04-19 00:26:57 +02:00
|
|
|
def structure(state: State): BuildStructure = getOrError(state, stateBuildStructure, "No build loaded.")
|
2011-03-02 12:46:28 +01:00
|
|
|
def session(state: State): SessionSettings = getOrError(state, sessionSettings, "Session not initialized.")
|
2011-07-24 23:36:42 +02:00
|
|
|
def isProjectLoaded(state: State): Boolean = (state has sessionSettings) && (state has stateBuildStructure)
|
2011-03-21 03:54:01 +01:00
|
|
|
|
2011-04-19 00:26:57 +02:00
|
|
|
def extract(state: State): Extracted = extract( session(state), structure(state) )
|
2011-08-04 13:20:25 +02:00
|
|
|
def extract(se: SessionSettings, st: BuildStructure): Extracted = Extracted(st, se, se.current)( showContextKey(se, st) )
|
2011-02-03 01:27:55 +01:00
|
|
|
|
2011-04-19 00:26:57 +02:00
|
|
|
def getProjectForReference(ref: Reference, structure: BuildStructure): Option[ResolvedProject] =
|
2011-03-03 12:44:19 +01:00
|
|
|
ref match { case pr: ProjectRef => getProject(pr, structure); case _ => None }
|
2011-08-14 16:53:37 +02:00
|
|
|
def getProject(ref: ProjectRef, structure: BuildStructure): Option[ResolvedProject] = getProject(ref, structure.units)
|
2012-07-31 17:52:10 +02:00
|
|
|
def getProject(ref: ProjectRef, structure: LoadedBuild): Option[ResolvedProject] = getProject(ref, structure.units)
|
|
|
|
|
def getProject(ref: ProjectRef, units: Map[URI, LoadedBuildUnit]): Option[ResolvedProject] =
|
2011-08-14 16:53:37 +02:00
|
|
|
(units get ref.build).flatMap(_.defined get ref.project)
|
2011-02-05 04:02:39 +01:00
|
|
|
|
2011-09-22 04:54:46 +02:00
|
|
|
def runUnloadHooks(s: State): State =
|
2011-02-05 04:02:39 +01:00
|
|
|
{
|
2011-04-27 03:19:56 +02:00
|
|
|
val previousOnUnload = orIdentity(s get Keys.onUnload.key)
|
2011-09-22 04:54:46 +02:00
|
|
|
previousOnUnload(s.runExitHooks())
|
|
|
|
|
}
|
|
|
|
|
def setProject(session: SessionSettings, structure: BuildStructure, s: State): State =
|
|
|
|
|
{
|
|
|
|
|
val unloaded = runUnloadHooks(s)
|
2011-04-27 03:19:56 +02:00
|
|
|
val (onLoad, onUnload) = getHooks(structure.data)
|
2011-09-25 03:18:24 +02:00
|
|
|
val newAttrs = unloaded.attributes.put(stateBuildStructure, structure).put(sessionSettings, session).put(Keys.onUnload.key, onUnload)
|
2011-04-27 03:19:56 +02:00
|
|
|
val newState = unloaded.copy(attributes = newAttrs)
|
|
|
|
|
onLoad(updateCurrent( newState ))
|
2011-02-05 04:02:39 +01:00
|
|
|
}
|
2011-04-27 03:19:56 +02:00
|
|
|
def orIdentity[T](opt: Option[T => T]): T => T = opt getOrElse idFun
|
2011-10-16 23:27:36 +02:00
|
|
|
def getHook[T](key: SettingKey[T => T], data: Settings[Scope]): T => T = orIdentity(key in GlobalScope get data)
|
2011-04-27 03:19:56 +02:00
|
|
|
def getHooks(data: Settings[Scope]): (State => State, State => State) = (getHook(Keys.onLoad, data), getHook(Keys.onUnload, data))
|
|
|
|
|
|
2011-03-03 12:44:19 +01:00
|
|
|
def current(state: State): ProjectRef = session(state).current
|
2011-07-24 23:36:42 +02:00
|
|
|
def updateCurrent(s: State): State =
|
2011-01-22 20:01:59 +01:00
|
|
|
{
|
2011-07-24 23:36:42 +02:00
|
|
|
val structure = Project.structure(s)
|
|
|
|
|
val ref = Project.current(s)
|
2011-03-03 12:44:19 +01:00
|
|
|
val project = Load.getProject(structure.units, ref.build, ref.project)
|
2011-09-03 23:30:37 +02:00
|
|
|
val msg = Keys.onLoadMessage in ref get structure.data getOrElse ""
|
2011-10-16 23:27:36 +02:00
|
|
|
if(!msg.isEmpty) s.log.info(msg)
|
2011-03-01 14:51:14 +01:00
|
|
|
def get[T](k: SettingKey[T]): Option[T] = k in ref get structure.data
|
2011-03-12 04:33:30 +01:00
|
|
|
def commandsIn(axis: ResolvedReference) = commands in axis get structure.data toList ;
|
2011-01-22 20:01:59 +01:00
|
|
|
|
2011-03-14 02:42:44 +01:00
|
|
|
val allCommands = commandsIn(ref) ++ commandsIn(BuildRef(ref.build)) ++ (commands in Global get structure.data toList )
|
2011-04-16 17:24:58 +02:00
|
|
|
val history = get(historyPath) flatMap idFun
|
2011-03-02 12:46:28 +01:00
|
|
|
val prompt = get(shellPrompt)
|
|
|
|
|
val watched = get(watch)
|
2011-03-12 04:33:30 +01:00
|
|
|
val commandDefs = allCommands.distinct.flatten[Command].map(_ tag (projectCommand, true))
|
2012-01-29 20:36:27 +01:00
|
|
|
val newDefinedCommands = commandDefs ++ BasicCommands.removeTagged(s.definedCommands, projectCommand)
|
2011-03-02 12:46:28 +01:00
|
|
|
val newAttrs = setCond(Watched.Configuration, watched, s.attributes).put(historyPath.key, history)
|
2011-03-21 22:56:41 +01:00
|
|
|
s.copy(attributes = setCond(shellPrompt.key, prompt, newAttrs), definedCommands = newDefinedCommands)
|
2011-01-22 20:01:59 +01:00
|
|
|
}
|
2011-02-22 01:35:05 +01:00
|
|
|
def setCond[T](key: AttributeKey[T], vopt: Option[T], attributes: AttributeMap): AttributeMap =
|
|
|
|
|
vopt match { case Some(v) => attributes.put(key, v); case None => attributes.remove(key) }
|
2011-08-04 13:20:25 +02:00
|
|
|
def makeSettings(settings: Seq[Setting[_]], delegates: Scope => Seq[Scope], scopeLocal: ScopedKey[_] => Seq[Setting[_]])(implicit display: Show[ScopedKey[_]]) =
|
2012-07-31 17:52:10 +02:00
|
|
|
Def.make(settings)(delegates, scopeLocal, display)
|
2011-01-22 20:01:59 +01:00
|
|
|
|
2012-01-09 14:00:29 +01:00
|
|
|
def equal(a: ScopedKey[_], b: ScopedKey[_], mask: ScopeMask): Boolean =
|
|
|
|
|
a.key == b.key && Scope.equal(a.scope, b.scope, mask)
|
|
|
|
|
|
2011-02-12 22:23:40 +01:00
|
|
|
def fillTaskAxis(scoped: ScopedKey[_]): ScopedKey[_] =
|
|
|
|
|
ScopedKey(Scope.fillTaskAxis(scoped.scope, scoped.key), scoped.key)
|
|
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def mapScope(f: Scope => Scope) = new (ScopedKey ~> ScopedKey) { def apply[T](key: ScopedKey[T]) =
|
|
|
|
|
ScopedKey( f(key.scope), key.key)
|
|
|
|
|
}
|
2011-02-23 04:36:48 +01:00
|
|
|
|
2011-01-19 00:24:11 +01:00
|
|
|
def transform(g: Scope => Scope, ss: Seq[Setting[_]]): Seq[Setting[_]] = {
|
|
|
|
|
val f = mapScope(g)
|
2011-01-24 04:34:17 +01:00
|
|
|
ss.map(_ mapKey f mapReferenced f)
|
2011-01-19 00:24:11 +01:00
|
|
|
}
|
2011-02-12 02:22:17 +01:00
|
|
|
def transformRef(g: Scope => Scope, ss: Seq[Setting[_]]): Seq[Setting[_]] = {
|
|
|
|
|
val f = mapScope(g)
|
|
|
|
|
ss.map(_ mapReferenced f)
|
|
|
|
|
}
|
2011-02-01 00:16:25 +01:00
|
|
|
|
2011-04-19 00:26:57 +02:00
|
|
|
def delegates(structure: BuildStructure, scope: Scope, key: AttributeKey[_]): Seq[ScopedKey[_]] =
|
2011-02-16 00:41:01 +01:00
|
|
|
structure.delegates(scope).map(d => ScopedKey(d, key))
|
|
|
|
|
|
2011-11-24 01:53:20 +01:00
|
|
|
def scopedKeyData(structure: BuildStructure, scope: Scope, key: AttributeKey[_]): Option[ScopedKeyData[_]] =
|
|
|
|
|
structure.data.get(scope, key) map { v => ScopedKeyData(ScopedKey(scope, key), v) }
|
|
|
|
|
|
2011-08-04 13:20:25 +02:00
|
|
|
def details(structure: BuildStructure, actual: Boolean, scope: Scope, key: AttributeKey[_])(implicit display: Show[ScopedKey[_]]): String =
|
2011-02-06 17:33:56 +01:00
|
|
|
{
|
|
|
|
|
val scoped = ScopedKey(scope,key)
|
2011-11-24 01:53:20 +01:00
|
|
|
|
|
|
|
|
val data = scopedKeyData(structure, scope, key) map {_.description} getOrElse {"No entry for key."}
|
2011-04-21 02:18:58 +02:00
|
|
|
val description = key.description match { case Some(desc) => "Description:\n\t" + desc + "\n"; case None => "" }
|
2012-01-20 14:31:36 +01:00
|
|
|
|
|
|
|
|
val providedBy = structure.data.definingScope(scope, key) match {
|
2011-04-21 02:18:58 +02:00
|
|
|
case Some(sc) => "Provided by:\n\t" + Scope.display(sc, key.label) + "\n"
|
|
|
|
|
case None => ""
|
|
|
|
|
}
|
2012-07-31 17:52:10 +02:00
|
|
|
val comp = Def.compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display)
|
2012-01-20 14:31:36 +01:00
|
|
|
val definedAt = comp get scoped map { c =>
|
2012-01-27 14:51:13 +01:00
|
|
|
def fmt(s: Setting[_]) = s.pos match {
|
2012-02-16 13:58:51 +01:00
|
|
|
case pos: FilePosition => Some(pos.path + ":" + pos.startLine)
|
2012-01-27 14:51:13 +01:00
|
|
|
case NoPosition => None
|
|
|
|
|
}
|
|
|
|
|
val posDefined = c.settings.map(fmt).flatten
|
2012-01-24 10:32:21 +01:00
|
|
|
if (posDefined.size > 0) {
|
|
|
|
|
val header = if (posDefined.size == c.settings.size) "Defined at:" else
|
|
|
|
|
"Some of the defining occurrences:"
|
2012-01-27 14:51:13 +01:00
|
|
|
header + (posDefined mkString ("\n\t", "\n\t", "\n"))
|
2012-01-20 14:31:36 +01:00
|
|
|
} else ""
|
|
|
|
|
} getOrElse ""
|
|
|
|
|
|
|
|
|
|
|
2012-07-31 17:52:10 +02:00
|
|
|
val cMap = Def.flattenLocals(comp)
|
2011-02-06 17:33:56 +01:00
|
|
|
val related = cMap.keys.filter(k => k.key == key && k.scope != scope)
|
|
|
|
|
val depends = cMap.get(scoped) match { case Some(c) => c.dependencies.toSet; case None => Set.empty }
|
2012-01-20 14:31:36 +01:00
|
|
|
|
2011-02-09 02:36:29 +01:00
|
|
|
val reverse = reverseDependencies(cMap, scoped)
|
2011-02-06 17:33:56 +01:00
|
|
|
def printScopes(label: String, scopes: Iterable[ScopedKey[_]]) =
|
2011-08-04 13:20:25 +02:00
|
|
|
if(scopes.isEmpty) "" else scopes.map(display.apply).mkString(label + ":\n\t", "\n\t", "\n")
|
2011-02-09 02:36:29 +01:00
|
|
|
|
2011-11-24 01:53:20 +01:00
|
|
|
data + "\n" +
|
2011-04-21 02:18:58 +02:00
|
|
|
description +
|
2012-01-20 14:31:36 +01:00
|
|
|
providedBy +
|
|
|
|
|
definedAt +
|
2011-02-09 02:36:29 +01:00
|
|
|
printScopes("Dependencies", depends) +
|
|
|
|
|
printScopes("Reverse dependencies", reverse) +
|
2011-02-16 00:41:01 +01:00
|
|
|
printScopes("Delegates", delegates(structure, scope, key)) +
|
2011-02-09 02:36:29 +01:00
|
|
|
printScopes("Related", related)
|
2011-02-06 17:33:56 +01:00
|
|
|
}
|
2011-11-23 06:49:27 +01:00
|
|
|
def settingGraph(structure: BuildStructure, basedir: File, scoped: ScopedKey[_])(implicit display: Show[ScopedKey[_]]): SettingGraph =
|
|
|
|
|
SettingGraph(structure, basedir, scoped, 0)
|
2011-08-04 13:20:25 +02:00
|
|
|
def graphSettings(structure: BuildStructure, basedir: File)(implicit display: Show[ScopedKey[_]])
|
2011-04-02 03:08:08 +02:00
|
|
|
{
|
|
|
|
|
def graph(actual: Boolean, name: String) = graphSettings(structure, actual, name, new File(basedir, name + ".dot"))
|
|
|
|
|
graph(true, "actual_dependencies")
|
|
|
|
|
graph(false, "declared_dependencies")
|
|
|
|
|
}
|
2011-08-04 13:20:25 +02:00
|
|
|
def graphSettings(structure: BuildStructure, actual: Boolean, graphName: String, file: File)(implicit display: Show[ScopedKey[_]])
|
2011-07-24 05:07:54 +02:00
|
|
|
{
|
|
|
|
|
val rel = relation(structure, actual)
|
2011-08-04 13:20:25 +02:00
|
|
|
val keyToString = display.apply _
|
2011-07-24 05:07:54 +02:00
|
|
|
DotGraph.generateGraph(file, graphName, rel, keyToString, keyToString)
|
|
|
|
|
}
|
2011-08-04 13:20:25 +02:00
|
|
|
def relation(structure: BuildStructure, actual: Boolean)(implicit display: Show[ScopedKey[_]]) =
|
2011-04-02 03:08:08 +02:00
|
|
|
{
|
|
|
|
|
type Rel = Relation[ScopedKey[_], ScopedKey[_]]
|
2012-07-31 17:52:10 +02:00
|
|
|
val cMap = Def.flattenLocals(Def.compiled(structure.settings, actual)(structure.delegates, structure.scopeLocal, display))
|
2011-07-24 05:07:54 +02:00
|
|
|
((Relation.empty: Rel) /: cMap) { case (r, (key, value)) =>
|
|
|
|
|
r + (key, value.dependencies)
|
|
|
|
|
}
|
2011-04-02 03:08:08 +02:00
|
|
|
}
|
2011-12-13 23:29:08 +01:00
|
|
|
|
|
|
|
|
def showDefinitions(key: AttributeKey[_], defs: Seq[Scope])(implicit display: Show[ScopedKey[_]]): String =
|
|
|
|
|
defs.map(scope => display(ScopedKey(scope, key))).sorted.mkString("\n\t", "\n\t", "\n\n")
|
|
|
|
|
def showUses(defs: Seq[ScopedKey[_]])(implicit display: Show[ScopedKey[_]]): String =
|
|
|
|
|
defs.map(display.apply).sorted.mkString("\n\t", "\n\t", "\n\n")
|
|
|
|
|
|
|
|
|
|
def definitions(structure: BuildStructure, actual: Boolean, key: AttributeKey[_])(implicit display: Show[ScopedKey[_]]): Seq[Scope] =
|
|
|
|
|
relation(structure, actual)(display)._1s.toSeq flatMap { sk => if(sk.key == key) sk.scope :: Nil else Nil }
|
|
|
|
|
def usedBy(structure: BuildStructure, actual: Boolean, key: AttributeKey[_])(implicit display: Show[ScopedKey[_]]): Seq[ScopedKey[_]] =
|
|
|
|
|
relation(structure, actual)(display).all.toSeq flatMap { case (a,b) => if(b.key == key) List[ScopedKey[_]](a) else Nil }
|
|
|
|
|
|
2011-10-01 20:39:40 +02:00
|
|
|
def reverseDependencies(cMap: Map[ScopedKey[_],Flattened], scoped: ScopedKey[_]): Iterable[ScopedKey[_]] =
|
2011-02-09 02:36:29 +01:00
|
|
|
for( (key,compiled) <- cMap; dep <- compiled.dependencies if dep == scoped) yield key
|
2011-02-27 22:28:00 +01:00
|
|
|
|
2012-07-13 19:40:59 +02:00
|
|
|
//@deprecated("Use SettingCompletions.setAll when available.", "0.13.0")
|
|
|
|
|
def setAll(extracted: Extracted, settings: Seq[Setting[_]]): SessionSettings =
|
|
|
|
|
SettingCompletions.setAll(extracted, settings).session
|
2011-12-13 23:29:08 +01:00
|
|
|
|
2012-04-07 02:28:31 +02:00
|
|
|
val ExtraBuilds = AttributeKey[List[URI]]("extra-builds", "Extra build URIs to load in addition to the ones defined by the project.")
|
|
|
|
|
def extraBuilds(s: State): List[URI] = getOrNil(s, ExtraBuilds)
|
|
|
|
|
def getOrNil[T](s: State, key: AttributeKey[List[T]]): List[T] = s get key getOrElse Nil
|
|
|
|
|
def setExtraBuilds(s: State, extra: List[URI]): State = s.put(ExtraBuilds, extra)
|
|
|
|
|
def addExtraBuilds(s: State, extra: List[URI]): State = setExtraBuilds(s, extra ::: extraBuilds(s))
|
|
|
|
|
def removeExtraBuilds(s: State, remove: List[URI]): State = updateExtraBuilds(s, _.filterNot(remove.toSet))
|
|
|
|
|
def updateExtraBuilds(s: State, f: List[URI] => List[URI]): State = setExtraBuilds(s, f(extraBuilds(s)))
|
|
|
|
|
|
2011-03-12 04:33:30 +01:00
|
|
|
object LoadAction extends Enumeration {
|
|
|
|
|
val Return, Current, Plugins = Value
|
|
|
|
|
}
|
|
|
|
|
import LoadAction._
|
2011-11-20 05:56:30 +01:00
|
|
|
import DefaultParsers._
|
2011-03-12 04:33:30 +01:00
|
|
|
|
|
|
|
|
val loadActionParser = token(Space ~> ("plugins" ^^^ Plugins | "return" ^^^ Return)) ?? Current
|
|
|
|
|
|
2011-04-21 02:18:58 +02:00
|
|
|
val ProjectReturn = AttributeKey[List[File]]("project-return", "Maintains a stack of builds visited using reload.")
|
2012-04-07 02:28:31 +02:00
|
|
|
def projectReturn(s: State): List[File] = getOrNil(s, ProjectReturn)
|
2012-03-18 00:31:04 +01:00
|
|
|
def inPluginProject(s: State): Boolean = projectReturn(s).toList.length > 1
|
2011-03-12 04:33:30 +01:00
|
|
|
def setProjectReturn(s: State, pr: List[File]): State = s.copy(attributes = s.attributes.put( ProjectReturn, pr) )
|
|
|
|
|
def loadAction(s: State, action: LoadAction.Value) = action match {
|
|
|
|
|
case Return =>
|
|
|
|
|
projectReturn(s) match
|
|
|
|
|
{
|
|
|
|
|
case current :: returnTo :: rest => (setProjectReturn(s, returnTo :: rest), returnTo)
|
|
|
|
|
case _ => error("Not currently in a plugin definition")
|
|
|
|
|
}
|
|
|
|
|
case Current =>
|
|
|
|
|
val base = s.configuration.baseDirectory
|
|
|
|
|
projectReturn(s) match { case Nil => (setProjectReturn(s, base :: Nil), base); case x :: xs => (s, x) }
|
|
|
|
|
case Plugins =>
|
|
|
|
|
val extracted = Project.extract(s)
|
|
|
|
|
val newBase = extracted.currentUnit.unit.plugins.base
|
|
|
|
|
val newS = setProjectReturn(s, newBase :: projectReturn(s))
|
|
|
|
|
(newS, newBase)
|
|
|
|
|
}
|
2011-09-22 04:54:46 +02:00
|
|
|
@deprecated("This method does not apply state changes requested during task execution. Use 'runTask' instead, which does.", "0.11.1")
|
2011-03-19 05:04:37 +01:00
|
|
|
def evaluateTask[T](taskKey: ScopedKey[Task[T]], state: State, checkCycles: Boolean = false, maxWorkers: Int = EvaluateTask.SystemProcessors): Option[Result[T]] =
|
2011-11-20 05:56:30 +01:00
|
|
|
runTask(taskKey, state, EvaluateConfig(true, EvaluateTask.defaultRestrictions(maxWorkers), checkCycles)).map(_._2)
|
|
|
|
|
def runTask[T](taskKey: ScopedKey[Task[T]], state: State, checkCycles: Boolean = false): Option[(State, Result[T])] =
|
|
|
|
|
runTask(taskKey, state, EvaluateConfig(true, EvaluateTask.restrictions(state), checkCycles))
|
|
|
|
|
def runTask[T](taskKey: ScopedKey[Task[T]], state: State, config: EvaluateConfig): Option[(State, Result[T])] =
|
2011-03-19 05:04:37 +01:00
|
|
|
{
|
|
|
|
|
val extracted = Project.extract(state)
|
2011-10-19 04:43:25 +02:00
|
|
|
EvaluateTask(extracted.structure, taskKey, state, extracted.currentRef, config)
|
2011-03-19 05:04:37 +01:00
|
|
|
}
|
2011-01-19 00:24:11 +01:00
|
|
|
|
2012-07-31 17:52:10 +02:00
|
|
|
/** Many methods were moved to Def in 0.13. This implicit makes those methods still available on Project for the transition. */
|
|
|
|
|
@inline
|
|
|
|
|
@deprecated("Use Def directly", "0.13.0")
|
|
|
|
|
implicit def projectToDef(p: Project.type): Def.type = Def
|
|
|
|
|
|
|
|
|
|
implicit def projectToRef(p: Project): ProjectReference = LocalProject(p.id)
|
|
|
|
|
|
|
|
|
|
final class RichTaskSessionVar[S](i: Initialize[Task[S]])
|
|
|
|
|
{
|
|
|
|
|
import SessionVar.{persistAndSet, resolveContext, set, transform => tx}
|
|
|
|
|
|
|
|
|
|
def updateState(f: (State, S) => State): Initialize[Task[S]] = i(t => tx(t, f))
|
|
|
|
|
def storeAs(key: TaskKey[S])(implicit f: sbinary.Format[S]): Initialize[Task[S]] = (Keys.resolvedScoped, i) { (scoped, task) =>
|
|
|
|
|
tx(task, (state, value) => persistAndSet( resolveContext(key, scoped.scope, state), state, value)(f))
|
|
|
|
|
}
|
|
|
|
|
def keepAs(key: TaskKey[S]): Initialize[Task[S]] =
|
|
|
|
|
(i, Keys.resolvedScoped)( (t,scoped) => tx(t, (state,value) => set(resolveContext(key, scoped.scope, state), state, value) ) )
|
|
|
|
|
}
|
2011-11-24 01:53:20 +01:00
|
|
|
}
|
|
|
|
|
|
2011-04-09 04:12:52 +02:00
|
|
|
trait ProjectExtra
|
2011-01-19 00:24:11 +01:00
|
|
|
{
|
2011-04-08 04:48:01 +02:00
|
|
|
implicit def configDependencyConstructor[T <% ProjectReference](p: T): Constructor = new Constructor(p)
|
|
|
|
|
implicit def classpathDependency[T <% ProjectReference](p: T): ClasspathDependency = new ClasspathDependency(p, None)
|
2011-03-03 12:44:19 +01:00
|
|
|
|
2012-07-31 17:52:10 +02:00
|
|
|
// These used to be in Project so that they didn't need to get imported (due to Initialize being nested in Project).
|
|
|
|
|
// Moving Initialize and other settings types to Def and decoupling Project, Def, and Structure means these go here for now
|
|
|
|
|
implicit def richInitializeTask[T](init: Initialize[Task[T]]): Scoped.RichInitializeTask[T] = new Scoped.RichInitializeTask(init)
|
|
|
|
|
implicit def richInitializeInputTask[T](init: Initialize[InputTask[T]]): Scoped.RichInitializeInputTask[T] = new Scoped.RichInitializeInputTask(init)
|
|
|
|
|
implicit def richInitialize[T](i: Initialize[T]): Scoped.RichInitialize[T] = new Scoped.RichInitialize[T](i)
|
|
|
|
|
|
|
|
|
|
implicit def richTaskSessionVar[T](init: Initialize[Task[T]]): Project.RichTaskSessionVar[T] = new Project.RichTaskSessionVar(init)
|
|
|
|
|
|
2011-04-09 04:12:52 +02:00
|
|
|
def inConfig(conf: Configuration)(ss: Seq[Setting[_]]): Seq[Setting[_]] =
|
|
|
|
|
inScope(ThisScope.copy(config = Select(conf)) )( (configuration :== conf) +: ss)
|
|
|
|
|
def inTask(t: Scoped)(ss: Seq[Setting[_]]): Seq[Setting[_]] =
|
|
|
|
|
inScope(ThisScope.copy(task = Select(t.key)) )( ss )
|
|
|
|
|
def inScope(scope: Scope)(ss: Seq[Setting[_]]): Seq[Setting[_]] =
|
|
|
|
|
Project.transform(Scope.replaceThis(scope), ss)
|
2011-09-22 04:54:46 +02:00
|
|
|
}
|