mirror of https://github.com/sbt/sbt.git
work on special settings, TupleN/FunctionN interface for map/flatMap
This commit is contained in:
parent
1c9caf40a3
commit
b9e4c9299b
|
|
@ -11,7 +11,7 @@ package sbt
|
|||
import scala.annotation.tailrec
|
||||
import collection.mutable
|
||||
import Compile.{Compilers,Inputs}
|
||||
import Project.{ScopedKey, Setting}
|
||||
import Project.{AppConfig, ScopedKey, Setting, ThisProject, ThisProjectRef}
|
||||
import TypeFunctions.{Endo,Id}
|
||||
import tools.nsc.reporters.ConsoleReporter
|
||||
|
||||
|
|
@ -108,9 +108,9 @@ object EvaluateTask
|
|||
val (state, dummyState) = dummy[State]("state")
|
||||
val (streams, dummyStreams) = dummy[TaskStreams]("streams")
|
||||
|
||||
def injectSettings = Seq(
|
||||
state :== dummyState,
|
||||
streams :== dummyStreams
|
||||
def injectSettings: Seq[Project.Setting[_]] = Seq(
|
||||
state(Scope.GlobalScope) :== dummyState,
|
||||
streams(Scope.GlobalScope) :== dummyStreams
|
||||
)
|
||||
|
||||
def dummy[T](name: String): (TaskKey[T], Task[T]) = (TaskKey[T](name), dummyTask(name))
|
||||
|
|
@ -195,7 +195,8 @@ object Load
|
|||
val compilers = Compile.compilers(state.configuration, log)
|
||||
val evalPluginDef = EvaluateTask.evalPluginDef(state, log) _
|
||||
val delegates = memo(defaultDelegates)
|
||||
val config = new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, delegates, EvaluateTask.injectSettings, log)
|
||||
val inject: Seq[Project.Setting[_]] = (AppConfig(Scope.GlobalScope) :== state.configuration) +: EvaluateTask.injectSettings
|
||||
val config = new LoadBuildConfiguration(stagingDirectory, classpath, loader, compilers, evalPluginDef, delegates, inject, log)
|
||||
apply(base, config)
|
||||
}
|
||||
def defaultDelegates: LoadedBuild => Scope => Seq[Scope] = (lb: LoadedBuild) => {
|
||||
|
|
@ -229,7 +230,7 @@ object Load
|
|||
val loaded = resolveProjects(load(rootBase, config))
|
||||
val projects = loaded.units
|
||||
lazy val rootEval = lazyEval(loaded.units(loaded.root).unit)
|
||||
val settings = buildConfigurations(loaded, getRootProject(projects), config.injectSettings, rootEval)
|
||||
val settings = config.injectSettings ++ buildConfigurations(loaded, getRootProject(projects), rootEval)
|
||||
val delegates = config.delegates(loaded)
|
||||
val data = Project.make(settings)(delegates)
|
||||
val index = structureIndex(data)
|
||||
|
|
@ -250,14 +251,17 @@ object Load
|
|||
}
|
||||
|
||||
def isProjectThis(s: Setting[_]) = s.key.scope.project == This
|
||||
def buildConfigurations(loaded: LoadedBuild, rootProject: URI => String, injectSettings: Seq[Setting[_]], rootEval: () => Eval): Seq[Setting[_]] =
|
||||
def buildConfigurations(loaded: LoadedBuild, rootProject: URI => String, rootEval: () => Eval): Seq[Setting[_]] =
|
||||
loaded.units.toSeq flatMap { case (uri, build) =>
|
||||
val eval = if(uri == loaded.root) rootEval else lazyEval(build.unit)
|
||||
val pluginSettings = build.unit.plugins.plugins
|
||||
val (pluginThisProject, pluginGlobal) = pluginSettings partition isProjectThis
|
||||
val projectSettings = build.defined flatMap { case (id, project) =>
|
||||
val srcs = configurationSources(project.base)
|
||||
val settings = injectSettings ++ project.settings ++ pluginThisProject ++ configurations(srcs, eval, build.imports)
|
||||
val settings =
|
||||
(ThisProject :== project) +:
|
||||
(ThisProjectRef :== ProjectRef(Some(uri), Some(id))) +:
|
||||
(project.settings ++ pluginThisProject ++ configurations(srcs, eval, build.imports))
|
||||
|
||||
// map This to thisScope, Select(p) to mapRef(uri, rootProject, p)
|
||||
transformSettings(projectScope(uri, id), uri, rootProject, settings)
|
||||
|
|
|
|||
|
|
@ -88,6 +88,10 @@ object Project extends Init[Scope]
|
|||
|
||||
val SessionKey = AttributeKey[SessionSettings]("session-settings")
|
||||
val StructureKey = AttributeKey[Load.BuildStructure]("build-structure")
|
||||
val AppConfig = SettingKey[xsbti.AppConfiguration]("app-configuration")
|
||||
val ThisProject = SettingKey[Project]("project")
|
||||
val ThisProjectRef = SettingKey[ProjectRef]("project-ref")
|
||||
|
||||
}
|
||||
|
||||
import SessionSettings._
|
||||
|
|
|
|||
|
|
@ -87,11 +87,13 @@ object Scoped
|
|||
protected final val scopedList = scoped :^: KNil
|
||||
|
||||
final def :==(value: S): Setting[S] = :=(value)
|
||||
final def :==(value: SettingKey[S]): Setting[S] = :-(value app identity)
|
||||
final def := (value: => S): Setting[S] = Project.value(scoped)(value)
|
||||
final def :~ (f: S => S): Setting[S] = Project.update(scoped)(f)
|
||||
final def :- (app: Apply[S]): Setting[S] = app toSetting scoped
|
||||
|
||||
final def apply[T](f: S => T): Apply[T] = Apply.mk(scopedList)(hl => f(hl.head))
|
||||
final def app[T](f: S => T): Apply[T] = apply(f)
|
||||
|
||||
final def get(settings: Settings[Scope]): Option[S] = settings.get(scope, key)
|
||||
}
|
||||
|
|
@ -108,10 +110,12 @@ object Scoped
|
|||
def :==(value: Task[S]): ScS = Project.value(scoped)( value )
|
||||
def := (value: => S): ScS = :==(task(value))
|
||||
def :== (v: TaskKey[S]): ScS = Project.app(scoped, ScopedKey(scope, v.key) :^: KNil)(_.head)
|
||||
def :== (v: SettingKey[S]): ScS = :-( v app const )
|
||||
def :~ (f: S => S): ScS = Project.update(scoped)( _ map f )
|
||||
|
||||
def :- (app: App[S]): ScS = app toSetting scoped
|
||||
|
||||
def setting: ScopedSetting[Task[S]] = scopedSetting(scope, key)
|
||||
def get(settings: Settings[Scope]): Option[Task[S]] = settings.get(scope, key)
|
||||
|
||||
type App[T] = Apply[Task[T]]
|
||||
|
|
@ -204,7 +208,82 @@ object Scoped
|
|||
tasks flatMapR f
|
||||
}
|
||||
}
|
||||
|
||||
// this is the least painful arrangement I came up with
|
||||
implicit def t2ToTable2[A,B](t2: (ScopedTaskable[A], ScopedTaskable[B]) ): RichTaskable2[A,B] = new RichTaskable2(t2)
|
||||
implicit def t3ToTable3[A,B,C](t3: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C]) ): RichTaskable3[A,B,C] = new RichTaskable3(t3)
|
||||
implicit def t4ToTable4[A,B,C,D](t4: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D]) ): RichTaskable4[A,B,C,D] = new RichTaskable4(t4)
|
||||
implicit def t5ToTable5[A,B,C,D,E](t5: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E]) ): RichTaskable5[A,B,C,D,E] = new RichTaskable5(t5)
|
||||
implicit def t6ToTable6[A,B,C,D,E,F](t6: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F]) ): RichTaskable6[A,B,C,D,E,F] = new RichTaskable6(t6)
|
||||
implicit def t7ToTable7[A,B,C,D,E,F,G](t7: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G]) ): RichTaskable7[A,B,C,D,E,F,G] = new RichTaskable7(t7)
|
||||
implicit def t8ToTable8[A,B,C,D,E,F,G,H](t8: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H]) ): RichTaskable8[A,B,C,D,E,F,G,H] = new RichTaskable8(t8)
|
||||
implicit def t9ToTable9[A,B,C,D,E,F,G,H,I](t9: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H], ScopedTaskable[I]) ): RichTaskable9[A,B,C,D,E,F,G,H,I] = new RichTaskable9(t9)
|
||||
|
||||
sealed abstract class RichTaskables[In <: HList](keys: KList[ScopedTaskable, In])
|
||||
{
|
||||
type App[T] = Apply[Task[T]]
|
||||
type Fun[M[_],Ret]
|
||||
protected def convertH[Ret](f: Fun[Id,Ret]): In => Ret
|
||||
protected def convertK[M[_],Ret](f: Fun[M,Ret]): KList[M,In] => Ret
|
||||
private[this] val red = reduced(keys)
|
||||
|
||||
def flatMap[T](f: Fun[Id,Task[T]]): App[T] = red.combine(Combine.flatMapR, convertH(f) compose allM)
|
||||
def flatMapR[T](f: Fun[Result,Task[T]]): App[T] = red.combine(Combine.flatMapR, convertK(f))
|
||||
def map[T](f: Fun[Id, T]): App[T] = red.combine[Id,T](Combine.mapR, convertH(f) compose allM)
|
||||
def mapR[T](f: Fun[Result,T]): App[T] = red.combine[Id,T](Combine.mapR, convertK(f))
|
||||
def flatFailure[T](f: Seq[Incomplete] => Task[T]): App[T] = red.combine(Combine.flatMapR, f compose anyFailM)
|
||||
def mapFailure[T](f: Seq[Incomplete] => T): App[T] = red.combine[Id,T](Combine.mapR, f compose anyFailM)
|
||||
}
|
||||
final class RichTaskable2[A,B](t2: (ScopedTaskable[A], ScopedTaskable[B])) extends RichTaskables(t2._1 :^: t2._2 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B]) => Ret
|
||||
protected def convertH[R](f: (A,B) => R) = { case a :+: b :+: HNil => f(a,b) }
|
||||
protected def convertK[M[_],R](f: (M[A],M[B]) => R) = { case a :^: b :^: KNil => f(a,b) }
|
||||
}
|
||||
final class RichTaskable3[A,B,C](t3: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C])) extends RichTaskables(t3._1 :^: t3._2 :^: t3._3 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C]) => Ret
|
||||
protected def convertH[R](f: Fun[Id,R]) = { case a :+: b :+: c :+: HNil => f(a,b,c) }
|
||||
protected def convertK[M[_],R](f: Fun[M,R]) = { case a :^: b :^: c :^: KNil => f(a,b,c) }
|
||||
}
|
||||
final class RichTaskable4[A,B,C,D](t4: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D])) extends RichTaskables(t4._1 :^: t4._2 :^: t4._3 :^: t4._4 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C],M[D]) => Ret
|
||||
protected def convertH[R](f: Fun[Id,R]) = { case a :+: b :+: c :+: d :+: HNil => f(a,b,c,d) }
|
||||
protected def convertK[M[_],R](f: Fun[M,R]) = { case a :^: b :^: c :^: d :^: KNil => f(a,b,c,d) }
|
||||
}
|
||||
final class RichTaskable5[A,B,C,D,E](t5: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E])) extends RichTaskables(t5._1 :^: t5._2 :^: t5._3 :^: t5._4 :^: t5._5 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C],M[D],M[E]) => Ret
|
||||
protected def convertH[R](f: Fun[Id,R]) = { case a :+: b :+: c :+: d :+: e :+: HNil => f(a,b,c,d,e) }
|
||||
protected def convertK[M[_],R](f: Fun[M,R]) = { case a :^: b :^: c :^: d :^: e :^: KNil => f(a,b,c,d,e) }
|
||||
}
|
||||
final class RichTaskable6[A,B,C,D,E,F](t6: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F])) extends RichTaskables(t6._1 :^: t6._2 :^: t6._3 :^: t6._4 :^: t6._5 :^: t6._6 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C],M[D],M[E],M[F]) => Ret
|
||||
protected def convertH[R](z: Fun[Id,R]) = { case a :+: b :+: c :+: d :+: e :+: f :+: HNil => z(a,b,c,d,e,f) }
|
||||
protected def convertK[M[_],R](z: Fun[M,R]) = { case a :^: b :^: c :^: d :^: e :^: f :^: KNil => z(a,b,c,d,e,f) }
|
||||
}
|
||||
final class RichTaskable7[A,B,C,D,E,F,G](t7: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G])) extends RichTaskables(t7._1 :^: t7._2 :^: t7._3 :^: t7._4 :^: t7._5 :^: t7._6 :^: t7._7 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C],M[D],M[E],M[F],M[G]) => Ret
|
||||
protected def convertH[R](z: Fun[Id,R]) = { case a :+: b :+: c :+: d :+: e :+: f :+: g :+: HNil => z(a,b,c,d,e,f,g) }
|
||||
protected def convertK[M[_],R](z: Fun[M,R]) = { case a :^: b :^: c :^: d :^: e :^: f :^: g :^: KNil => z(a,b,c,d,e,f,g) }
|
||||
}
|
||||
final class RichTaskable8[A,B,C,D,E,F,G,H](t8: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H])) extends RichTaskables(t8._1 :^: t8._2 :^: t8._3 :^: t8._4 :^: t8._5 :^: t8._6 :^: t8._7 :^: t8._8 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C],M[D],M[E],M[F],M[G],M[H]) => Ret
|
||||
protected def convertH[R](z: Fun[Id,R]) = { case a :+: b :+: c :+: d :+: e :+: f :+: g :+: h :+: HNil => z(a,b,c,d,e,f,g,h) }
|
||||
protected def convertK[M[_],R](z: Fun[M,R]) = { case a :^: b :^: c :^: d :^: e :^: f :^: g :^: h :^: KNil => z(a,b,c,d,e,f,g,h) }
|
||||
}
|
||||
final class RichTaskable9[A,B,C,D,E,F,G,H,I](t9: (ScopedTaskable[A], ScopedTaskable[B], ScopedTaskable[C], ScopedTaskable[D], ScopedTaskable[E], ScopedTaskable[F], ScopedTaskable[G], ScopedTaskable[H], ScopedTaskable[I])) extends RichTaskables(t9._1 :^: t9._2 :^: t9._3 :^: t9._4 :^: t9._5 :^: t9._6 :^: t9._7 :^: t9._8 :^: t9._9 :^: KNil)
|
||||
{
|
||||
type Fun[M[_],Ret] = (M[A],M[B],M[C],M[D],M[E],M[F],M[G],M[H],M[I]) => Ret
|
||||
protected def convertH[R](z: Fun[Id,R]) = { case a :+: b :+: c :+: d :+: e :+: f :+: g :+: h :+: i :+: HNil => z(a,b,c,d,e,f,g,h,i) }
|
||||
protected def convertK[M[_],R](z: Fun[M,R]) = { case a :^: b :^: c :^: d :^: e :^: f :^: g :^: h :^: i :^: KNil => z(a,b,c,d,e,f,g,h,i) }
|
||||
}
|
||||
|
||||
// this doesn't actually work for mixed KLists because the compiler crashes trying to infer the bound when constructing the KList
|
||||
implicit def richTaskableKeys[HL <: HList](in: KList[ScopedTaskable, HL]): RichTaskableKeys[HL] = new RichTaskableKeys(in)
|
||||
final class RichTaskableKeys[In <: HList](keys: KList[ScopedTaskable, In])
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,350 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import std._
|
||||
import inc.Analysis
|
||||
import TaskExtra._
|
||||
import ClasspathProject._
|
||||
import java.io.File
|
||||
import Path._
|
||||
import Types._
|
||||
import scala.xml.{Node => XNode,NodeSeq}
|
||||
|
||||
trait ClasspathProject
|
||||
{
|
||||
def name: String
|
||||
def configurations: Seq[Configuration]
|
||||
def defaultConfiguration: Option[Configuration]
|
||||
|
||||
val products: Classpath
|
||||
val unmanagedClasspath: Classpath
|
||||
val managedClasspath: Classpath
|
||||
val internalDependencyClasspath: Classpath
|
||||
|
||||
lazy val externalDependencyClasspath: Classpath =
|
||||
TaskMap { (configuration: Configuration) =>
|
||||
val un = unmanagedClasspath(configuration)
|
||||
val m = managedClasspath(configuration)
|
||||
(un, m) map concat[Attributed[File]]
|
||||
}
|
||||
|
||||
lazy val dependencyClasspath: Classpath =
|
||||
TaskMap { (configuration: Configuration) =>
|
||||
val external = externalDependencyClasspath(configuration)
|
||||
val internal = internalDependencyClasspath(configuration)
|
||||
(external, internal) map concat[Attributed[File]]
|
||||
}
|
||||
lazy val fullClasspath: Classpath =
|
||||
TaskMap { case (configuration: Configuration) =>
|
||||
val dep = dependencyClasspath(configuration)
|
||||
val prod = products(configuration)
|
||||
(dep, prod) map concat[Attributed[File]]
|
||||
}
|
||||
|
||||
lazy val configurationMap: Map[String, Configuration] =
|
||||
configurations map { conf => (conf.name, conf) } toMap;
|
||||
}
|
||||
|
||||
trait BasicClasspathProject extends ClasspathProject
|
||||
{
|
||||
val ivyConfiguration: Task[IvyConfiguration]
|
||||
val moduleSettings: Task[ModuleSettings]
|
||||
val unmanagedBase: Task[File]
|
||||
def cacheDirectory: File
|
||||
|
||||
val updateConfig: Task[UpdateConfiguration]
|
||||
|
||||
lazy val ivySbt: Task[IvySbt] =
|
||||
ivyConfiguration map { conf => new IvySbt(conf) }
|
||||
|
||||
lazy val ivyModule: Task[IvySbt#Module] =
|
||||
(ivySbt, moduleSettings) map { (ivySbt: IvySbt, settings: ModuleSettings) =>
|
||||
new ivySbt.Module(settings)
|
||||
}
|
||||
|
||||
def classpathFilter: FileFilter = GlobFilter("*.jar")
|
||||
def defaultExcludes: FileFilter
|
||||
|
||||
override lazy val managedClasspath: Classpath =
|
||||
TaskMap { configuration =>
|
||||
update map { x => attributed(x.getOrElse(configuration, error("No such configuration '" + configuration.toString + "'")) ) }
|
||||
}
|
||||
|
||||
lazy val unmanagedClasspath: Classpath =
|
||||
TaskMap { configuration =>
|
||||
unmanagedBase map { base =>
|
||||
attributed( (base * (classpathFilter -- defaultExcludes) +++
|
||||
(base / configuration.toString).descendentsExcept(classpathFilter, defaultExcludes)).getFiles.toSeq )
|
||||
}
|
||||
}
|
||||
|
||||
lazy val update = (ivyModule, updateConfig) map cachedUpdate(cacheDirectory / "update", configurationMap)
|
||||
}
|
||||
trait PublishProject extends BasicClasspathProject
|
||||
{
|
||||
val publishConfig: Task[PublishConfiguration]
|
||||
val publishLocalConfig: Task[PublishConfiguration]
|
||||
val makePomConfig: Task[MakePomConfiguration]
|
||||
def packageToPublish: Seq[Task[_]]
|
||||
|
||||
def publishMavenStyle = true
|
||||
def deliverDepends = if(publishMavenStyle) makePom :: Nil else packageToPublish
|
||||
|
||||
lazy val makePom = (ivyModule, makePomConfig) map(IvyActions.makePom) dependsOn( packageToPublish : _*)
|
||||
lazy val deliver = (ivyModule, publishConfig) map cachedPublish(cacheDirectory / "deliver")(IvyActions.deliver) dependsOn(deliverDepends : _*)
|
||||
lazy val deliverLocal = (ivyModule, publishLocalConfig) map cachedPublish(cacheDirectory / "deliver-local")(IvyActions.deliver) dependsOn(deliverDepends : _*)
|
||||
lazy val publish = (ivyModule, publishConfig) map cachedPublish(cacheDirectory / "publish")(IvyActions.publish) dependsOn(deliver)
|
||||
lazy val publishLocal = (ivyModule, publishLocalConfig) map cachedPublish(cacheDirectory / "publish-local")(IvyActions.publish) dependsOn(deliverLocal)
|
||||
}
|
||||
|
||||
trait DefaultClasspathProject extends BasicClasspathProject with PublishProject with Project
|
||||
{
|
||||
def outputDirectory: Path
|
||||
def projectID: ModuleID
|
||||
def baseResolvers: Seq[Resolver]
|
||||
lazy val resolvers: Task[Seq[Resolver]] = task { baseResolvers }
|
||||
|
||||
def otherResolvers: Seq[Resolver] = Nil
|
||||
def moduleConfigurations: Seq[ModuleConfiguration] = Nil
|
||||
|
||||
def retrievePattern = "[type]/[organisation]/[module]/[artifact](-[revision])(-[classifier]).[ext]"
|
||||
override lazy val updateConfig: Task[UpdateConfiguration] = retrieveConfig map { rConf =>
|
||||
new UpdateConfiguration(rConf, UpdateLogging.Quiet)
|
||||
}
|
||||
lazy val retrieveConfig: Task[Option[RetrieveConfiguration]] = task {
|
||||
None//Some(new RetrieveConfiguration(managedDependencyPath asFile, retrievePattern, true))
|
||||
}
|
||||
|
||||
def offline: Boolean = false
|
||||
def paths: IvyPaths = new IvyPaths(info.projectDirectory, None)
|
||||
|
||||
lazy val ivyConfiguration: Task[IvyConfiguration] = resolvers map { rs =>
|
||||
// TODO: log should be passed directly to IvyActions and pulled from Streams
|
||||
new InlineIvyConfiguration(paths, rs, otherResolvers, moduleConfigurations, offline, Some(info.globalLock), ConsoleLogger())
|
||||
}
|
||||
|
||||
def libraryDependencies: Seq[ModuleID] = ReflectUtilities.allVals[ModuleID](this).toSeq.map(_._2)
|
||||
|
||||
def managedDependencyPath: Path = info.projectDirectory / "lib_managed"
|
||||
def dependencyPath: Path = info.projectDirectory / "lib"
|
||||
|
||||
def ivyXML: NodeSeq = NodeSeq.Empty
|
||||
def defaultConfiguration: Option[Configuration] = None
|
||||
def ivyScala: Option[IvyScala] = None
|
||||
def ivyValidate: Boolean = false
|
||||
def moduleID = normalizedName
|
||||
|
||||
def pomFile: File
|
||||
def publishTo: Resolver = error("Repository for publishing is not specified.")
|
||||
|
||||
lazy val internalDependencyClasspath: Classpath = internalDependencies(this)
|
||||
|
||||
lazy val unmanagedBase = task { dependencyPath.asFile }
|
||||
|
||||
lazy val moduleSettings: Task[ModuleSettings] = task {
|
||||
new InlineConfiguration(projectID, libraryDependencies, ivyXML, configurations, defaultConfiguration, ivyScala, ivyValidate)
|
||||
}
|
||||
|
||||
lazy val publishConfig = task { publishConfiguration( publishPatterns(outputDirectory), resolverName = publishTo.name ) }
|
||||
lazy val publishLocalConfig = task { publishConfiguration( publishPatterns(outputDirectory, true) ) }
|
||||
lazy val makePomConfig = task { makePomConfiguration(pomFile) }
|
||||
}
|
||||
trait MultiClasspathProject extends DefaultClasspathProject
|
||||
{
|
||||
def dependencies: Seq[ProjectDependency.Classpath]
|
||||
def name: String
|
||||
def organization: String
|
||||
def version: String
|
||||
def pomFile: File = outputDirectory / (moduleID + "-" + version + ".pom")
|
||||
def artifacts: Seq[Artifact] = Nil
|
||||
|
||||
def projectDependencies: Seq[ModuleID] =
|
||||
resolvedDependencies(this) collect { case (p: DefaultClasspathProject, conf) => p.projectID.copy(configurations = conf) }
|
||||
|
||||
lazy val projectResolver =
|
||||
depMap(this) map { m =>
|
||||
new RawRepository(new ProjectResolver("inter-project", m))
|
||||
}
|
||||
|
||||
override def projectID = ModuleID(organization, moduleID, version).cross(true).artifacts(artifacts.toSeq : _*)
|
||||
override def libraryDependencies: Seq[ModuleID] = super.libraryDependencies ++ projectDependencies
|
||||
|
||||
override lazy val resolvers: Task[Seq[Resolver]] = projectResolver map { _ +: baseResolvers }
|
||||
}
|
||||
|
||||
trait ReflectiveClasspathProject extends DefaultClasspathProject
|
||||
{
|
||||
private[this] def vals[T: Manifest] = ReflectUtilities.allVals[T](this).toSeq.map(_._2)
|
||||
def configurations: Seq[Configuration] = vals[Configuration] ++ Configurations.defaultMavenConfigurations
|
||||
def baseResolvers: Seq[Resolver] = Resolver.withDefaultResolvers(vals[Resolver] )
|
||||
}
|
||||
|
||||
import org.apache.ivy.core.module
|
||||
import module.id.ModuleRevisionId
|
||||
import module.descriptor.ModuleDescriptor
|
||||
|
||||
object ClasspathProject
|
||||
{
|
||||
type Classpath = Configuration => Task[Seq[Attributed[File]]]
|
||||
|
||||
val Analyzed = AttributeKey[Analysis]("analysis")
|
||||
|
||||
def attributed[T](in: Seq[T]): Seq[Attributed[T]] = in map Attributed.blank
|
||||
|
||||
def analyzed[T](data: T, analysis: Analysis) = Attributed.blank(data).put(Analyzed, analysis)
|
||||
|
||||
def analyzed(compile: Task[Analysis], inputs: Task[Compile.Inputs]): Task[Attributed[File]] =
|
||||
(compile, inputs) map { case analysis :+: i :+: HNil =>
|
||||
analyzed(i.config.classesDirectory, analysis)
|
||||
}
|
||||
|
||||
def makeProducts(compile: Task[Analysis], inputs: Task[Compile.Inputs], name: String, prefix: String): Task[Seq[Attributed[File]]] =
|
||||
{
|
||||
def mkName(postfix: String) = name + "/" + prefix + postfix
|
||||
analyzed(compile, inputs) named(mkName("analyzed")) map { _ :: Nil } named(mkName("products"))
|
||||
}
|
||||
|
||||
def concat[A]: (Seq[A], Seq[A]) => Seq[A] = _ ++ _
|
||||
|
||||
def extractAnalysis[T](a: Attributed[T]): (T, Analysis) =
|
||||
(a.data, a.metadata get Analyzed getOrElse Analysis.Empty)
|
||||
|
||||
def analysisMap[T](cp: Seq[Attributed[T]]): Map[T, Analysis] =
|
||||
(cp map extractAnalysis).toMap
|
||||
|
||||
def data[T](in: Seq[Attributed[T]]): Seq[T] = in.map(_.data)
|
||||
def taskData[T](in: Task[Seq[Attributed[T]]]): Task[Seq[T]] = in map data
|
||||
|
||||
def depMap(root: Project): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
||||
depMap(MultiProject.topologicalSort(root).dropRight(1) collect { case cp: DefaultClasspathProject => cp })
|
||||
|
||||
def depMap(projects: Seq[DefaultClasspathProject]): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
|
||||
projects.map( _.ivyModule ).join.map { mods =>
|
||||
(mods.map{ mod =>
|
||||
val md = mod.moduleDescriptor
|
||||
(md.getModuleRevisionId, md)
|
||||
}).toMap
|
||||
}
|
||||
|
||||
def resolvedDependencies(p: Project): Seq[(Project, Option[String])] =
|
||||
p.dependencies map { cp =>
|
||||
(resolveProject(cp.project, p), cp.configuration)
|
||||
}
|
||||
|
||||
def resolveProject(e: Either[File, Project], context: Project): Project =
|
||||
e match {
|
||||
case Left(extPath) => context.info.externals(extPath)
|
||||
case Right(proj) => proj
|
||||
}
|
||||
|
||||
def mapped(c: String, mapping: Option[String], default: String)(errMsg: => String): String =
|
||||
parseSimpleConfigurations(mapping getOrElse default).getOrElse(c, errMsg)
|
||||
def internalDependencies(project: Project): Classpath =
|
||||
TaskMap { (conf: Configuration) =>
|
||||
val visited = asSet(new java.util.LinkedHashSet[(Project,String)])
|
||||
def visit(p: Project, c: String)
|
||||
{
|
||||
val applicableConfigs = allConfigs(p, c)
|
||||
for(ac <- applicableConfigs)
|
||||
visited add (p, ac)
|
||||
|
||||
for( (dep, confMapping) <- resolvedDependencies(p))
|
||||
{
|
||||
val depConf = mapped(c, confMapping, defaultConfiguration(dep).toString) { missingMapping(p.name, dep.name, c) }
|
||||
if( ! visited( (dep, depConf) ) )
|
||||
visit(dep, depConf)
|
||||
}
|
||||
}
|
||||
visit(project, conf.name)
|
||||
|
||||
val productsTasks = asSet(new java.util.LinkedHashSet[Task[Seq[Attributed[File]]]])
|
||||
for( (dep: ClasspathProject, c) <- visited )
|
||||
if( (dep ne project) || conf.name != c )
|
||||
productsTasks += products(dep, c)
|
||||
|
||||
def name(action: String) = project.name + "/" + conf + "/" + action + "-products"
|
||||
(productsTasks.toSeq.join) named(name("join")) map(_.flatten) named(name("flatten"))
|
||||
}
|
||||
|
||||
def parseSimpleConfigurations(confString: String): Map[String, String] =
|
||||
confString.split(";").flatMap( conf =>
|
||||
trim(conf.split("->",2)) match {
|
||||
case x :: Nil => for(a <- parseList(x)) yield (a,a)
|
||||
case x :: y :: Nil => for(a <- parseList(x); b <- parseList(x)) yield (a,b)
|
||||
case _ => error("Invalid configuration '" + conf + "'") // shouldn't get here
|
||||
}
|
||||
).toMap
|
||||
|
||||
def parseList(s: String): Seq[String] = trim(s split ",")
|
||||
private def trim(a: Array[String]): List[String] = a.toList.map(_.trim)
|
||||
|
||||
def missingMapping(from: String, to: String, conf: String) =
|
||||
error("No configuration mapping defined from '" + from + "' to '" + to + "' for '" + conf + "'")
|
||||
def missingConfiguration(in: String, conf: String) =
|
||||
error("Configuration '" + conf + "' not defined in '" + in + "'")
|
||||
def allConfigs(dep: Project, conf: String): Seq[String] =
|
||||
dep match {
|
||||
case cp: ClasspathProject => Dag.topologicalSort(configuration(cp, conf))(_.extendsConfigs).map(_.name)
|
||||
case _ => Nil
|
||||
}
|
||||
def configuration(dep: ClasspathProject, conf: String): Configuration =
|
||||
dep.configurationMap.getOrElse(conf,missingConfiguration(dep.name, conf))
|
||||
def products(dep: ClasspathProject, conf: String) =
|
||||
dep.products(configuration(dep, conf))
|
||||
def defaultConfiguration(p: Project): Configuration =
|
||||
p match
|
||||
{
|
||||
case cp: ClasspathProject => cp.defaultConfiguration getOrElse Configurations.Default
|
||||
case _ => Configurations.Default
|
||||
}
|
||||
|
||||
def makePomConfiguration(file: File, configurations: Option[Iterable[Configuration]] = None, extra: NodeSeq = NodeSeq.Empty, process: XNode => XNode = n => n, filterRepositories: MavenRepository => Boolean = _ => true) =
|
||||
new MakePomConfiguration(file, configurations, extra, process, filterRepositories)
|
||||
|
||||
def publishConfiguration(patterns: PublishPatterns, resolverName: String = "local", status: String = "release", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) =
|
||||
new PublishConfiguration(patterns, status, resolverName, None, logging)
|
||||
|
||||
def publishPatterns(outputPath: Path, publishIvy: Boolean = false): PublishPatterns =
|
||||
{
|
||||
val deliverPattern = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath
|
||||
val srcArtifactPatterns: Seq[String] =
|
||||
{
|
||||
val pathPatterns =
|
||||
(outputPath / "[artifact]-[revision]-[type](-[classifier]).[ext]") ::
|
||||
(outputPath / "[artifact]-[revision](-[classifier]).[ext]") ::
|
||||
Nil
|
||||
pathPatterns.map(_.absolutePath)
|
||||
}
|
||||
new PublishPatterns( if(publishIvy) Some(deliverPattern) else None, srcArtifactPatterns)
|
||||
}
|
||||
|
||||
import Cache._
|
||||
import Types._
|
||||
import CacheIvy.{classpathFormat, publishIC, updateIC}
|
||||
|
||||
def cachedUpdate(cacheFile: File, configMap: Map[String, Configuration]): (IvySbt#Module :+: UpdateConfiguration :+: HNil) => Map[Configuration, Seq[File]] =
|
||||
{ case module :+: config :+: HNil =>
|
||||
implicit val updateCache = updateIC
|
||||
val f = cached(cacheFile) { (conf: IvyConfiguration, settings: ModuleSettings, config: UpdateConfiguration) =>
|
||||
println("Updating...")
|
||||
val r = IvyActions.update(module, config)
|
||||
println("Done updating.")
|
||||
r
|
||||
}
|
||||
val classpaths = f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)
|
||||
val confMap = configMap
|
||||
classpaths map { case (key, value) => (confMap(key), value) } toMap;
|
||||
}
|
||||
|
||||
// can't cache deliver/publish easily since files involved are hidden behind patterns. publish will be difficult to verify target-side anyway
|
||||
def cachedPublish(cacheFile: File)(g: (IvySbt#Module, PublishConfiguration) => Unit): (IvySbt#Module :+: PublishConfiguration :+: HNil) => Unit =
|
||||
{ case module :+: config :+: HNil =>
|
||||
/* implicit val publishCache = publishIC
|
||||
val f = cached(cacheFile) { (conf: IvyConfiguration, settings: ModuleSettings, config: PublishConfiguration) =>*/
|
||||
g(module, config)
|
||||
/*}
|
||||
f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)*/
|
||||
}
|
||||
}
|
||||
|
|
@ -1,264 +0,0 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import std._
|
||||
import Path._
|
||||
import TaskExtra._
|
||||
import GlobFilter._
|
||||
import Transform.Context
|
||||
import inc.Analysis
|
||||
import build.{Auto, Build}
|
||||
import xsbti.AppConfiguration
|
||||
import MultiProject.transformName
|
||||
|
||||
import java.io.File
|
||||
import annotation.tailrec
|
||||
|
||||
object MultiProject
|
||||
{
|
||||
val ScalaVersion = AttributeKey[String]("scala-version")
|
||||
|
||||
val defaultExcludes: FileFilter = (".*" - ".") || HiddenFileFilter
|
||||
def descendents(base: PathFinder, select: FileFilter) = base.descendentsExcept(select, defaultExcludes)
|
||||
def children(base: PathFinder, select: FileFilter) = base * (select -- defaultExcludes)
|
||||
def projectClassName = classOf[Project].getName
|
||||
|
||||
def projectStandard(base: Path) = base / "project"
|
||||
def projectHidden(base: Path) = base / ".sbt"
|
||||
def selectProjectDir(base: Path) =
|
||||
{
|
||||
val a = projectHidden(base)
|
||||
val b = projectStandard(base)
|
||||
if(a.exists) a else b
|
||||
}
|
||||
|
||||
def crossPath(base: Path, instance: ScalaInstance) = base / ("scala_" + instance.actualVersion)
|
||||
|
||||
def construct[T <: AnyRef](arg: T)(implicit mf: Manifest[T]): Class[_] => Any = clazz =>
|
||||
Build.constructor(clazz, mf.erasure) match {
|
||||
case Some(c) => c.newInstance(arg)
|
||||
case None => error("Couldn't find constructor with one argument of type " + mf.toString)
|
||||
}
|
||||
|
||||
// externals must not be evaluated until after _all_ projects have been loaded
|
||||
def load(configuration: AppConfiguration, log: Logger, externals: ExternalProjects)(base: File): Project =
|
||||
{
|
||||
if(!base.isDirectory) throw new build.BuildException(base + " is not a project directory")
|
||||
val projectDir = selectProjectDir(base)
|
||||
val buildDir = projectDir / "build"
|
||||
val srcMain = buildDir / "src" / "main"
|
||||
val javaSrcBase = srcMain / "java"
|
||||
val sources = children(buildDir +++ projectDir, "*.scala") +++ descendents(buildDir / "scala" +++ buildDir / "java", "*.scala" | "*.java")
|
||||
val classpath = configuration.provider.mainClasspath.toSeq
|
||||
val compilers = Compile.compilers(configuration, log)
|
||||
val target = crossPath(buildDir / "target", compilers.scalac.scalaInstance)
|
||||
val inputs = Compile.inputs(classpath, sources.getFiles.toSeq, target, Nil, Nil, javaSrcBase :: Nil, Compile.DefaultMaxErrors)(compilers, log)
|
||||
|
||||
val analysis = Compile(inputs, log)
|
||||
val info = ProjectInfo(None, base, projectDir, Nil, None)(configuration, analysis, inputs, load(configuration, log, externals), externals)
|
||||
|
||||
val discovered = Build.discover(analysis, Some(false), Auto.Subclass, projectClassName)
|
||||
val discoveredOrDefault = if(discovered.isEmpty) List(build.ToLoad("sbt.DefaultProject", false)) else discovered
|
||||
val toLoad = Build.check(discoveredOrDefault, false)
|
||||
Build.binaries(inputs.config.classpath, toLoad, getClass.getClassLoader)(construct(info)).head.asInstanceOf[Project]
|
||||
}
|
||||
|
||||
def loadExternals(from: Seq[Project], loadImpl: File => Project): Map[File, Project] =
|
||||
{
|
||||
def load(loaded: Map[File, Project], file: File): Map[File, Project] =
|
||||
(loaded get file) match
|
||||
{
|
||||
case None => doLoad(loaded, file)
|
||||
case Some(p) => loaded
|
||||
}
|
||||
def doLoad(loaded: Map[File, Project], file: File): Map[File, Project] =
|
||||
{
|
||||
val loadedProject = loadImpl(file)
|
||||
val newMap = loaded.updated(file, loadedProject)
|
||||
loadAll( externals(loadedProject :: Nil), newMap )
|
||||
}
|
||||
def loadAll(files: Set[File], loaded: Map[File, Project]): Map[File, Project] = (loaded /: files)(load)
|
||||
|
||||
loadAll( externals(from) , Map.empty)
|
||||
}
|
||||
|
||||
def externals(containers: Seq[Project]): Set[File] =
|
||||
{
|
||||
def exts(containers: Seq[Project]): Seq[File] =
|
||||
containers flatMap { container => externalProjects(container) ++ exts(internalProjects(container)) }
|
||||
exts(containers).toSet
|
||||
}
|
||||
def externalProjects(p: Project) = lefts( allDependencies(p) )
|
||||
def internalProjects(p: Project) = rights( allDependencies(p) )
|
||||
def allDependencies(p: Project) = (p.aggregate ++ p.dependencies).map(_.project)
|
||||
|
||||
def internalTopologicalSort(root: Project): Seq[Project] =
|
||||
Dag.topologicalSort(root)(internalProjects)
|
||||
|
||||
def topologicalSort(root: Project): Seq[Project] = topologicalSort(root, root.info.externals)
|
||||
def topologicalSort(root: Project, resolveExternal: File => Project): Seq[Project] =
|
||||
Dag.topologicalSort(root) { p =>
|
||||
(externalProjects(p) map resolveExternal) ++ internalProjects(p)
|
||||
}
|
||||
|
||||
def makeContext(root: Project) =
|
||||
{
|
||||
val contexts = topologicalSort(root) map { p => (p, ReflectiveContext(p, p.name, root)) }
|
||||
val externals = root.info.externals
|
||||
def subs(f: Project => Seq[ProjectDependency]): Project => Seq[Project] = p =>
|
||||
f(p) map( _.project match { case Left(path) => externals(path); case Right(proj) => proj } )
|
||||
MultiContext(contexts, root)(subs(_.aggregate), subs(_.dependencies) )
|
||||
}
|
||||
|
||||
def lefts[A,B](e: Seq[Either[A,B]]):Seq[A] = e collect { case Left(l) => l }
|
||||
def rights[A,B](e: Seq[Either[A,B]]):Seq[B] = e collect { case Right(r)=> r }
|
||||
|
||||
def transformName(s: String) =
|
||||
{
|
||||
val parts = s.split("-+")
|
||||
(parts.take(1) ++ parts.drop(1).map(_.capitalize)).mkString
|
||||
}
|
||||
}
|
||||
|
||||
object MultiContext
|
||||
{
|
||||
def identityMap[A,B](in: Iterable[(A,B)]): collection.Map[A,B] =
|
||||
{
|
||||
import collection.JavaConversions._
|
||||
val map: collection.mutable.Map[A, B] = new java.util.IdentityHashMap[A,B]
|
||||
for( (a,b) <- in) map(a) = b
|
||||
map
|
||||
}
|
||||
|
||||
def fun[A,B](map: collection.Map[A,B]): A => Option[B] = map get _
|
||||
def apply[Owner <: AnyRef](contexts: Iterable[(Owner, Context[Owner])], root: Owner)(agg: Owner => Iterable[Owner], deps: Owner => Iterable[Owner]): Context[Owner] = new Context[Owner]
|
||||
{
|
||||
val ownerReverse = (for( (owner, context) <- contexts; name <- context.ownerName(owner).toList) yield (name, owner) ).toMap
|
||||
val ownerMap = identityMap[Task[_],Owner]( for((owner, context) <- contexts; task <- context.allTasks(owner) ) yield (task, owner) )
|
||||
val context = identityMap(contexts)
|
||||
def subMap(f: Owner => Iterable[Owner]) = identityMap( contexts.map { case (o,_) => (o,f(o)) })
|
||||
val aggMap = subMap(agg)
|
||||
val depMap = subMap(deps)
|
||||
|
||||
def rootOwner: Owner = root
|
||||
def allTasks(owner: Owner): Iterable[Task[_]] = context(owner).allTasks(owner)
|
||||
def ownerForName(name: String): Option[Owner] = ownerReverse get name
|
||||
val staticName: Task[_] => Option[String] = t => owner(t) flatMap { o => context(o).staticName(t) }
|
||||
val ownerName = (o: Owner) => context(o).ownerName(o)
|
||||
val owner = (t: Task[_]) => ownerMap.get(t)
|
||||
val aggregate = (o: Owner) => (aggMap get o).toList.flatten
|
||||
def dependencies(o: Owner): Iterable[Owner] = (depMap get o).toList.flatten
|
||||
val static = (o: Owner, s: String) => context(o).static(o, s)
|
||||
}
|
||||
}
|
||||
final class MultiNavigation(val self: Project, val selectFun: (Project, Project, State) => State, val selectedProject: Project, val initialProject: Project) extends Navigation
|
||||
{
|
||||
type Project = sbt.Project
|
||||
def parent = self.info.parent map nav
|
||||
def name = self.name
|
||||
def select(s: State): State = if(selectedProject == self) s else selectFun(self, initialProject, s)
|
||||
@tailrec final lazy val root: MultiNavigation = parent match { case Some(p) => p.root; case None => this }
|
||||
def initial = nav(initialProject)
|
||||
def closure = projectClosure map nav
|
||||
|
||||
def selected = nav(selectedProject)
|
||||
|
||||
def projectClosure: Seq[Project] = MultiProject.topologicalSort(initialProject)
|
||||
|
||||
private val nav = (p: Project) => new MultiNavigation(p, selectFun, selectedProject, initialProject)
|
||||
}
|
||||
final class MultiWatched(val self: Project) extends Watched
|
||||
{
|
||||
def watched(p: Project): Seq[Watched] = MultiProject.topologicalSort(p)
|
||||
def sourcePaths(p: Project): PathFinder = (Path.emptyPathFinder /: watched(p))(_ +++ _.watchPaths)
|
||||
override def watchPaths = sourcePaths(self)
|
||||
override def terminateWatch(key: Int): Boolean = self.terminateWatch(key)
|
||||
}
|
||||
trait Project extends Tasked with ConsoleTask with Watched
|
||||
{
|
||||
val info: ProjectInfo
|
||||
|
||||
def name: String = info.name getOrElse error("'name' not overridden")
|
||||
def normalizedName: String = StringUtilities.normalize(name)
|
||||
|
||||
def base = info.projectDirectory
|
||||
def outputRootPath = base / "target"
|
||||
def historyPath: Option[File] = Some(outputRootPath / ".history")
|
||||
def streamBase = outputRootPath / "streams"
|
||||
|
||||
implicit def streams = Dummy.Streams
|
||||
def input = Dummy.In
|
||||
def state = Dummy.State
|
||||
def context = Dummy.Context
|
||||
|
||||
def aggregate: Seq[ProjectDependency.Execution] = info.dependencies collect { case ex: ProjectDependency.Execution => ex }
|
||||
def dependencies: Seq[ProjectDependency.Classpath] = info.dependencies collect { case cp: ProjectDependency.Classpath => cp }
|
||||
|
||||
type Task[T] = sbt.Task[T]
|
||||
def act(input: Input, state: State): Option[(Task[State], Execute.NodeView[Task])] =
|
||||
{
|
||||
import Dummy._
|
||||
val context = MultiProject.makeContext(this)
|
||||
val dummies = new Transform.Dummies(In, State, Streams, Context)
|
||||
def name(t: Task[_]): String = context.staticName(t.original) getOrElse std.Streams.name(t)
|
||||
val mklog = LogManager.construct(context)
|
||||
def getOwner(t: Task[_]) = context.owner(t.original).getOrElse(error("No owner for " + name(t.original) + "\n\t" + t.original))
|
||||
val actualStreams = std.Streams(t => getOwner(t).streamBase / name(t), mklog )
|
||||
val injected = new Transform.Injected( input, state, actualStreams )
|
||||
context.static(this, transformName(input.name)) map { t => (t.merge.map(_ => state), Transform(dummies, injected, context) ) }
|
||||
}
|
||||
|
||||
def help: Seq[Help] = Nil
|
||||
}
|
||||
trait ProjectExtra
|
||||
{
|
||||
val info: ProjectInfo
|
||||
/** Converts a String to a path relative to the project directory of this project. */
|
||||
implicit def path(component: String): Path = info.projectDirectory / component
|
||||
/** Converts a String to a simple name filter. * has the special meaning: zero or more of any character */
|
||||
implicit def globFilter(simplePattern: String): NameFilter = GlobFilter(simplePattern)
|
||||
def defaultExcludes: FileFilter = MultiProject.defaultExcludes
|
||||
def descendents(path: PathFinder, filter: FileFilter): PathFinder = path.descendentsExcept(filter, defaultExcludes)
|
||||
}
|
||||
trait ReflectiveProject extends Project
|
||||
{
|
||||
private[this] def vals[T: Manifest] = ReflectUtilities.allVals[T](this).toSeq.map(_._2)
|
||||
override def aggregate: Seq[ProjectDependency.Execution] = vals[ProjectDependency.Execution] ++ vals[Project].map(p => ProjectDependency.Execution(Right(p))) ++ super.aggregate
|
||||
override def dependencies: Seq[ProjectDependency.Classpath] = vals[ProjectDependency.Classpath] ++ super.dependencies
|
||||
}
|
||||
trait ConsoleTask
|
||||
{
|
||||
val info: ProjectInfo
|
||||
lazy val projectConsole = task { Console.sbtDefault(info.compileInputs, this)(ConsoleLogger()) }
|
||||
}
|
||||
|
||||
trait ProjectConstructors extends Project
|
||||
{
|
||||
val info: ProjectInfo
|
||||
//def project(base: Path, name: String, deps: ProjectDependency*): Project = project(path, name, info => new DefaultProject(info), deps: _* )
|
||||
def project[P <: Project](path: Path, name: String, construct: ProjectInfo => P, deps: ProjectDependency*): P =
|
||||
construct( info.copy(Some(name), projectDirectory = path.asFile, parent = Some(this), dependencies = deps)() )
|
||||
|
||||
def project(base: Path): ProjectDependency.Execution = new ProjectDependency.Execution(Left(base.asFile))
|
||||
|
||||
implicit def defaultProjectDependency(p: Project): ProjectDependency = new ProjectDependency.Classpath(Right(p), None)
|
||||
|
||||
implicit def dependencyConstructor(p: Project): ProjectDependencyConstructor = dependencyConstructor(Right(p))
|
||||
implicit def extDependencyConstructor(p: File): ProjectDependencyConstructor = dependencyConstructor(Left(p))
|
||||
implicit def extDependencyConstructor(p: ProjectDependency.Execution): ProjectDependencyConstructor = dependencyConstructor(p.project)
|
||||
|
||||
def dependencyConstructor(p: Either[File, Project]): ProjectDependencyConstructor = new ProjectDependencyConstructor {
|
||||
def %(conf: String) = new ProjectDependency.Classpath(p, Some(conf))
|
||||
}
|
||||
}
|
||||
sealed trait ProjectDependency { val project: Either[File, Project] }
|
||||
object ProjectDependency
|
||||
{
|
||||
final case class Execution(project: Either[File, Project]) extends ProjectDependency
|
||||
final case class Classpath(project: Either[File, Project], configuration: Option[String]) extends ProjectDependency
|
||||
}
|
||||
sealed trait ProjectDependencyConstructor {
|
||||
def %(conf: String): ProjectDependency.Classpath
|
||||
}
|
||||
Loading…
Reference in New Issue