* Moved topologicalSort in Dag trait to companion object

* Subprojects can be excluded from dependencies so that their actions aren't executed when a parent's actions are



git-svn-id: https://simple-build-tool.googlecode.com/svn/trunk@944 d89573ee-9141-11dd-94d4-bdf5e562f29c
This commit is contained in:
dmharrah 2009-08-09 02:03:24 +00:00
parent d798cb88b8
commit 749934f64a
4 changed files with 21 additions and 26 deletions

View File

@ -520,7 +520,7 @@ trait ReflectiveProject extends ReflectiveModules with ReflectiveTasks with Refl
/** This Project subclass is used to contain other projects as dependencies.*/ /** This Project subclass is used to contain other projects as dependencies.*/
class ParentProject(val info: ProjectInfo) extends BasicDependencyProject class ParentProject(val info: ProjectInfo) extends BasicDependencyProject
{ {
def dependencies = info.dependencies ++ subProjects.values.toList def dependencies: Iterable[Project] = info.dependencies ++ subProjects.values.toList
/** The directories to which a project writes are listed here and is used /** The directories to which a project writes are listed here and is used
* to check a project and its dependencies for collisions.*/ * to check a project and its dependencies for collisions.*/
override def outputDirectories = managedDependencyPath :: outputPath :: Nil override def outputDirectories = managedDependencyPath :: outputPath :: Nil

View File

@ -1,28 +1,31 @@
/* sbt -- Simple Build Tool /* sbt -- Simple Build Tool
* Copyright 2008 David MacIver * Copyright 2008, 2009 David MacIver, Mark Harrah
*/ */
package sbt; package sbt;
import scala.collection.mutable;
trait Dag[Node <: Dag[Node]]{ trait Dag[Node <: Dag[Node]]{
self : Node => self : Node =>
def dependencies : Iterable[Node] def dependencies : Iterable[Node]
def topologicalSort = Dag.topologicalSort(self)(_.dependencies)
}
object Dag
{
import scala.collection.mutable;
def topologicalSort = { def topologicalSort[T](root: T)(dependencies: T => Iterable[T]) = {
val discovered = new mutable.HashSet[Node]; val discovered = new mutable.HashSet[T];
val finished = new wrap.MutableSetWrapper(new java.util.LinkedHashSet[Node]) val finished = new wrap.MutableSetWrapper(new java.util.LinkedHashSet[T])
def visit(dag : Node){ def visit(dag : T){
if (!discovered(dag)) { if (!discovered(dag)) {
discovered(dag) = true; discovered(dag) = true;
dag.dependencies.foreach(visit); dependencies(dag).foreach(visit);
finished += dag; finished += dag;
} }
} }
visit(self); visit(root);
finished.toList; finished.toList;
} }

View File

@ -72,7 +72,7 @@ object Main
import success.project import success.project
val doNext: RunCompleteAction = val doNext: RunCompleteAction =
// in interactive mode, fill all undefined properties // in interactive mode, fill all undefined properties
if(args.length > 0 || fillUndefinedProjectProperties(project.topologicalSort.toList.reverse)) if(args.length > 0 || fillUndefinedProjectProperties(project.projectClosure.toList.reverse))
startProject(project, args, startTime) startProject(project, args, startTime)
else else
new Exit(NormalExitCode) new Exit(NormalExitCode)
@ -191,7 +191,7 @@ object Main
**/ **/
private def interactive(baseProject: Project): RunCompleteAction = private def interactive(baseProject: Project): RunCompleteAction =
{ {
val projectNames = baseProject.topologicalSort.map(_.name) val projectNames = baseProject.projectClosure.map(_.name)
val prefixes = ContinuousExecutePrefix :: CrossBuildPrefix :: Nil val prefixes = ContinuousExecutePrefix :: CrossBuildPrefix :: Nil
val completors = new Completors(ProjectAction, projectNames, interactiveCommands, List(GetAction, SetAction), prefixes) val completors = new Completors(ProjectAction, projectNames, interactiveCommands, List(GetAction, SetAction), prefixes)
val reader = new JLineReader(baseProject.historyPath, completors, baseProject.log) val reader = new JLineReader(baseProject.historyPath, completors, baseProject.log)
@ -235,7 +235,7 @@ object Main
else if(trimmed.startsWith(ProjectAction + " ")) else if(trimmed.startsWith(ProjectAction + " "))
{ {
val projectName = trimmed.substring(ProjectAction.length + 1) val projectName = trimmed.substring(ProjectAction.length + 1)
baseProject.topologicalSort.find(_.name == projectName) match baseProject.projectClosure.find(_.name == projectName) match
{ {
case Some(newProject) => case Some(newProject) =>
{ {
@ -255,7 +255,7 @@ object Main
if(trimmed == HelpAction) if(trimmed == HelpAction)
displayInteractiveHelp() displayInteractiveHelp()
else if(trimmed == ShowProjectsAction) else if(trimmed == ShowProjectsAction)
baseProject.topologicalSort.foreach(listProject) baseProject.projectClosure.foreach(listProject)
else if(trimmed.startsWith(SetAction + " ")) else if(trimmed.startsWith(SetAction + " "))
setProperty(currentProject, trimmed.substring(SetAction.length + 1)) setProperty(currentProject, trimmed.substring(SetAction.length + 1))
else if(trimmed.startsWith(GetAction + " ")) else if(trimmed.startsWith(GetAction + " "))
@ -414,7 +414,7 @@ object Main
private def toggleTrace(project: Project) private def toggleTrace(project: Project)
{ {
val newValue = !project.log.traceEnabled val newValue = !project.log.traceEnabled
project.topologicalSort.foreach(_.log.enableTrace(newValue)) project.projectClosure.foreach(_.log.enableTrace(newValue))
printTraceEnabled(project) printTraceEnabled(project)
} }
private def printTraceEnabled(project: Project) private def printTraceEnabled(project: Project)
@ -424,7 +424,7 @@ object Main
/** Sets the logging level on the given project.*/ /** Sets the logging level on the given project.*/
private def setLevel(project: Project, level: Level.Value) private def setLevel(project: Project, level: Level.Value)
{ {
project.topologicalSort.foreach(_.log.setLevel(level)) project.projectClosure.foreach(_.log.setLevel(level))
Console.println("Set log level to " + project.log.getLevel) Console.println("Set log level to " + project.log.getLevel)
} }
/** Prints the elapsed time to the given project's log using the given /** Prints the elapsed time to the given project's log using the given

View File

@ -82,15 +82,7 @@ trait Project extends TaskManager with Dag[Project] with BasicEnvironment
* specified for the project and are different from those specified in the project constructor. The * specified for the project and are different from those specified in the project constructor. The
* main use within sbt is in ParentProject.*/ * main use within sbt is in ParentProject.*/
def subProjects: Map[String, Project] = immutable.Map.empty def subProjects: Map[String, Project] = immutable.Map.empty
/** The name of this project and the names of all subprojects/dependencies, transitively.*/ def projectClosure: List[Project] = Dag.topologicalSort(this)(p => p.dependencies ++ p.subProjects.values.toList)
def projectNames: Iterable[String] =
{
val names = new mutable.HashSet[String]
names ++= subProjects.keys
for(dependentProject <- topologicalSort)
names ++= dependentProject.tasks.keys
names.toList
}
def call(name: String, parameters: Array[String]): Option[String] = def call(name: String, parameters: Array[String]): Option[String] =
{ {
@ -424,7 +416,7 @@ object Project
* output directories. */ * output directories. */
private def checkOutputDirectoriesImpl(project: Project): LoadResult = private def checkOutputDirectoriesImpl(project: Project): LoadResult =
{ {
val projects = project.topologicalSort val projects = project.projectClosure
import scala.collection.mutable.{HashMap, HashSet, Set} import scala.collection.mutable.{HashMap, HashSet, Set}
val outputDirectories = new HashMap[Path, Set[Project]] val outputDirectories = new HashMap[Path, Set[Project]]
for(p <- projects; path <- p.outputDirectories) for(p <- projects; path <- p.outputDirectories)