diff --git a/cache/tracking/DependencyTracking.scala b/cache/tracking/DependencyTracking.scala deleted file mode 100644 index 30e060af3..000000000 --- a/cache/tracking/DependencyTracking.scala +++ /dev/null @@ -1,136 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2009, 2010 Mark Harrah - */ -package sbt - -private object DependencyTracking -{ - import scala.collection.mutable.{Set, HashMap, Map, MultiMap} - type DependencyMap[T] = HashMap[T, Set[T]] with MultiMap[T, T] - def newMap[T]: DependencyMap[T] = new HashMap[T, Set[T]] with MultiMap[T, T] - type TagMap[T] = Map[T, Array[Byte]] - def newTagMap[T] = new HashMap[T, Array[Byte]] -} - -trait UpdateTracking[T] extends NotNull -{ - def dependency(source: T, dependsOn: T): Unit - def use(source: T, uses: T): Unit - def product(source: T, output: T): Unit - def tag(source: T, t: Array[Byte]): Unit - def read: ReadTracking[T] - // removes files from all maps, both keys and values - def removeAll(files: Iterable[T]): Unit - // removes sources as keys/values in source, product maps and as values in reverseDependencies map - def pending(sources: Iterable[T]): Unit -} -trait ReadTracking[T] extends NotNull -{ - def isProduct(file: T): Boolean - def isSource(file: T): Boolean - def isUsed(file: T): Boolean - def dependsOn(file: T): Set[T] - def products(file: T): Set[T] - def sources(file: T): Set[T] - def usedBy(file: T): Set[T] - def tag(file: T): Array[Byte] - def allProducts: Set[T] - def allSources: Set[T] - def allUsed: Set[T] - def allTags: Seq[(T,Array[Byte])] -} -import DependencyTracking.{DependencyMap => DMap, newMap, newTagMap, TagMap} -private object DefaultTracking -{ - def apply[T](translateProducts: Boolean): DependencyTracking[T] = - new DefaultTracking(translateProducts)(newMap, newMap, newMap, newTagMap) -} -private final class DefaultTracking[T](translateProducts: Boolean) - (val reverseDependencies: DMap[T], val reverseUses: DMap[T], val sourceMap: DMap[T], val tagMap: TagMap[T]) - extends DependencyTracking[T](translateProducts) -{ - val productMap: DMap[T] = forward(sourceMap) // map from a source to its products. Keep in sync with sourceMap -} -// if translateProducts is true, dependencies on a product are translated to dependencies on a source -// if there is a source recorded as generating that product -private abstract class DependencyTracking[T](translateProducts: Boolean) extends ReadTracking[T] with UpdateTracking[T] -{ - val reverseDependencies: DMap[T] // map from a file to the files that depend on it - val reverseUses: DMap[T] // map from a file to the files that use it - val sourceMap: DMap[T] // map from a product to its sources. Keep in sync with productMap - val productMap: DMap[T] // map from a source to its products. Keep in sync with sourceMap - val tagMap: TagMap[T] - - def read = this - - final def dependsOn(file: T): Set[T] = get(reverseDependencies, file) - final def products(file: T): Set[T] = get(productMap, file) - final def sources(file: T): Set[T] = get(sourceMap, file) - final def usedBy(file: T): Set[T] = get(reverseUses, file) - final def tag(file: T): Array[Byte] = tagMap.getOrElse(file, new Array[Byte](0)) - - def isProduct(file: T): Boolean = exists(sourceMap, file) - def isSource(file: T): Boolean = exists(productMap, file) - def isUsed(file: T): Boolean = exists(reverseUses, file) - - - final def allProducts = sourceMap.keysIterator.toSet - final def allSources = productMap.keysIterator.toSet - final def allUsed = reverseUses.keysIterator.toSet - final def allTags = tagMap.toSeq - - private def exists(map: DMap[T], value: T): Boolean = map.contains(value) - private def get(map: DMap[T], value: T): Set[T] = map.getOrElse[collection.Set[T]](value, Set.empty[T]).toSet - - final def dependency(sourceFile: T, dependsOn: T) - { - val actualDependencies = - if(!translateProducts) - Seq(dependsOn) - else - sourceMap.getOrElse[Iterable[T]](dependsOn, Seq(dependsOn)) - actualDependencies.foreach { actualDependency => reverseDependencies.add(actualDependency, sourceFile) } - } - final def product(sourceFile: T, product: T) - { - productMap.add(sourceFile, product) - sourceMap.add(product, sourceFile) - } - final def use(sourceFile: T, usesFile: T) { reverseUses.add(usesFile, sourceFile) } - final def tag(sourceFile: T, t: Array[Byte]) { tagMap(sourceFile) = t } - - private def removeOneWay(a: DMap[T], files: Iterable[T]): Unit = - a.values.foreach { _ --= files } - private def remove(a: DMap[T], b: DMap[T], file: T): Unit = - for(x <- a.removeKey(file)) b --= x - private def removeAll(files: Iterable[T], a: DMap[T], b: DMap[T]): Unit = - files.foreach { file => remove(a, b, file); remove(b, a, file) } - final def removeAll(files: Iterable[T]) - { - removeAll(files, forward(reverseDependencies), reverseDependencies) - removeAll(files, productMap, sourceMap) - removeAll(files, forward(reverseUses), reverseUses) - tagMap --= files - } - def pending(sources: Iterable[T]) - { - removeOneWay(reverseDependencies, sources) - removeOneWay(reverseUses, sources) - removeAll(sources, productMap, sourceMap) - tagMap --= sources - } - protected final def forward(map: DMap[T]): DMap[T] = - { - val f = newMap[T] - for( (key, values) <- map; value <- values) f.add(value, key) - f - } - override def toString = - (graph("Reverse source dependencies", reverseDependencies) :: - graph("Sources and products", productMap) :: - graph("Reverse uses", reverseUses) :: - Nil) mkString "\n" - def graph(title: String, map: DMap[T]) = - "\"" + title + "\" {\n\t" + graphEntries(map) + "\n}" - def graphEntries(map: DMap[T]) = map.map{ case (key, values) => values.map(key + " -> " + _).mkString("\n\t") }.mkString("\n\t") -} diff --git a/cache/tracking/TrackingFormat.scala b/cache/tracking/TrackingFormat.scala deleted file mode 100644 index d8a5e0f2c..000000000 --- a/cache/tracking/TrackingFormat.scala +++ /dev/null @@ -1,65 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2009, 2010 Mark Harrah - */ -package sbt - -import java.io.File -import scala.collection.mutable.{HashMap, Map, MultiMap, Set} -import scala.reflect.Manifest -import sbinary.{DefaultProtocol, Format} -import DefaultProtocol._ -import TrackingFormat._ -import CacheIO.{fromFile, toFile} -import DependencyTracking.{DependencyMap => DMap, newMap, TagMap} - -private class TrackingFormat[T](directory: File, translateProducts: Boolean)(implicit tFormat: Format[T], mf: Manifest[T]) extends NotNull -{ - val indexFile = new File(directory, "index") - val dependencyFile = new File(directory, "dependencies") - def read(): DependencyTracking[T] = - { - val indexMap = CacheIO.fromFile[Map[Int,T]](indexFile, new HashMap[Int,T]) - val indexedFormat = wrap[T,Int](ignore => error("Read-only"), i => indexMap.getOrElse(i, error("Index " + i + " not found"))) - val trackFormat = trackingFormat(translateProducts)(indexedFormat) - fromFile(trackFormat, DefaultTracking[T](translateProducts))(dependencyFile) - } - def write(tracking: DependencyTracking[T]) - { - val index = new IndexMap[T] - val indexedFormat = wrap[T,Int](t => index(t), ignore => error("Write-only")) - val trackFormat = trackingFormat(translateProducts)(indexedFormat) - toFile(trackFormat)(tracking)(dependencyFile) - toFile(index.indices)(indexFile) - } -} -private object TrackingFormat -{ - implicit def mutableMapFormat[S, T](implicit binS : Format[S], binT : Format[T]) : Format[HashMap[S, T]] = - new LengthEncoded[HashMap[S, T], (S, T)] { - def build(size : Int, ts : Iterator[(S, T)]) : HashMap[S, T] = { - val b = new HashMap[S, T] - b ++= ts - b - } - } - implicit def depMapFormat[T](implicit bin: Format[T]) : Format[DMap[T]] = - new LengthEncoded[DMap[T], (T, Set[T])] { - def build(size : Int, ts : Iterator[(T, Set[T])]) : DMap[T] = { - val b = newMap[T] - b ++= ts - b - } - } - def trackingFormat[T](translateProducts: Boolean)(implicit tFormat: Format[T]): Format[DependencyTracking[T]] = - asProduct4((a: DMap[T],b: DMap[T],c: DMap[T], d:TagMap[T]) => new DefaultTracking(translateProducts)(a,b,c,d) : DependencyTracking[T] - )(dt => (dt.reverseDependencies, dt.reverseUses, dt.sourceMap, dt.tagMap)) -} - -private final class IndexMap[T] extends NotNull -{ - private[this] var lastIndex = 0 - private[this] val map = new HashMap[T, Int] - private[this] def nextIndex = { lastIndex += 1; lastIndex } - def indices = HashMap(map.map( (_: (T,Int)).swap ).toSeq : _*) - def apply(t: T) = map.getOrElseUpdate(t, nextIndex) -} \ No newline at end of file diff --git a/run/Console.scala b/main/Console.scala similarity index 100% rename from run/Console.scala rename to main/Console.scala diff --git a/sbt/src/main/scala/sbt/Doc.scala b/sbt/src/main/scala/sbt/Doc.scala deleted file mode 100644 index 7be7c0a21..000000000 --- a/sbt/src/main/scala/sbt/Doc.scala +++ /dev/null @@ -1,38 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2008, 2009 Mark Harrah - */ -package sbt - -import java.io.File -import xsbt.{AnalyzingCompiler, CompileFailed} - -final class Scaladoc(maximumErrors: Int, compiler: AnalyzingCompiler) -{ - final def apply(label: String, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) - { - log.info(actionStartMessage(label)) - if(sources.isEmpty) - log.info(actionNothingToDoMessage) - else - { - IO.createDirectory(outputDirectory) - compiler.doc(sources, classpath, outputDirectory, options, maximumErrors, log) - log.info(actionSuccessfulMessage) - } - } - def actionStartMessage(label: String) = "Generating API documentation for " + label + " sources..." - val actionNothingToDoMessage = "No sources specified." - val actionSuccessfulMessage = "API documentation generation successful." - def actionUnsuccessfulMessage = "API documentation generation unsuccessful." -} -final class Console(compiler: AnalyzingCompiler) -{ - /** Starts an interactive scala interpreter session with the given classpath.*/ - def apply(classpath: Seq[File])(implicit log: Logger): Option[String] = - apply(classpath, Nil, "", log) - def apply(classpath: Iterable[File], options: Seq[String], initialCommands: String)(implicit log: Logger): Option[String] = - { - def console0 = compiler.console(Path.getFiles(classpath), options, initialCommands, log) - JLine.withJLine( Run.executeTrapExit(console0, log) ) - } -} diff --git a/sbt/src/main/scala/sbt/Update.scala b/sbt/src/main/scala/sbt/Update.scala deleted file mode 100644 index a0ba342c3..000000000 --- a/sbt/src/main/scala/sbt/Update.scala +++ /dev/null @@ -1,213 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2010 Mark Harrah - */ -package sbt - -/** A trait that provides a task for updating sbt. */ -trait UpdateSbt extends Project -{ - /** The first argument is the version to update to and is mandatory. - * The second argument is the location of the launcher jar. If omitted, the launcher used to launch the currently running instance of sbt is used.*/ - lazy val sbtUpdate = task { args => task { (new Update(this))(args) } } describedAs("Updates the version of sbt used to build this project and updates the launcher jar.") -} - -import java.io.{File, InputStream, IOException} -import java.net.{HttpURLConnection, URL} -import HttpURLConnection.{HTTP_NOT_FOUND , HTTP_OK} -import SimpleReader.readLine -import xsbt.FileUtilities.{classLocationFile, copyFile, readLines, transfer, unzip, withTemporaryDirectory, write, zip} -import xsbt.PathMapper.relativeTo -import xsbt.Paths._ -import xsbt.OpenResource.{fileOutputStream, urlInputStream} - -private class Update(project: Project) -{ - val info = project.info - val app = info.app - val log = project.log - - /** The location of the jar used to launch the currently running instance of sbt.*/ - lazy val launcherJar = classLocationFile[xsbti.AppProvider] - /** A temporary jar file to use in the given directory. */ - def tempJar(dir: File) = dir / launcherJar.getName - - /** Implementation of the sbt-update task: reads arguments and hands off to the other `apply`.*/ - def apply(args: Array[String]): Option[String] = - args match - { - case Array(version) if validVersion(version) => apply(version, None) - case Array(version, temporaryJar) if validVersion(version) => apply(version, Some(new File(temporaryJar) getAbsoluteFile)) - case _ => Some("Expected '' or ' ', got '" + args.mkString(" ") + "'") - } - - def validVersion(version: String) = !version.trim.isEmpty - - /** Implementation of the sbt-update task after arguments have checked. Gives user a chance to cancel and continues with `doUpdate`.*/ - def apply(version: String, temporaryJar: Option[File]): Option[String] = - { - readLine("Updating the sbt version requires a restart. Continue? (Y/n) ") match - { - case Some(line) if(isYes(line)) => doUpdate(version, temporaryJar) - case _ => Some("Update declined.") - } - } - /** Implementation of the sbt-update task: high-level control after initial verification.*/ - def doUpdate(version: String, temporaryJar: Option[File]): Option[String] = - { - retrieveNewVersion(version) - log.info("Version is valid. Setting 'sbt.version' to " + version + "...") - setNewVersion(version) - - log.info("'sbt.version' updated.") - if(temporaryJar.isDefined || updateInPlace(version)) - { - log.info("Downloading new launcher ...") - - if(downloadLauncher(version, temporaryJar)) - log.info("Downloaded launcher.") - else - tryUpdateLauncher(version, temporaryJar) - } - else - log.info("Launcher update declined.") - - log.info("Please restart sbt.") - System.exit(0) - None - } - /** Updates 'sbt.version' in `project/build.properties`.*/ - def setNewVersion(version: String) - { - project.sbtVersion() = version - project.saveEnvironment() - } - /** Retrieves the given `version` of sbt in order to verify the version is valid.*/ - def retrieveNewVersion(version: String) - { - val newAppID = changeVersion(app.id, version) - log.info("Checking repositories for sbt " + version + " ...") - app.scalaProvider.app(newAppID) - } - /** Asks the user whether the current launcher should be overrwritten. Called when no file is explicitly specified as an argument. */ - def updateInPlace(version: String) = - { - val input = readLine(" The current launcher (" + launcherJar + ") will be updated in place. Continue? (Y/n) ") - isYes(input) - } - def isYes(line: Option[String]): Boolean = line.filter(isYes).isDefined - - /** Updates the launcher as in `updateLauncher` but performs various checks and logging around it. */ - def tryUpdateLauncher(version: String, temporaryJar: Option[File]) - { - log.warn("No launcher found for '" + version + "'") - def promptStart = if(temporaryJar.isDefined) " Copy current launcher but with " else " Modify current launcher to use " - val input = readLine(promptStart + version + " as the default for new projects? (Y/n) ") - val updated = isYes(input) - if(updated) updateLauncher(version, temporaryJar) - - def extra = if(temporaryJar.isDefined) " at " + temporaryJar.get + "." else "." - log.info(if(updated) "Launcher updated" + extra else "Launcher not updated.") - } - /** The jar to copy/download to. If `userJar` is not defined, it is a temporary file in `tmpDir` that should then be moved to the current launcher file. - * If it is defined and is a directory, the jar is defined in that directory. If it is a file, that file is returned. */ - def targetJar(tmpDir: File, userJar: Option[File]): File = - userJar match { case Some(file) => if(file.isDirectory) tempJar(file) else file; case None => tempJar(tmpDir) } - - /** Gets the given `version` of the launcher from Google Code. If `userProvidedJar` is defined, - * this updated launcher is downloaded there, otherwise it overwrites the current launcher. */ - def downloadLauncher(version: String, userProvidedJar: Option[File]): Boolean = - { - def getLauncher(tmp: File): Boolean = - { - val temporaryJar = targetJar(tmp, userProvidedJar) - temporaryJar.getParentFile.mkdirs() - val url = launcherURL(version) - val connection = url.openConnection.asInstanceOf[HttpURLConnection] - connection.setInstanceFollowRedirects(false) - - def download(in: InputStream): Unit = fileOutputStream(false)(temporaryJar) { out => transfer(in, out) } - def checkAndRetrieve(in: InputStream): Boolean = (connection.getResponseCode == HTTP_OK) && { download(in); true } - def handleError(e: IOException) = if(connection.getResponseCode == HTTP_NOT_FOUND ) false else throw e - def retrieve() = - { - val in = connection.getInputStream - try { checkAndRetrieve(in) } finally { in.close() } - } - - val success = try { retrieve() } catch { case e: IOException => handleError(e)} finally { connection.disconnect() } - if(success && userProvidedJar.isEmpty) - move(temporaryJar, launcherJar) - success - } - withTemporaryDirectory(getLauncher) - } - /** The location of the launcher for the given version, if it exists. */ - def launcherURL(version: String): URL = - new URL("http://simple-build-tool.googlecode.com/files/sbt-launch-" + version + ".jar") - - /** True iff the given user input is empty, 'y' or 'yes' (case-insensitive).*/ - def isYes(line: String) = - { - val lower = line.toLowerCase - lower.isEmpty || lower == "y" || lower == "yes" - } - /** Copies the current launcher but with the default 'sbt.version' set to `version`. If `userProvidedJar` is defined, - * the updated launcher is copied there, otherwise the copy overwrites the current launcher. */ - def updateLauncher(version: String, userProvidedJar: Option[File]) - { - def makeUpdated(base: File, newJar: File) - { - val files = unzip(launcherJar, base) - updateBootProperties(files, version) - zip(relativeTo(base)( files ), newJar) - } - def updateLauncher(tmp: File) - { - val basePath = tmp / "launcher-jar" - val temporaryJar = targetJar(tmp, userProvidedJar) - makeUpdated(basePath, temporaryJar) - if(userProvidedJar.isEmpty) - move(temporaryJar, launcherJar) - } - - withTemporaryDirectory(updateLauncher) - } - - /** Copies the `src` file to the `dest` file, preferably by renaming. The `src` file may or may not be removed.*/ - def move(src: File, dest: File) - { - val renameSuccess = src renameTo dest - if(!renameSuccess) - copyFile(src, dest) - } - - /** Updates the default value used for 'sbt.version' in the 'sbt.boot.properties' file in the launcher `files` to be `version`.*/ - def updateBootProperties(files: Iterable[File], version: String): Unit = - files.find(_.getName == "sbt.boot.properties").foreach(updateBootProperties(version)) - /** Updates the default value used for 'sbt.version' in the given `file` to be `version`.*/ - def updateBootProperties(version: String)(file: File) - { - val newContent = readLines(file) map updateSbtVersion(version) - write(file, newContent.mkString("\n")) - } - - /** If the given `line` is the 'sbt.version' configuration, update it to use the `newVersion`.*/ - def updateSbtVersion(newVersion: String)(line: String) = - if(line.trim.startsWith("sbt.version")) sbtVersion(newVersion) else line - - /** The configuration line that defines the 'sbt.version' property, using the provided `version` for defaults.*/ - def sbtVersion(version: String) = - " sbt.version: quick=set(" + version + "), new=prompt(sbt version)[" + version + "], fill=prompt(sbt version)[" + version + "]" - - /** Copies the given ApplicationID but with the specified version.*/ - def changeVersion(appID: xsbti.ApplicationID, versionA: String): xsbti.ApplicationID = - new xsbti.ApplicationID { - def groupID = appID.groupID - def name = appID.name - def version = versionA - def mainClass = appID.mainClass - def mainComponents = appID.mainComponents - def crossVersioned = appID.crossVersioned - def classpathExtra = appID.classpathExtra - } -} diff --git a/sbt/src/main/scala/sbt/impl/RunTask.scala b/sbt/src/main/scala/sbt/impl/RunTask.scala deleted file mode 100644 index 9f1d9a88e..000000000 --- a/sbt/src/main/scala/sbt/impl/RunTask.scala +++ /dev/null @@ -1,154 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2009 Mark Harrah - */ - package sbt.impl - import sbt._ - -import scala.collection.{immutable, mutable} -import scala.collection.Map -import sbt.wrap.Wrappers.identityMap - -private[sbt] object RunTask -{ - final type Task = Project#Task - def apply(root: Task, rootName: String): List[WorkFailure[Task]] = apply(root, rootName, true) - def apply(root: Task, rootName: String, parallelExecution: Boolean): List[WorkFailure[Task]] = - apply(root, rootName, if(parallelExecution) Runtime.getRuntime.availableProcessors else 1) - def apply(root: Task, rootName: String, maximumTasks: Int): List[WorkFailure[Task]] = (new RunTask(root, rootName, maximumTasks)).run() -} -import RunTask._ -private final class RunTask(root: Task, rootName: String, maximumTasks: Int) extends NotNull -{ - require(maximumTasks >= 1) - def parallel = maximumTasks > 1 - def multiProject = allProjects.size >= 2 - def run(): List[WorkFailure[Task]] = - { - try - { - runTasksExceptRoot() match - { - case Nil => - val result = runTask(root, rootName) - result.map( errorMessage => WorkFailure(root, "Error running " + rootName + ": " + errorMessage) ).toList - case failures => failures - } - } - finally - { - for(project <- allProjects; saveError <- project.saveEnvironment) - project.log.warn("Could not save properties for project " + project.name + ": " + saveError) - } - } - // This runs all tasks except the root.task. - // It uses a buffered logger in record mode to ensure that all output for a given task is consecutive - // it ignores the root task so that the root task may be run with buffering disabled so that the output - // occurs without delay. - private def runTasksExceptRoot() = - ParallelRunner.run(expandedRoot, expandedTaskName, runIfNotRoot, maximumTasks, (t: Task) => t.manager.log) - private def withBuffered(f: BufferedLogger => Unit) - { - for(buffered <- bufferedLoggers) - Control.trap(f(buffered)) - } - /** Will be called in its own thread. Runs the given task if it is not the root task.*/ - private def runIfNotRoot(action: Task): Option[String] = - { - if(isRoot(action)) - None - else - runTask(action, expandedTaskName(action)) - } - private val headerStart = System.getProperty("sbt.start.delimiter", "==") - private val headerEnd = System.getProperty("sbt.end.delimiter", "==") - private def isRoot(t: Task) = t == expandedRoot - /** Will be called in its own thread except for the root task. */ - private def runTask(action: Task, actionName: String): Option[String] = - { - val label = if(multiProject) (action.manager.name + " / " + actionName) else actionName - def banner(event: ControlEvent.Value, firstSeparator: String, secondSeparator: String) = - Control.trap(action.manager.log.control(event, firstSeparator + " " + label + " " + secondSeparator)) - val buffered = parallel && !isRoot(action) - if(buffered) - banner(ControlEvent.Start, "\n ", "...") - def doRun() = - { - banner(ControlEvent.Header, "\n" + headerStart, headerStart) - try { action.invoke } - catch { case e: Exception => action.manager.log.trace(e); Some(e.toString) } - finally { banner(ControlEvent.Finish, headerEnd, headerEnd) } - } - - if(buffered) - bufferLogging(action, doRun()) - else - doRun() - } - private def bufferLogging[T](action: Task, f: => T) = - bufferedLogger(action.manager) match - { - case Some(buffered) => buffered.buffer { f } - case None => f - } - - /* Most of the following is for implicitly adding dependencies (see the expand method)*/ - private val projectDependencyCache = identityMap[Project, Iterable[Project]] - private def dependencies(project: Project) = projectDependencyCache.getOrElseUpdate(project, project.topologicalSort.dropRight(1)) - - private val expandedCache = identityMap[Task, Task] - private def expanded(task: Task): Task = expandedCache.getOrElseUpdate(task, expandImpl(task)) - - private val expandedTaskNameCache = identityMap[Task, String] - private def expandedTaskName(task: Task) = - if(task == expandedRoot) - rootName - else - expandedTaskNameCache.getOrElse(task, task.name) - - private val nameToTaskCache = identityMap[Project, Map[String, Task]] - private def nameToTaskMap(project: Project): Map[String, Task] = nameToTaskCache.getOrElseUpdate(project, project.tasks) - private def taskForName(project: Project, name: String): Option[Task] = nameToTaskMap(project).get(name) - - private val taskNameCache = identityMap[Project, Map[Task, String]] - private def taskName(task: Task) = - { - val project = task.manager - taskNameCache.getOrElseUpdate(project, taskNameMap(project)).get(task) - } - - private val expandedRoot = expand(root) - private val allTasks = expandedRoot.topologicalSort - private val allProjects = Set(allTasks.map(_.manager).toSeq : _*) - private val bufferedLoggers = if(parallel) allProjects.toList.flatMap(bufferedLogger) else Nil - - /** Adds implicit dependencies, which are tasks with the same name in the project dependencies - * of the enclosing project of the task.*/ - private def expand(root: Task): Task = expanded(root) - private def expandImpl(task: Task): Task = - { - val nameOption = taskName(task) - val explicitDependencies = task.dependencies - val implicitDependencies = nameOption.map(name => dependencies(task.manager).flatMap(noninteractiveTask(name)) ).getOrElse(Nil) - val allDependencies = mutable.HashSet( (explicitDependencies ++ implicitDependencies).toSeq : _* ) - val expandedTask = task.setDependencies(allDependencies.toList.map(expanded)) - nameOption.foreach(name => expandedTaskNameCache(expandedTask) = name) - expandedTask - } - private def noninteractiveTask(name: String)(project: Project): Option[Task] = - taskForName(project, name) flatMap { task => - if(task.interactive) - { - project.log.debug("Not including task " + name + " in project " + project.name + ": interactive tasks can only be run directly.") - None - } - else - Some(task) - } - private def taskNameMap(project: Project) = mutable.Map(nameToTaskMap(project).map(_.swap).toSeq : _*) - private def bufferedLogger(project: Project): Option[BufferedLogger] = - project.log match - { - case buffered: BufferedLogger => Some(buffered) - case _ => None - } -} \ No newline at end of file