mirror of https://github.com/sbt/sbt.git
redo external projects
move externals from State to ProjectInfo
This commit is contained in:
parent
e3d39175d4
commit
c2a9a95baf
|
|
@ -241,9 +241,11 @@ object Commands
|
|||
|
||||
def loadProject = Command.simple(LoadProject, LoadProjectBrief, LoadProjectDetailed) { (in, s) =>
|
||||
val base = s.configuration.baseDirectory
|
||||
val p = MultiProject.load(s.configuration, ConsoleLogger() /*TODO*/)(base)
|
||||
val exts = MultiProject.loadExternals(p :: Nil, p.info.construct)
|
||||
s.copy(project = p)().put(MultiProject.ExternalProjects, exts.updated(base, p)).put(MultiProject.InitialProject, p)
|
||||
lazy val p: Project = MultiProject.load(s.configuration, ConsoleLogger() /*TODO*/, ProjectInfo.externals(exts))(base)
|
||||
// lazy so that p can forward-reference it
|
||||
lazy val exts: Map[File, Project] = MultiProject.loadExternals(p :: Nil, p.info.construct).updated(base, p)
|
||||
exts// force
|
||||
runExitHooks(s).copy(project = p)().put(MultiProject.InitialProject, p)
|
||||
}
|
||||
|
||||
def handleException(e: Throwable, s: State, trace: Boolean = true): State = {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import annotation.tailrec
|
|||
|
||||
object MultiProject
|
||||
{
|
||||
val ExternalProjects = AttributeKey[Map[File, Project]]("external-projects")
|
||||
val InitialProject = AttributeKey[Project]("initial-project")
|
||||
|
||||
val defaultExcludes: FileFilter = (".*" - ".") || HiddenFileFilter
|
||||
|
|
@ -42,7 +41,8 @@ object MultiProject
|
|||
case None => error("Couldn't find constructor with one argument of type " + mf.toString)
|
||||
}
|
||||
|
||||
def load(configuration: AppConfiguration, log: Logger)(base: File): Project =
|
||||
// externals must not be evaluated until after _all_ projects have been loaded
|
||||
def load(configuration: AppConfiguration, log: Logger, externals: ExternalProjects)(base: File): Project =
|
||||
{
|
||||
val projectDir = selectProjectDir(base)
|
||||
val buildDir = projectDir / "build"
|
||||
|
|
@ -55,7 +55,7 @@ object MultiProject
|
|||
val inputs = Compile.inputs(classpath, sources.getFiles.toSeq, target, Nil, Nil, javaSrcBase :: Nil, Compile.DefaultMaxErrors)(compilers, log)
|
||||
|
||||
val analysis = Compile(inputs)
|
||||
val info = ProjectInfo(None, base, projectDir, Nil, None)(configuration, analysis, inputs, load(configuration, log))
|
||||
val info = ProjectInfo(None, base, projectDir, Nil, None)(configuration, analysis, inputs, load(configuration, log, externals), externals)
|
||||
|
||||
val discovered = Build.check(Build.discover(analysis, Some(false), Auto.Subclass, projectClassName), false)
|
||||
Build.binaries(inputs.config.classpath, discovered, getClass.getClassLoader)(construct(info)).head.asInstanceOf[Project]
|
||||
|
|
@ -93,19 +93,17 @@ object MultiProject
|
|||
def internalTopologicalSort(root: Project): Seq[Project] =
|
||||
Dag.topologicalSort(root)(internalProjects)
|
||||
|
||||
def topologicalSort(root: Project, state: State): Seq[Project] = topologicalSort(root)(externalMap(state))
|
||||
def topologicalSort(root: Project)(implicit resolveExternal: File => Project): Seq[Project] =
|
||||
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 externalMap(state: State): File => Project = state get MultiProject.ExternalProjects getOrElse Map.empty
|
||||
def initialProject(state: State, ifUnset: => Project): Project =state get MultiProject.InitialProject getOrElse ifUnset
|
||||
|
||||
def makeContext(root: Project, state: State) =
|
||||
def makeContext(root: Project) =
|
||||
{
|
||||
val allProjects = topologicalSort(root, state)
|
||||
val contexts = allProjects map { p => (p, ReflectiveContext(p, p.name)) }
|
||||
val externals = externalMap(state)
|
||||
val contexts = topologicalSort(root) map { p => (p, ReflectiveContext(p, p.name)) }
|
||||
val externals = root.info.externals
|
||||
def subs(f: Project => Iterable[ProjectDependency]): Project => Iterable[Project] = p =>
|
||||
f(p) map( _.project match { case Left(path) => externals(path); case Right(proj) => proj } )
|
||||
MultiContext(contexts)(subs(_.aggregate), subs(_.dependencies) )
|
||||
|
|
@ -157,7 +155,7 @@ trait Project extends Tasked with HistoryEnabled with Member[Project] with Named
|
|||
def historyPath = Some(outputRootPath / ".history")
|
||||
def streamBase = outputRootPath / "streams"
|
||||
|
||||
def projectClosure(s: State): Seq[Project] = MultiProject.topologicalSort(MultiProject.initialProject(s, rootProject), s)
|
||||
def projectClosure(s: State): Seq[Project] = MultiProject.topologicalSort(MultiProject.initialProject(s, rootProject))
|
||||
@tailrec final def rootProject: Project = info.parent match { case Some(p) => p.rootProject; case None => this }
|
||||
|
||||
implicit def streams = Dummy.Streams
|
||||
|
|
@ -171,7 +169,7 @@ trait Project extends Tasked with HistoryEnabled with Member[Project] with Named
|
|||
def act(input: Input, state: State): Option[(Task[State], Execute.NodeView[Task])] =
|
||||
{
|
||||
import Dummy._
|
||||
val context = MultiProject.makeContext(this, state)
|
||||
val context = MultiProject.makeContext(this)
|
||||
val dummies = new Transform.Dummies(In, State, Streams)
|
||||
def name(t: Task[_]): String = context.staticName(t.original) getOrElse std.Streams.name(t)
|
||||
val mklog = LogManager.construct(context, settings)
|
||||
|
|
@ -227,8 +225,8 @@ trait ProjectConstructors extends Project
|
|||
sealed trait ProjectDependency { val project: Either[File, Project] }
|
||||
object ProjectDependency
|
||||
{
|
||||
final class Execution(val project: Either[File, Project]) extends ProjectDependency
|
||||
final class Classpath(val project: Either[File, Project], configuration: Option[String]) extends 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
|
||||
|
|
|
|||
|
|
@ -16,16 +16,24 @@ import inc.Analysis
|
|||
* `buildScalaVersion` contains the explicitly requested Scala version to use for building (as when using `+` or `++`) or None if the normal version should be used.
|
||||
*/
|
||||
final case class ProjectInfo(name: Option[String], projectDirectory: File, builderDir: File, dependencies: Iterable[Project], parent: Option[Project])(
|
||||
val configuration: AppConfiguration, val analysis: Analysis, val compileInputs: Compile.Inputs, val construct: File => Project)
|
||||
val configuration: AppConfiguration, val analysis: Analysis, val compileInputs: Compile.Inputs, val construct: File => Project, external: ExternalProjects)
|
||||
{
|
||||
def app = configuration.provider
|
||||
/** The version of Scala running sbt.*/
|
||||
def definitionScalaVersion = app.scalaProvider.version
|
||||
/** The launcher instance that booted sbt.*/
|
||||
def launcher = app.scalaProvider.launcher
|
||||
def globalLock = launcher.globalLock
|
||||
/* cannot be referenced in a Project's constructor */
|
||||
lazy val externals = external.value
|
||||
}
|
||||
final class ExternalProjects(externalMap: => Map[File, Project])
|
||||
{
|
||||
lazy val value = externalMap
|
||||
}
|
||||
|
||||
object ProjectInfo
|
||||
{
|
||||
def externals(externalMap: => Map[File, Project]) = new ExternalProjects(externalMap)
|
||||
val MetadataDirectoryName = "project"
|
||||
}
|
||||
|
|
@ -18,12 +18,12 @@ object Watched
|
|||
val ContinuousCompilePollDelaySeconds = 1
|
||||
def isEnter(key: Int): Boolean = key == 10 || key == 13
|
||||
|
||||
def watched(p: Project, s: State): Seq[Watched] = MultiProject.topologicalSort(p, s).collect { case w: Watched => w }
|
||||
def sourcePaths(p: Project, s: State): PathFinder = (Path.emptyPathFinder /: watched(p, s))(_ +++ _.watchPaths)
|
||||
def watched(p: Project): Seq[Watched] = MultiProject.topologicalSort(p).collect { case w: Watched => w }
|
||||
def sourcePaths(p: Project): PathFinder = (Path.emptyPathFinder /: watched(p))(_ +++ _.watchPaths)
|
||||
def executeContinuously(project: Project with Watched, s: State, in: Input): State =
|
||||
{
|
||||
def shouldTerminate: Boolean = (System.in.available > 0) && (project.terminateWatch(System.in.read()) || shouldTerminate)
|
||||
val sourcesFinder = sourcePaths(project, s)
|
||||
val sourcesFinder = sourcePaths(project)
|
||||
val watchState = s get ContinuousState getOrElse WatchState.empty
|
||||
|
||||
if(watchState.count > 0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue