diff --git a/sbt_pending/src/main/resources/scalac-plugin.xml b/sbt_pending/src/main/resources/scalac-plugin.xml
deleted file mode 100644
index 54ec5669c..000000000
--- a/sbt_pending/src/main/resources/scalac-plugin.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
- sbt-analyze
- sbt.Analyzer
-
diff --git a/sbt_pending/src/main/scala/sbt/BasicProjectTypes.scala b/sbt_pending/src/main/scala/sbt/BasicProjectTypes.scala
deleted file mode 100644
index 1a7ef203e..000000000
--- a/sbt_pending/src/main/scala/sbt/BasicProjectTypes.scala
+++ /dev/null
@@ -1,571 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Mark Harrah
- */
-package sbt
-
-import scala.xml.{Node, NodeSeq}
-import StringUtilities.{appendable,nonEmpty}
-import BasicManagedProject._
-
-/** A project that provides a classpath. */
-trait ClasspathProject extends Project
-{
- /** The local classpath for this project.*/
- def projectClasspath(config: Configuration): PathFinder
-
- /** Returns the classpath of this project and the classpaths of all dependencies for the
- * given configuration. Specifically, this concatentates projectClasspath(config) for all
- * projects of type ClasspathProject in topologicalSort. */
- def fullClasspath(config: Configuration): PathFinder =
- Path.lazyPathFinder
- {
- val set = new wrap.MutableSetWrapper(new java.util.LinkedHashSet[Path])
- for(project <- topologicalSort)
- {
- project match
- {
- case sp: ClasspathProject => set ++= sp.projectClasspath(config).get
- case _ => ()
- }
- }
- set.toList
- }
- /* Filter used to select dependencies for the classpath from managed and unmanaged directories.
- * By default, it explicitly filters (x)sbt-launch(er)-.jar, since it contains minified versions of various classes.*/
- def classpathFilter: FileFilter = "*.jar" - "*sbt-launch*.jar"
-}
-trait BasicDependencyProject extends BasicManagedProject with UnmanagedClasspathProject
-{
- /** This returns the classpath for only this project for the given configuration.*/
- def projectClasspath(config: Configuration) = fullUnmanagedClasspath(config) +++ managedClasspath(config)
-}
-/** A project that provides a directory in which jars can be manually managed.*/
-trait UnmanagedClasspathProject extends ClasspathProject
-{
- /** The location of the manually managed (unmanaged) dependency directory.*/
- def dependencyPath: Path
- /** The classpath containing all jars in the unmanaged directory. */
- def unmanagedClasspath: PathFinder =
- {
- val base = descendents(dependencyPath, classpathFilter)
- if(scratch)
- base +++ (info.projectPath * classpathFilter)
- else
- base
- }
- /** The classpath containing all unmanaged classpath elements for the given configuration. This typically includes
- * at least 'unmanagedClasspath'.*/
- def fullUnmanagedClasspath(config: Configuration): PathFinder
-}
-
-trait IvyTasks extends Project
-{
- def ivyTask(action: => Unit) =
- task
- {
- try { action; None }
- catch {
- case e: ResolveException =>
- log.error(e.toString)
- Some(e.toString)
- case e: Exception =>
- log.trace(e)
- log.error(e.toString)
- Some(e.toString)
- }
- }
- def updateTask(module: => IvySbt#Module, configuration: => UpdateConfiguration) =
- ivyTask { IvyActions.update(module, configuration) }
-
- def publishTask(module: => IvySbt#Module, publishConfiguration: => PublishConfiguration) =
- ivyTask
- {
- val publishConfig = publishConfiguration
- import publishConfig._
- val deliveredIvy = if(publishIvy) Some(deliveredPattern) else None
- IvyActions.publish(module, resolverName, srcArtifactPatterns, deliveredIvy, configurations)
- }
- def deliverTask(module: => IvySbt#Module, deliverConfiguration: => PublishConfiguration, logging: => UpdateLogging.Value) =
- ivyTask
- {
- val deliverConfig = deliverConfiguration
- import deliverConfig._
- IvyActions.deliver(module, status, deliveredPattern, extraDependencies, configurations, logging)
- }
- @deprecated def makePomTask(module: => IvySbt#Module, output: => Path, extraDependencies: => Iterable[ModuleID], pomExtra: => NodeSeq, configurations: => Option[Iterable[Configuration]]): Task =
- makePomTask(module, MakePomConfiguration(extraDependencies, configurations, pomExtra), output)
- def makePomTask(module: => IvySbt#Module, configuration: => MakePomConfiguration, output: => Path): Task =
- ivyTask { IvyActions.makePom(module, configuration, output asFile) }
-
-
- def installTask(module: IvySbt#Module, from: Resolver, to: Resolver) =
- ivyTask { IvyActions.install(module, from.name, to.name) }
-
- def cleanCacheTask(ivySbt: => IvySbt) =
- ivyTask { IvyActions.cleanCache(ivySbt) }
-
- def cleanLibTask(managedDependencyPath: Path) =
- task { FileUtilities.clean(managedDependencyPath.get, log) }
-}
-
-/** A project that provides automatic dependency management.*/
-trait ManagedProject extends ClasspathProject with IvyTasks
-{
- /** This is the public ID of the project (used for publishing, for example) */
- def moduleID: String = normalizedName
- /** This is the full public ID of the project (used for publishing, for example) */
- def projectID: ModuleID = ModuleID(organization, moduleID, version.toString).artifacts(artifacts.toSeq : _*).cross(true)
-
- /** This is the default name for artifacts (such as jars) without any version string.*/
- def artifactID = moduleID
- /** This is the default name for artifacts (such as jars) including the version string.*/
- def artifactBaseName = artifactID + "-" + version.toString
- def artifacts: Iterable[Artifact]
-
- def managedDependencyPath: Path
- /** The managed classpath for the given configuration. This can be overridden to add jars from other configurations
- * so that the Ivy 'extends' mechanism is not required. That way, the jars are only copied to one configuration.*/
- def managedClasspath(config: Configuration): PathFinder = configurationClasspath(config)
- /** All dependencies in the given configuration. */
- final def configurationClasspath(config: Configuration): PathFinder = descendents(configurationPath(config), classpathFilter)
-
- /** The base path to which dependencies in configuration 'config' are downloaded.*/
- def configurationPath(config: Configuration): Path = managedDependencyPath / config.toString
-
-
- /** Creates a new configuration with the given name.*/
- def config(name: String) = new Configuration(name)
-}
-/** This class groups required configuration for the deliver and publish tasks. */
-trait PublishConfiguration extends NotNull
-{
- /** The name of the resolver to which publishing should be done.*/
- def resolverName: String
- /** The Ivy pattern used to determine the delivered Ivy file location. An example is
- * (outputPath / "[artifact]-[revision].[ext]").relativePath. */
- def deliveredPattern: String
- /** Ivy patterns used to find artifacts for publishing. An example pattern is
- * (outputPath / "[artifact]-[revision].[ext]").relativePath */
- def srcArtifactPatterns: Iterable[String]
- /** Additional dependencies to include for delivering/publishing only. These are typically dependencies on
- * subprojects. */
- def extraDependencies: Iterable[ModuleID]
- /** The status to use when delivering or publishing. This might be "release" or "integration" or another valid Ivy status. */
- def status: String
- /** The configurations to include in the publish/deliver action: specify none for all configurations. */
- def configurations: Option[Iterable[Configuration]]
- /** True if the Ivy file should be published. */
- def publishIvy: Boolean
-}
-object ManagedStyle extends Enumeration
-{
- val Maven, Ivy, Auto = Value
-}
-import ManagedStyle.{Auto, Ivy, Maven, Value => ManagedType}
-trait BasicManagedProject extends ManagedProject with ReflectiveManagedProject with BasicDependencyPaths
-{
- def ivyUpdateConfiguration = new UpdateConfiguration(managedDependencyPath.asFile, outputPattern, true/*sync*/, ivyUpdateLogging)
- def ivyUpdateLogging = UpdateLogging.DownloadOnly
- def ivyLocalOnly: Boolean = offline.value
-
- def ivyRepositories: Seq[Resolver] =
- {
- val repos = repositories.toSeq
- if(repos.isEmpty) Nil else Resolver.withDefaultResolvers(repos)
- }
- def otherRepositories: Seq[Resolver] = defaultPublishRepository.toList
- def ivyValidate = true
- def ivyScala: Option[IvyScala] = Some(new IvyScala(buildScalaVersion, checkScalaInConfigurations, checkExplicitScalaDependencies, filterScalaJars))
- def ivyCacheDirectory: Option[Path] = None
-
- def ivyPaths: IvyPaths = new IvyPaths(info.projectPath.asFile, ivyCacheDirectory.map(_.asFile))
- def inlineIvyConfiguration = new InlineIvyConfiguration(ivyPaths, ivyRepositories.toSeq, otherRepositories, moduleConfigurations.toSeq, ivyLocalOnly, Some(info.launcher.globalLock), log)
- def ivyConfiguration: IvyConfiguration =
- {
- val in = inlineIvyConfiguration
- def adapt(c: IvyConfiguration): IvyConfiguration = c.withBase(in.baseDirectory)
- def parentIvyConfiguration(default: IvyConfiguration)(p: Project) = p match { case b: BasicManagedProject => adapt(b.ivyConfiguration); case _ => default }
- if(in.resolvers.isEmpty)
- {
- if(in.moduleConfigurations.isEmpty && in.otherResolvers.isEmpty)
- {
- IvyConfiguration(in.paths, in.lock, in.localOnly, in.log) match
- {
- case e: ExternalIvyConfiguration => e
- case i => info.parent map(parentIvyConfiguration(i)) getOrElse(i)
- }
- }
- else
- in.changeResolvers(Resolver.withDefaultResolvers(Nil))
- }
- else
- in
- }
-
- def moduleSettings: ModuleSettings = defaultModuleSettings
- def byIvyFile(path: Path): IvyFileConfiguration = new IvyFileConfiguration(path.asFile, ivyScala, ivyValidate)
- def byPom(path: Path): PomConfiguration = new PomConfiguration(path.asFile, ivyScala, ivyValidate)
- /** The settings that represent inline declarations. The default settings combines the information
- * from 'ivyXML', 'projectID', 'repositories', ivyConfigurations, defaultConfiguration,
- * ivyScala, and 'libraryDependencies' and does not typically need to be be overridden. */
- def inlineSettings = new InlineConfiguration(projectID, withCompat, ivyXML, ivyConfigurations, defaultConfiguration, ivyScala, ivyValidate)
- /** Library dependencies with extra dependencies for compatibility*/
- private def withCompat =
- {
- val deps = libraryDependencies
- deps ++ compatExtra(deps)
- }
- /** Determines extra libraries needed for compatibility. Currently, this is the compatibility test framework. */
- private def compatExtra(deps: Set[ModuleID]) =
- if(isScala27 && deps.exists(requiresCompat)) { log.debug("Using compatibility implementation of test interface."); compatTestFramework } else Nil
- /** True if the given dependency requires the compatibility test framework. */
- private def requiresCompat(m: ModuleID) =
- {
- def nameMatches(name: String, id: String) = name == id || name.startsWith(id + "_2.7.")
-
- (nameMatches(m.name, "scalacheck") && Set("1.5", "1.6").contains(m.revision)) ||
- (nameMatches(m.name, "specs") && Set("1.6.0", "1.6.1").contains(m.revision)) ||
- (nameMatches(m.name, "scalatest") && m.revision == "1.0")
- }
- /** Extra dependencies to add if a dependency on an older test framework (one released before the uniform test interface) is declared.
- * This is the compatibility test framework by default.*/
- def compatTestFramework = Set("org.scala-tools.sbt" %% "test-compat" % "0.4.1" % "test")
-
- def defaultModuleSettings: ModuleSettings =
- {
- val in = inlineSettings
- if(in.configurations.isEmpty)
- {
- if(in.dependencies.isEmpty && in.ivyXML.isEmpty && (in.module.explicitArtifacts.size <= 1) && in.configurations.isEmpty)
- externalSettings
- else if(useDefaultConfigurations)
- in withConfigurations ( Configurations.defaultMavenConfigurations )
- else
- in
- }
- else
- in
- }
- def externalSettings = ModuleSettings(ivyScala, ivyValidate, projectID)(info.projectPath.asFile, log)
-
- def ivySbt: IvySbt = new IvySbt(ivyConfiguration)
- def ivyModule: IvySbt#Module = newIvyModule(moduleSettings)
- def newIvyModule(moduleSettings: ModuleSettings): IvySbt#Module =
- {
- val i = ivySbt
- new i.Module(moduleSettings)
- }
-
-
- /** The pattern for Ivy to use when retrieving dependencies into the local project. Classpath management
- * depends on the first directory being [conf] and the extension being [ext].*/
- def outputPattern = "[conf]/[artifact](-[revision])(-[classifier]).[ext]"
- /** Override this to specify the publications, configurations, and/or dependencies sections of an Ivy file.
- * See http://code.google.com/p/simple-build-tool/wiki/LibraryManagement for details.*/
- def ivyXML: NodeSeq = NodeSeq.Empty
- def pomExtra: NodeSeq = NodeSeq.Empty
-
- override def ivyConfigurations: Iterable[Configuration] =
- {
- val reflective = super.ivyConfigurations
- val extra = extraDefaultConfigurations
- if(useDefaultConfigurations)
- {
- if(reflective.isEmpty && extra.isEmpty)
- Nil
- else
- Configurations.removeDuplicates(Configurations.defaultMavenConfigurations ++ reflective ++ extra)
- }
- else
- reflective ++ extra
- }
- def extraDefaultConfigurations: List[Configuration] = Nil
- def useIntegrationTestConfiguration = false
- def defaultConfiguration: Option[Configuration] = Some(Configurations.DefaultConfiguration(useDefaultConfigurations))
- def useMavenConfigurations = true // TODO: deprecate after going through a minor version series to verify that this works ok
- def useDefaultConfigurations = useMavenConfigurations
- def managedStyle: ManagedType =
- info.parent match
- {
- case Some(m: BasicManagedProject) => m.managedStyle
- case _ => Auto
- }
- protected implicit final val defaultPatterns: Patterns =
- {
- managedStyle match
- {
- case Maven => Resolver.mavenStylePatterns
- case Ivy => Resolver.ivyStylePatterns
- case Auto => Resolver.defaultPatterns
- }
- }
-
- def updateModuleSettings = moduleSettings
- def updateIvyModule = newIvyModule(updateModuleSettings)
- def deliverModuleSettings = moduleSettings.noScala
- def deliverIvyModule = newIvyModule(deliverModuleSettings)
- def publishModuleSettings = deliverModuleSettings
- def publishIvyModule = newIvyModule(publishModuleSettings)
- /** True if the default implicit extensions should be used when determining classpaths. The default value is true. */
- def defaultConfigurationExtensions = true
- /** If true, verify that explicit dependencies on Scala libraries use the same version as scala.version. */
- def checkExplicitScalaDependencies = true
- /** If true, filter dependencies on scala-library and scala-compiler. This is true by default to avoid conflicts with
- * the jars provided by sbt. You can set this to false to download these jars. Overriding checkScalaInConfigurations might
- * be more appropriate, however.*/
- def filterScalaJars = true
- /** The configurations to check/filter.*/
- def checkScalaInConfigurations: Iterable[Configuration] = ivyConfigurations
- def defaultPublishRepository: Option[Resolver] =
- {
- reflectiveRepositories.get(PublishToName) orElse
- info.parent.flatMap
- {
- case managed: BasicManagedProject => managed.defaultPublishRepository
- case _ => None
- }
- }
- /** Includes the Compile configuration on the Runtime classpath, and Compile and Runtime on the Test classpath.
- * Including Compile and Runtime can be disabled by setting defaultConfigurationExtensions to false.*/
- override def managedClasspath(config: Configuration) =
- {
- import Configurations.{Compile, Default, Runtime, Test}
- val baseClasspath = configurationClasspath(config)
- config match
- {
- case Compile => baseClasspath +++ managedClasspath(Default)
- case Runtime if defaultConfigurationExtensions => baseClasspath +++ managedClasspath(Compile)
- case Test if defaultConfigurationExtensions => baseClasspath +++ managedClasspath(Runtime)
- case _ => baseClasspath
- }
- }
-
- protected def updateAction = updateTask(updateIvyModule, ivyUpdateConfiguration) describedAs UpdateDescription
- protected def cleanLibAction = cleanLibTask(managedDependencyPath) describedAs CleanLibDescription
- protected def cleanCacheAction = cleanCacheTask(ivySbt) describedAs CleanCacheDescription
-
- protected def deliverProjectDependencies: Iterable[ModuleID] =
- {
- val interDependencies = new scala.collection.mutable.ListBuffer[ModuleID]
- dependencies.foreach(dep => dep match { case mp: ManagedProject => interDependencies += mp.projectID; case _ => () })
- if(filterScalaJars)
- interDependencies ++= deliverScalaDependencies
- interDependencies.readOnly
- }
- def pomIncludeRepository(repo: MavenRepository): Boolean = !repo.root.startsWith("file:")
- def pomPostProcess(pom: Node): Node = pom
-
- def makePomConfiguration = new MakePomConfiguration(deliverProjectDependencies, None, pomExtra, pomPostProcess, pomIncludeRepository)
- protected def deliverScalaDependencies: Iterable[ModuleID] = Nil
- protected def makePomAction = makePomTask(deliverIvyModule, makePomConfiguration, pomPath)
- protected def deliverLocalAction = deliverTask(deliverIvyModule, publishLocalConfiguration, ivyUpdateLogging)
- protected def publishLocalAction =
- {
- val dependencies = deliverLocal :: publishPomDepends
- publishTask(publishIvyModule, publishLocalConfiguration) dependsOn(dependencies : _*)
- }
- protected def publishLocalConfiguration = new DefaultPublishConfiguration("local", "release", true)
- protected def deliverAction = deliverTask(deliverIvyModule, publishConfiguration, ivyUpdateLogging)
- protected def publishAction =
- {
- val dependencies = deliver :: publishPomDepends
- publishTask(publishIvyModule, publishConfiguration) dependsOn(dependencies : _*)
- }
- private def publishPomDepends = if(managedStyle == Maven) makePom :: Nil else Nil
- protected def publishConfiguration =
- {
- val repository = defaultPublishRepository.getOrElse(error("Repository to publish to not specified."))
- val publishIvy = managedStyle != Maven
- new DefaultPublishConfiguration(repository, "release", publishIvy)
- }
- protected class DefaultPublishConfiguration(val resolverName: String, val status: String, val publishIvy: Boolean) extends PublishConfiguration
- {
- def this(resolver: Resolver, status: String, publishIvy: Boolean) = this(resolver.name, status, publishIvy)
- def this(resolverName: String, status: String) = this(resolverName, status, true)
- def this(resolver: Resolver, status: String) = this(resolver.name, status)
-
- protected def deliveredPathPattern = outputPath / "[artifact]-[revision](-[classifier]).[ext]"
- def deliveredPattern = deliveredPathPattern.relativePath
- def srcArtifactPatterns: Iterable[String] =
- {
- val pathPatterns =
- (outputPath / "[artifact]-[revision]-[type](-[classifier]).[ext]") ::
- (outputPath / "[artifact]-[revision](-[classifier]).[ext]") ::
- Nil
- pathPatterns.map(_.relativePath)
- }
- def extraDependencies: Iterable[ModuleID] = deliverProjectDependencies
- /** The configurations to include in the publish/deliver action: specify none for all public configurations. */
- def configurations: Option[Iterable[Configuration]] = None
- }
-
- def packageToPublishActions: Seq[ManagedTask] = Nil
-
- private[this] def depMap[T](f: BasicManagedProject => T) =
- topologicalSort.dropRight(1).flatMap { case m: BasicManagedProject => f(m) :: Nil; case _ => Nil }
-
- lazy val update = updateAction
- lazy val makePom = makePomAction dependsOn(packageToPublishActions : _*)
- lazy val cleanLib = cleanLibAction
- lazy val cleanCache = cleanCacheAction
- // deliver must run after its dependencies' `publish` so that the artifacts produced by the dependencies can be resolved
- // (deliver requires a resolve first)
- lazy val deliverLocal: Task = deliverLocalAction dependsOn((depMap(_.publishLocal) ++ packageToPublishActions) : _*)
- lazy val publishLocal: Task = publishLocalAction
- lazy val deliver: Task = deliverAction dependsOn((depMap(_.publish) ++ packageToPublishActions) : _*)
- lazy val publish: Task = publishAction
-}
-
-object BasicManagedProject
-{
- val UpdateDescription =
- "Resolves and retrieves automatically managed dependencies."
- val CleanLibDescription =
- "Deletes the managed library directory."
- val CleanCacheDescription =
- "Deletes the cache of artifacts downloaded for automatically managed dependencies."
-
- val PublishToName = "publish-to"
- val RetrieveFromName = "retrieve-from"
-}
-
-class DefaultInstallProject(val info: ProjectInfo) extends InstallProject with MavenStyleScalaPaths with BasicDependencyProject
-{
- def fullUnmanagedClasspath(config: Configuration) = unmanagedClasspath
- def dependencies = info.dependencies
-}
-trait InstallProject extends BasicManagedProject
-{
- def installModuleSettings: ModuleSettings = moduleSettings.noScala
- def installIvyModule: IvySbt#Module = newIvyModule(installModuleSettings)
-
- lazy val install = installTask(installIvyModule, fromResolver, toResolver)
- def toResolver = reflectiveRepositories.get(PublishToName).getOrElse(error("No repository to publish to was specified"))
- def fromResolver = reflectiveRepositories.get(RetrieveFromName).getOrElse(error("No repository to retrieve from was specified"))
-}
-
-trait BasicDependencyPaths extends ManagedProject
-{
- import BasicDependencyPaths._
- def dependencyDirectoryName = DefaultDependencyDirectoryName
- def managedDirectoryName = DefaultManagedDirectoryName
- def pomName = artifactBaseName + PomExtension
- def dependencyPath = path(dependencyDirectoryName)
- def managedDependencyPath = crossPath(managedDependencyRootPath)
- def managedDependencyRootPath: Path = managedDirectoryName
- def pomPath = outputPath / pomName
-}
-object BasicDependencyPaths
-{
- val DefaultManagedDirectoryName = "lib_managed"
- val DefaultManagedSourceDirectoryName = "src_managed"
- val DefaultDependencyDirectoryName = "lib"
- val PomExtension = ".pom"
-}
-import scala.collection.{Map, mutable}
-/** A Project that determines its tasks by reflectively finding all vals with a type
-* that conforms to Task.*/
-trait ReflectiveTasks extends Project
-{
- def tasks: Map[String, ManagedTask] = reflectiveTaskMappings
- def reflectiveTaskMappings : Map[String, Task] = Reflective.reflectiveMappings[Task](this)
-}
-/** A Project that determines its method tasks by reflectively finding all vals with a type
-* that conforms to MethodTask.*/
-trait ReflectiveMethods extends Project
-{
- def methods: Map[String, MethodTask] = reflectiveMethodMappings
- def reflectiveMethodMappings : Map[String, MethodTask] = Reflective.reflectiveMappings[MethodTask](this)
-}
-/** A Project that determines its dependencies on other projects by reflectively
-* finding all vals with a type that conforms to Project.*/
-trait ReflectiveModules extends Project
-{
- override def subProjects: Map[String, Project] = reflectiveModuleMappings
- def reflectiveModuleMappings : Map[String, Project] = Reflective.reflectiveMappings[Project](this)
-}
-/** A Project that determines its dependencies on other projects by reflectively
-* finding all vals with a type that conforms to Project and determines its tasks
-* by reflectively finding all vals with a type that conforms to Task.*/
-trait ReflectiveProject extends ReflectiveModules with ReflectiveTasks with ReflectiveMethods
-
-/** This Project subclass is used to contain other projects as dependencies.*/
-class ParentProject(val info: ProjectInfo) extends BasicDependencyProject with Cleanable
-{
- def dependencies: Iterable[Project] = info.dependencies ++ subProjects.values.toList
- /** The directories to which a project writes are listed here and is used
- * to check a project and its dependencies for collisions.*/
- override def outputDirectories = managedDependencyPath :: outputPath :: Nil
- def fullUnmanagedClasspath(config: Configuration) = unmanagedClasspath
-}
-
-object Reflective
-{
- def reflectiveMappings[T](obj: AnyRef)(implicit m: scala.reflect.Manifest[T]): Map[String, T] =
- {
- val mappings = new mutable.HashMap[String, T]
- for ((name, value) <- ReflectUtilities.allVals[T](obj))
- mappings(ReflectUtilities.transformCamelCase(name, '-')) = value
- mappings
- }
-}
-
-/** A Project that determines its library dependencies by reflectively finding all vals with a type
-* that conforms to ModuleID.*/
-trait ReflectiveLibraryDependencies extends ManagedProject
-{
- def excludeIDs: Iterable[ModuleID] = projectID :: Nil
- /** Defines the library dependencies of this project. By default, this finds vals of type ModuleID defined on the project.
- * This can be overridden to directly provide dependencies */
- def libraryDependencies: Set[ModuleID] = reflectiveLibraryDependencies
- def reflectiveLibraryDependencies : Set[ModuleID] = Set[ModuleID](Reflective.reflectiveMappings[ModuleID](this).values.toList: _*) -- excludeIDs
-}
-
-trait ReflectiveConfigurations extends Project
-{
- def ivyConfigurations: Iterable[Configuration] = reflectiveIvyConfigurations
- def reflectiveIvyConfigurations: Set[Configuration] = Configurations.removeDuplicates(Reflective.reflectiveMappings[Configuration](this).values.toList)
-}
-trait ReflectiveArtifacts extends ManagedProject
-{
- def managedStyle: ManagedType
- def artifacts: Set[Artifact] =
- {
- val reflective = reflectiveArtifacts
- managedStyle match
- {
- case Maven => reflective ++ List(Artifact(artifactID, "pom", "pom"))
- case Ivy => reflective
- case Auto => reflective
- }
- }
- def reflectiveArtifacts: Set[Artifact] = Set(Reflective.reflectiveMappings[Artifact](this).values.toList: _*)
-}
-/** A Project that determines its library dependencies by reflectively finding all vals with a type
-* that conforms to ModuleID.*/
-trait ReflectiveRepositories extends Project
-{
- def repositories: Set[Resolver] =
- {
- val reflective = Set[Resolver]() ++ reflectiveRepositories.toList.flatMap { case (PublishToName, _) => Nil; case (_, value) => List(value) }
- info.parent match
- {
- case Some(p: ReflectiveRepositories) => p.repositories ++ reflective
- case None => reflective
- }
- }
- def reflectiveRepositories: Map[String, Resolver] = Reflective.reflectiveMappings[Resolver](this)
-
- def moduleConfigurations: Set[ModuleConfiguration] =
- {
- val reflective = Set[ModuleConfiguration](reflectiveModuleConfigurations.values.toList: _*)
- info.parent match
- {
- case Some(p: ReflectiveRepositories) => p.moduleConfigurations ++ reflective
- case None => reflective
- }
- }
- def reflectiveModuleConfigurations: Map[String, ModuleConfiguration] = Reflective.reflectiveMappings[ModuleConfiguration](this)
-}
-
-trait ReflectiveManagedProject extends ReflectiveProject with ReflectiveArtifacts with ReflectiveRepositories with ReflectiveLibraryDependencies with ReflectiveConfigurations
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/BuilderProject.scala b/sbt_pending/src/main/scala/sbt/BuilderProject.scala
deleted file mode 100644
index 3504ebc72..000000000
--- a/sbt_pending/src/main/scala/sbt/BuilderProject.scala
+++ /dev/null
@@ -1,262 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah, David MacIver
- */
-package sbt
-
-import BasicProjectPaths._
-import scala.collection.{immutable, Map}
-import immutable.Map.{empty => emptyMap}
-
-sealed abstract class InternalProject extends Project
-{
- override def defaultLoggingLevel = Level.Warn
- override final def historyPath = None
- override def tasks: Map[String, ManagedTask] = emptyMap
- override final protected def disableCrossPaths = false
- override final def shouldCheckOutputDirectories = false
-}
-sealed abstract class BasicBuilderProject extends InternalProject
-{
- def sourceFilter = "*.scala" | "*.java"
- def jarFilter: NameFilter = "*.jar"
- def compilePath = outputPath / DefaultMainCompileDirectoryName
- def mainResourcesPath = path(DefaultResourcesDirectoryName)
- def dependencyPath = path(DefaultDependencyDirectoryName)
- def libraries = descendents(dependencyPath, jarFilter)
- override final def dependencies = Nil
-
- protected final def logInfo(messages: String*): Unit = atInfo { messages.foreach(message => log.info(message)) }
- protected final def atInfo(action: => Unit)
- {
- val oldLevel = log.getLevel
- log.setLevel(Level.Info)
- action
- log.setLevel(oldLevel)
- }
-
- def projectClasspath = compilePath +++ libraries +++ sbtJars
- def sbtJars = info.sbtClasspath
-
- abstract class BuilderCompileConfiguration extends AbstractCompileConfiguration
- {
- def projectPath = info.projectPath
- def log = BasicBuilderProject.this.log
- def options = CompileOptions.Deprecation :: CompileOptions.Unchecked :: Nil
- def javaOptions = Nil
- def maxErrors = ScalaProject.DefaultMaximumCompileErrors
- def compileOrder = CompileOrder.Mixed
- }
- def definitionCompileConfiguration =
- new BuilderCompileConfiguration
- {
- def label = "builder"
- def sourceRoots = info.projectPath +++ path(DefaultSourceDirectoryName)
- def sources = (info.projectPath * sourceFilter) +++ path(DefaultSourceDirectoryName).descendentsExcept(sourceFilter, defaultExcludes)
- def outputDirectory = compilePath
- def classpath = projectClasspath
- def analysisPath = outputPath / DefaultMainAnalysisDirectoryName
- }
-
- def tpe: String
-
- import xsbt.ScalaInstance
-
- lazy val definitionCompileConditional = new BuilderCompileConditional(definitionCompileConfiguration, buildCompiler, tpe)
- final class BuilderCompileConditional(config: BuilderCompileConfiguration, compiler: xsbt.AnalyzingCompiler, tpe: String) extends AbstractCompileConditional(config, compiler)
- {
- type AnalysisType = BuilderCompileAnalysis
- override protected def constructAnalysis(analysisPath: Path, projectPath: Path, log: Logger) =
- new BuilderCompileAnalysis(analysisPath, projectPath, log)
- override protected def execute(cAnalysis: ConditionalAnalysis): Option[String] =
- {
- if(cAnalysis.dirtySources.isEmpty)
- None
- else
- {
- definitionChanged()
- logInfo(
- "Recompiling " + tpe + "...",
- "\t" + cAnalysis.toString)
- super.execute(cAnalysis)
- }
- }
- protected def analysisCallback: AnalysisCallback =
- new BasicAnalysisCallback(info.projectPath, analysis)
- {
- def superclassNames = List(Project.ProjectClassName)
- def annotationNames = Nil
- def foundApplication(sourcePath: Path, className: String) {}
- def foundAnnotated(sourcePath: Path, subclassName: String, annotationName: String, isModule: Boolean) {}
- def foundSubclass(sourcePath: Path, subclassName: String, superclassName: String, isModule: Boolean)
- {
- if(superclassName == Project.ProjectClassName && !isModule)
- {
- log.debug("Found " + tpe + " " + subclassName)
- analysis.addProjectDefinition(sourcePath, subclassName)
- }
- }
- }
- }
- protected def definitionChanged() {}
- lazy val compile = compileTask
- def compileTask = task { definitionCompileConditional.run }
-
- def projectDefinition: Either[String, Option[String]] =
- {
- definitionCompileConditional.analysis.allProjects.toList match
- {
- case Nil =>
- log.debug("No " + tpe + "s detected using default project.")
- Right(None)
- case singleDefinition :: Nil => Right(Some(singleDefinition))
- case multipleDefinitions =>Left(multipleDefinitions.mkString("Multiple " + tpe + "s detected: \n\t","\n\t","\n"))
- }
- }
- override final def methods = emptyMap
-}
-/** The project definition used to build project definitions. */
-final class BuilderProject(val info: ProjectInfo, val pluginPath: Path, rawLogger: Logger) extends BasicBuilderProject with ReflectiveTasks
-{
- override def name = "Project Definition Builder"
- lazy val pluginProject =
- {
- if(pluginPath.exists)
- Some(new PluginBuilderProject(ProjectInfo(pluginPath.asFile, Nil, None)(rawLogger, info.app, info.buildScalaVersion)))
- else
- None
- }
- override def projectClasspath = super.projectClasspath +++
- pluginProject.map(_.pluginClasspath).getOrElse(Path.emptyPathFinder)
- def tpe = "project definition"
-
- override def compileTask = super.compileTask dependsOn(pluginProject.map(_.sync).toList : _*)
- override def tasks = immutable.Map() ++ super[ReflectiveTasks].tasks ++ pluginProject.toList.flatMap { _.tasks.map { case (k,v) => (k + "-plugins", v) } }
-
- final class PluginBuilderProject(val info: ProjectInfo) extends BasicBuilderProject with ReflectiveTasks
- {
- override def name = "Plugin Builder"
- // don't include Java sources because BND includes Java sources in its jar (#85)
- def pluginSourceFilter: NameFilter = "*.scala"
- lazy val pluginUptodate = propertyOptional[Boolean](false)
- def tpe = "plugin definition"
- def managedSourcePath = path(BasicDependencyPaths.DefaultManagedSourceDirectoryName)
- def managedDependencyPath = crossPath(BasicDependencyPaths.DefaultManagedDirectoryName)
- override protected def definitionChanged() { setUptodate(false) }
- override def tasks: Map[String, ManagedTask] = super[ReflectiveTasks].tasks
- def setUptodate(flag: Boolean)
- {
- pluginUptodate() = flag
- saveEnvironment()
- }
-
- private def pluginTask(f: => Option[String]) = task { if(!pluginUptodate.value) f else None }
-
- lazy val sync = pluginTask(doSync()) dependsOn(extract)
- lazy val extract = pluginTask(extractSources()) dependsOn(autoUpdate)
- lazy val autoUpdate = pluginTask(loadAndUpdate(false)) dependsOn(compile)
- // manual update. force uptodate = false
- lazy val update = task { manualUpdate() } dependsOn(compile) describedAs("Manual plugin update. Used when autoUpdate is disabled.")
-
- def manualUpdate() =
- {
- setUptodate(false)
- val result = loadAndUpdate(true)
- logInfo("'reload' required to rebuild plugins.")
- result
- }
- def doSync() = pluginCompileConditional.run orElse { setUptodate(true); None }
- def extractSources() =
- {
- FileUtilities.clean(managedSourcePath, log) orElse
- Control.lazyFold(plugins.get.toList) { jar =>
- Control.thread(FileUtilities.unzip(jar, extractTo(jar), pluginSourceFilter, log)) { extracted =>
- if(!extracted.isEmpty)
- logInfo("\tExtracted source plugin " + jar + " ...")
- None
- }
- }
- }
- def loadAndUpdate(forceUpdate: Boolean) =
- {
- Control.thread(projectDefinition) {
- case Some(definition) =>
- val pluginInfo = ProjectInfo(info.projectPath.asFile, Nil, None)(rawLogger, info.app, info.buildScalaVersion)
- val pluginBuilder = Project.constructProject(pluginInfo, Project.getProjectClass[PluginDefinition](definition, projectClasspath, getClass.getClassLoader))
- if(forceUpdate || pluginBuilder.autoUpdate)
- {
- logInfo("\nUpdating plugins...")
- pluginBuilder.projectName() = "Plugin Definition"
- pluginBuilder.projectVersion() = OpaqueVersion("1.0")
- val result = pluginBuilder.update.run
- if(result.isEmpty)
- {
- atInfo {
- log.success("Plugins updated successfully.")
- log.info("")
- }
- }
- result
- }
- else
- {
- log.warn("Plugin definition recompiled, but autoUpdate is disabled.\n\tUsing already retrieved plugins...")
- None
- }
- case None => None
- }
- }
- def extractTo(jar: Path) =
- {
- val name = jar.asFile.getName
- managedSourcePath / name.substring(0, name.length - ".jar".length)
- }
- def plugins = descendents(managedDependencyPath, jarFilter)
- def pluginClasspath: PathFinder = plugins +++ pluginCompileConfiguration.outputDirectory
-
- lazy val pluginCompileConditional = new BuilderCompileConditional(pluginCompileConfiguration, buildCompiler, "plugin")
- lazy val pluginCompileConfiguration =
- new BuilderCompileConfiguration
- {
- def label = "plugin builder"
- def sourceRoots = managedSourcePath
- def sources = descendents(sourceRoots, sourceFilter)
- def outputDirectory = outputPath / "plugin-classes"
- def classpath: PathFinder = pluginClasspath +++ sbtJars
- def analysisPath = outputPath / "plugin-analysis"
- }
- }
-}
-class PluginDefinition(val info: ProjectInfo) extends InternalProject with BasicManagedProject
-{
- override def defaultLoggingLevel = Level.Info
- override final def outputPattern = "[artifact](-[revision]).[ext]"
- override final val tasks = immutable.Map("update" -> update)
- override def projectClasspath(config: Configuration) = Path.emptyPathFinder
- override def dependencies = info.dependencies
- def autoUpdate = true
-}
-class PluginProject(info: ProjectInfo) extends DefaultProject(info)
-{
- /* Since plugins are distributed as source, there is no need to append _ */
- override def moduleID = normalizedName
- /* Fix the version used to build to the version currently running sbt. */
- override def buildScalaVersion = defScalaVersion.value
- /* Add sbt to the classpath */
- override def unmanagedClasspath = super.unmanagedClasspath +++ info.sbtClasspath
- /* Package the plugin as source. */
- override def packageAction = packageSrc dependsOn(test)
- override def packageSrcJar = jarPath
- /* Some setup to make publishing quicker to configure. */
- override def useMavenConfigurations = true
- override def managedStyle = ManagedStyle.Maven
-}
-class ProcessorProject(info: ProjectInfo) extends DefaultProject(info)
-{
- /* Fix the version used to build to the version currently running sbt. */
- override def buildScalaVersion = defScalaVersion.value
- /* Add sbt to the classpath */
- override def unmanagedClasspath = super.unmanagedClasspath +++ info.sbtClasspath
- /* Some setup to make publishing quicker to configure. */
- override def useMavenConfigurations = true
- override def managedStyle = ManagedStyle.Maven
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/Control.scala b/sbt_pending/src/main/scala/sbt/Control.scala
deleted file mode 100644
index 8117fe29a..000000000
--- a/sbt_pending/src/main/scala/sbt/Control.scala
+++ /dev/null
@@ -1,73 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package sbt
-
-/** The trap methods execute the provided code in a try block and handle a thrown exception.*/
-object Control
-{
- def trap[T](errorMessagePrefix: => String, log: Logger)(execute: => Either[String, T]): Either[String, T] =
- try { execute }
- catch { case e => log.trace(e); Left(errorMessagePrefix + e.toString) }
-
- def trapAndFinally[T](errorMessagePrefix: => String, log: Logger)(execute: => Either[String, T])(doFinally: => Unit): Either[String, T] =
- try { execute }
- catch { case e => log.trace(e); Left(errorMessagePrefix + e.toString) }
- finally { trapAndLog(log)(doFinally) }
-
- def trapUnit(errorMessagePrefix: => String, log: Logger)(execute: => Option[String]): Option[String] =
- try { execute }
- catch { case e => log.trace(e); Some(errorMessagePrefix + e.toString) }
-
- def trapUnitAndFinally(errorMessagePrefix: => String, log: Logger)(execute: => Option[String])(doFinally: => Unit): Option[String] =
- try { execute }
- catch { case e => log.trace(e); Some(errorMessagePrefix + e.toString) }
- finally { trapAndLog(log)(doFinally) }
-
- def trap(execute: => Unit)
- {
- try { execute }
- catch { case e: Exception => () }
- }
- def trapAndLog(log: Logger)(execute: => Unit)
- {
- try { execute }
- catch { case e => log.trace(e); log.error(e.toString) }
- }
- def convertException[T](t: => T): Either[Exception, T] =
- {
- try { Right(t) }
- catch { case e: Exception => Left(e) }
- }
- def convertErrorMessage[T](log: Logger)(t: => T): Either[String, T] =
- {
- try { Right(t) }
- catch { case e: Exception => log.trace(e); Left(e.toString) }
- }
-
- def getOrError[T](result: Either[String, T]): T = result.fold(error, x=>x)
- final def lazyFold[T](list: List[T])(f: T => Option[String]): Option[String] =
- list match
- {
- case Nil => None
- case head :: tail =>
- f(head) match
- {
- case None => lazyFold(tail)(f)
- case x => x
- }
- }
- final def lazyFold[T, S](list: List[T], value: S)(f: (S,T) => Either[String, S]): Either[String, S] =
- list match
- {
- case Nil => Right(value)
- case head :: tail =>
- f(value, head) match
- {
- case Right(newValue) => lazyFold(tail, newValue)(f)
- case x => x
- }
- }
- def thread[T](e: Either[String, T])(f: T => Option[String]): Option[String] =
- e.right.flatMap( t => f(t).toLeft(()) ).left.toOption
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/FileTask.scala b/sbt_pending/src/main/scala/sbt/FileTask.scala
deleted file mode 100644
index a59883083..000000000
--- a/sbt_pending/src/main/scala/sbt/FileTask.scala
+++ /dev/null
@@ -1,109 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Mark Harrah
- */
-package sbt
-
-import scala.collection.{mutable, Map, Set}
-
-sealed trait ProductsSources extends NotNull
-{
- def products: Iterable[Path]
- def sources: Iterable[Path]
-}
-sealed trait ProductsWrapper extends NotNull
-{
- def from(sources: => Iterable[Path]): ProductsSources = from(Path.lazyPathFinder(sources))
- def from(sources: PathFinder): ProductsSources
-}
-/** Provides methods to define tasks with basic conditional execution based on the sources
-* and products of the task. */
-trait FileTasks extends Project
-{
- implicit def wrapProduct(product: => Path): ProductsWrapper = FileTasks.wrapProduct(product)
- implicit def wrapProducts(productsList: => Iterable[Path]): ProductsWrapper = FileTasks.wrapProducts(productsList)
- /** Runs 'action' if the given products are out of date with respect to the given sources. */
- def fileTask(label: String, files: ProductsSources)(action: => Option[String]): Task =
- task { FileTasks.runOption(label, files, log)(action) }
- /** Runs 'action' if any of the given products do not exist. */
- def fileTask(label: String, products: => Iterable[Path])(action: => Option[String]): Task =
- task { FileTasks.existenceCheck[Option[String]](label, products, log)(action)(None) }
-
- /** Creates a new task that performs 'action' only when the given products are out of date with respect to the given sources.. */
- def fileTask(files: ProductsSources)(action: => Option[String]): Task = fileTask("", files)(action)
- /** Creates a new task that performs 'action' only when at least one of the given products does not exist.. */
- def fileTask(products: => Iterable[Path])(action: => Option[String]): Task = fileTask("", products)(action)
-
-}
-object FileTasks
-{
- implicit def wrapProduct(product: => Path): ProductsWrapper = wrapProducts(product :: Nil)
- implicit def wrapProducts(productsList: => Iterable[Path]): ProductsWrapper =
- new ProductsWrapper
- {
- def from(sourceFinder: PathFinder) =
- new ProductsSources
- {
- def products = productsList
- def sources = sourceFinder.get
- }
- }
- /** Runs 'ifOutofdate' if the given products are out of date with respect to the given sources.*/
- def runOption(label: String, files: ProductsSources, log: Logger)(ifOutofdate: => Option[String]): Option[String] =
- {
- val result = apply[Option[String]](label, files, log)(ifOutofdate)(None)
- if(result.isDefined)
- FileUtilities.clean(files.products, true, log)
- result
- }
- /** Returns 'ifOutofdate' if the given products are out of date with respect to the given sources. Otherwise, returns ifUptodate. */
- def apply[T](label: String, files: ProductsSources, log: Logger)(ifOutofdate: => T)(ifUptodate: => T): T =
- {
- val products = files.products
- require(!products.isEmpty, "No products were specified; products must be known in advance.")
- existenceCheck[T](label, products, log)(ifOutofdate)
- {
- val sources = files.sources
- if(sources.isEmpty)
- {
- log.debug("Running " + label + " task because no sources exist.")
- ifOutofdate
- }
- else
- {
- val oldestProductModifiedTime = mapLastModified(products).reduceLeft(_ min _)
- val newestSourceModifiedTime = mapLastModified(sources).reduceLeft(_ max _)
- if(oldestProductModifiedTime < newestSourceModifiedTime)
- {
- if(log.atLevel(Level.Debug))
- {
- log.debug("Running " + label + " task because the following sources are newer than at least one product: ")
- logDebugIndented(sources.filter(_.lastModified > oldestProductModifiedTime), log)
- log.debug(" The following products are older than at least one source: ")
- logDebugIndented(products.filter(_.lastModified < newestSourceModifiedTime), log)
- }
- ifOutofdate
- }
- else
- ifUptodate
- }
- }
- }
- /** Checks that all 'products' exist. If they do, 'ifAllExists' is returned, otherwise 'products' is returned.*/
- private def existenceCheck[T](label: String, products: Iterable[Path], log: Logger)(action: => T)(ifAllExist: => T) =
- {
- val nonexisting = products.filter(!_.exists)
- if(nonexisting.isEmpty)
- ifAllExist
- else
- {
- if(log.atLevel(Level.Debug))
- {
- log.debug("Running " + label + " task because at least one product does not exist:")
- logDebugIndented(nonexisting, log)
- }
- action
- }
- }
- private def logDebugIndented[T](it: Iterable[T], log: Logger) { it.foreach(x => log.debug("\t" + x)) }
- private def mapLastModified(paths: Iterable[Path]): Iterable[Long] = paths.map(_.lastModified)
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/FileUtilities.scala b/sbt_pending/src/main/scala/sbt/FileUtilities.scala
deleted file mode 100644
index 0d0477906..000000000
--- a/sbt_pending/src/main/scala/sbt/FileUtilities.scala
+++ /dev/null
@@ -1,933 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009, 2010 Mark Harrah, Nathan Hamblen, Justin Caballero
- */
-package sbt
-
-import java.io.{Closeable, File, FileInputStream, FileOutputStream, InputStream, OutputStream}
-import java.io.{ByteArrayOutputStream, InputStreamReader, OutputStreamWriter}
-import java.io.{BufferedReader, BufferedWriter, FileReader, FileWriter, Reader, Writer}
-import java.util.zip.{GZIPInputStream, GZIPOutputStream}
-import java.net.{URL, URISyntaxException}
-import java.nio.charset.{Charset, CharsetDecoder, CharsetEncoder}
-import java.nio.channels.FileChannel
-import java.util.jar.{Attributes, JarEntry, JarFile, JarInputStream, JarOutputStream, Manifest}
-import java.util.zip.{GZIPOutputStream, ZipEntry, ZipFile, ZipInputStream, ZipOutputStream}
-
-import OpenResource._
-
-final class Preserved private[sbt](toRestore: scala.collection.Map[File, Path], temp: File) extends NotNull
-{
- def restore(log: Logger) =
- {
- try
- {
- Control.lazyFold(toRestore.toList) { case (src, dest) =>
- FileUtilities.copyFile(src, dest.asFile, log)
- }
- }
- finally { FileUtilities.clean(Path.fromFile(temp) :: Nil, true, log) }
- }
-}
-
-/** A collection of file related methods. */
-object FileUtilities
-{
- import wrap.Wrappers.readOnly
- /** The size of the byte or char buffer used in various methods.*/
- private val BufferSize = 8192
- val Newline = System.getProperty("line.separator")
- /** A pattern used to split a String by path separator characters.*/
- private val PathSeparatorPattern = java.util.regex.Pattern.compile(File.pathSeparator)
-
- /** Splits a String around path separator characters. */
- private[sbt] def pathSplit(s: String) = PathSeparatorPattern.split(s)
-
- def preserve(paths: Iterable[Path], log: Logger): Either[String, Preserved] =
- {
- for(tmp <- createTemporaryDirectory(log).right) yield
- {
- val pathMap = new scala.collection.mutable.HashMap[File, Path]
- val destinationDirectory = Path.fromFile(tmp)
- for(source <- paths)
- {
- val toPath = Path.fromString(destinationDirectory, source.relativePath)
- copyFile(source, toPath, log)
- pathMap(toPath.asFile) = source
- }
- new Preserved(readOnly(pathMap), tmp)
- }
- }
-
- /** Gzips the file 'in' and writes it to 'out'. 'in' cannot be the same file as 'out'. */
- def gzip(in: Path, out: Path, log: Logger): Option[String] =
- {
- require(in != out, "Input file cannot be the same as the output file.")
- readStream(in.asFile, log) { inputStream =>
- writeStream(out.asFile, log) { outputStream =>
- gzip(inputStream, outputStream, log)
- }
- }
- }
- /** Gzips the InputStream 'in' and writes it to 'output'. Neither stream is closed.*/
- def gzip(input: InputStream, output: OutputStream, log: Logger): Option[String] =
- gzipOutputStream.ioOption(output, "gzipping", log) { gzStream => transfer(input, gzStream, log) }
-
- def gunzip(input: InputStream, output: OutputStream, log: Logger): Option[String] =
- gzipInputStream.ioOption(input, "gunzipping", log) { gzStream => transfer(gzStream, output, log) }
- /** Gunzips the file 'in' and writes it to 'out'. 'in' cannot be the same file as 'out'. */
- def gunzip(in: Path, out: Path, log: Logger): Option[String] =
- {
- require(in != out, "Input file cannot be the same as the output file.")
- readStream(in.asFile, log) { inputStream =>
- writeStream(out.asFile, log) { outputStream =>
- gunzip(inputStream, outputStream, log)
- }
- }
- }
-
- /** Creates a jar file.
- * @param sources The files to include in the jar file. The path used for the jar is
- * relative to the base directory for the source. That is, the path in the jar for source
- * (basePath ###) / x / y is x / y.
- * @param outputJar The file to write the jar to.
- * @param manifest The manifest for the jar.
- * @param recursive If true, any directories in sources are recursively processed. Otherwise,
- * they are not
- * @param log The Logger to use. */
- def jar(sources: Iterable[Path], outputJar: Path, manifest: Manifest, recursive: Boolean, log: Logger) =
- archive(sources, outputJar, Some(manifest), recursive, log)
- /** Creates a zip file.
- * @param sources The files to include in the jar file. The path used for the jar is
- * relative to the base directory for the source. That is, the path in the jar for source
- * (basePath ###) / x / y is x / y.
- * @param outputZip The file to write the zip to.
- * @param recursive If true, any directories in sources are recursively processed. Otherwise,
- * they are not
- * @param log The Logger to use. */
- def zip(sources: Iterable[Path], outputZip: Path, recursive: Boolean, log: Logger) =
- archive(sources, outputZip, None, recursive, log)
-
- private def archive(sources: Iterable[Path], outputPath: Path, manifest: Option[Manifest], recursive: Boolean, log: Logger) =
- {
- log.info("Packaging " + outputPath + " ...")
- val outputFile = outputPath.asFile
- if(outputFile.isDirectory)
- Some("Specified output file " + outputFile + " is a directory.")
- else
- {
- val outputDir = outputFile.getParentFile
- val result = createDirectory(outputDir, log) orElse
- withZipOutput(outputFile, manifest, log)
- { output =>
- val createEntry: (String => ZipEntry) = if(manifest.isDefined) new JarEntry(_) else new ZipEntry(_)
- writeZip(sources, output, recursive, log)(createEntry)
- }
- if(result.isEmpty)
- log.info("Packaging complete.")
- result
- }
- }
-
- private def writeZip(sources: Iterable[Path], output: ZipOutputStream, recursive: Boolean, log: Logger)(createEntry: String => ZipEntry) =
- {
- def add(source: Path)
- {
- val sourceFile = source.asFile
- if(sourceFile.isDirectory)
- {
- if(recursive)
- wrapNull(sourceFile.listFiles).foreach(file => add(source / file.getName))
- }
- else if(sourceFile.exists)
- {
- val relativePath = source.relativePathString("/")
- log.debug("\tAdding " + source + " as " + relativePath + " ...")
- val nextEntry = createEntry(relativePath)
- nextEntry.setTime(sourceFile.lastModified)
- output.putNextEntry(nextEntry)
- transferAndClose(new FileInputStream(sourceFile), output, log)
- output.closeEntry()
- }
- else
- log.warn("\tSource " + source + " does not exist.")
- }
- sources.foreach(add)
- None
- }
-
- private def withZipOutput(file: File, manifest: Option[Manifest], log: Logger)(f: ZipOutputStream => Option[String]): Option[String] =
- {
- writeStream(file, log)
- {
- fileOut =>
- {
- val (zipOut, ext) =
- manifest match
- {
- case Some(mf) =>
- {
- import Attributes.Name.MANIFEST_VERSION
- val main = mf.getMainAttributes
- if(!main.containsKey(MANIFEST_VERSION))
- main.put(MANIFEST_VERSION, "1.0")
- (new JarOutputStream(fileOut, mf), "jar")
- }
- case None => (new ZipOutputStream(fileOut), "zip")
- }
- Control.trapUnitAndFinally("Error writing " + ext + ": ", log)
- { f(zipOut) } { zipOut.close }
- }
- }
- }
- import scala.collection.Set
- /** Unzips the contents of the zip file from to the toDirectory directory.*/
- def unzip(from: Path, toDirectory: Path, log: Logger): Either[String, Set[Path]] =
- unzip(from, toDirectory, AllPassFilter, log)
- /** Unzips the contents of the zip file from to the toDirectory directory.*/
- def unzip(from: File, toDirectory: Path, log: Logger): Either[String, Set[Path]] =
- unzip(from, toDirectory, AllPassFilter, log)
- /** Unzips the contents of the zip file from to the toDirectory directory.*/
- def unzip(from: InputStream, toDirectory: Path, log: Logger): Either[String, Set[Path]] =
- unzip(from, toDirectory, AllPassFilter, log)
- /** Unzips the contents of the zip file from to the toDirectory directory.*/
- def unzip(from: URL, toDirectory: Path, log: Logger): Either[String, Set[Path]] =
- unzip(from, toDirectory, AllPassFilter, log)
-
- /** Unzips the contents of the zip file from to the toDirectory directory.
- * Only the entries that match the given filter are extracted. */
- def unzip(from: Path, toDirectory: Path, filter: NameFilter, log: Logger): Either[String, Set[Path]] =
- unzip(from.asFile, toDirectory, filter, log)
- /** Unzips the contents of the zip file from to the toDirectory directory.
- * Only the entries that match the given filter are extracted. */
- def unzip(from: File, toDirectory: Path, filter: NameFilter, log: Logger): Either[String, Set[Path]] =
- readStreamValue(from, log)(in => unzip(in, toDirectory, filter, log))
- /** Unzips the contents of the zip file from to the toDirectory directory.
- * Only the entries that match the given filter are extracted. */
- def unzip(from: URL, toDirectory: Path, filter: NameFilter, log: Logger): Either[String, Set[Path]] =
- readStreamValue(from, log) { stream => unzip(stream, toDirectory, filter, log) }
- /** Unzips the contents of the zip file from to the toDirectory directory.
- * Only the entries that match the given filter are extracted. */
- def unzip(from: InputStream, toDirectory: Path, filter: NameFilter, log: Logger): Either[String, Set[Path]] =
- {
- createDirectory(toDirectory, log) match
- {
- case Some(err) => Left(err)
- case None => zipInputStream.io(from, "unzipping", log) { zipInput => extract(zipInput, toDirectory, filter, log) }
- }
- }
- private def extract(from: ZipInputStream, toDirectory: Path, filter: NameFilter, log: Logger) =
- {
- val set = new scala.collection.mutable.HashSet[Path]
- // don't touch dirs as we unzip because we don't know order of zip entires (any child will
- // update the dir's time)
- val dirTimes = new scala.collection.mutable.HashMap[Path, Long]
- def next(): Option[String] =
- {
- val entry = from.getNextEntry
- if(entry == null)
- None
- else
- {
- val name = entry.getName
- val entryErr =
- if(filter.accept(name))
- {
- val target = Path.fromString(toDirectory, name)
- log.debug("Extracting zip entry '" + name + "' to '" + target + "'")
- if(entry.isDirectory)
- {
- dirTimes += target -> entry.getTime
- createDirectory(target, log)
- }
- else
- writeStream(target.asFile, log) { out => FileUtilities.transfer(from, out, log) } orElse
- {
- set += target
- touchExisting(target.asFile, entry.getTime, log)
- None
- }
- }
- else
- {
- log.debug("Ignoring zip entry '" + name + "'")
- None
- }
- from.closeEntry()
- entryErr match { case None => next(); case x => x }
- }
- }
- val result = next()
- for ((dir, time) <- dirTimes) touchExisting(dir.asFile, time, log)
- result.toLeft(readOnly(set))
- }
-
- /** Copies all bytes from the given input stream to the given output stream.
- * Neither stream is closed.*/
- def transfer(in: InputStream, out: OutputStream, log: Logger): Option[String] =
- transferImpl(in, out, false, log)
- /** Copies all bytes from the given input stream to the given output stream. The
- * input stream is closed after the method completes.*/
- def transferAndClose(in: InputStream, out: OutputStream, log: Logger): Option[String] =
- transferImpl(in, out, true, log)
- private def transferImpl(in: InputStream, out: OutputStream, close: Boolean, log: Logger): Option[String] =
- {
- Control.trapUnitAndFinally("Error during transfer: ", log)
- {
- val buffer = new Array[Byte](BufferSize)
- def read: None.type =
- {
- val byteCount = in.read(buffer)
- if(byteCount >= 0)
- {
- out.write(buffer, 0, byteCount)
- read
- }
- else
- None
- }
- read
- }
- { if(close) in.close }
- }
-
- /** Creates a file at the given location.*/
- def touch(path: Path, log: Logger): Option[String] = touch(path.asFile, log)
- /** Creates a file at the given location.*/
- def touch(file: File, log: Logger): Option[String] =
- {
- Control.trapUnit("Could not create file " + file + ": ", log)
- {
- if(file.exists)
- touchExisting(file, System.currentTimeMillis, log)
- else
- createDirectory(file.getParentFile, log) orElse { file.createNewFile(); None }
- }
- }
- /** Sets the last mod time on the given {@code file}, which must already exist */
- private def touchExisting(file: File, time: Long, log: Logger): Option[String] =
- {
- def updateFailBase = "Could not update last modified for file " + file
- Control.trapUnit(updateFailBase + ": ", log)
- { if(file.setLastModified(time)) None else Some(updateFailBase) }
- }
- /** Creates a directory at the given location.*/
- def createDirectory(dir: Path, log: Logger): Option[String] = createDirectory(dir.asFile, log)
- /** Creates a directory at the given location.*/
- def createDirectory(dir: File, log: Logger): Option[String] =
- {
- Control.trapUnit("Could not create directory " + dir + ": ", log)
- {
- if(dir.exists)
- {
- if(dir.isDirectory)
- None
- else
- Some(dir + " exists and is not a directory.")
- }
- else
- {
- dir.mkdirs()
- log.debug("Created directory " + dir)
- None
- }
- }
- }
- /** Creates directories at the given locations.*/
- def createDirectories(d: Iterable[Path], log: Logger): Option[String] = createDirectories(Path.getFiles(d).toList, log)
- /** Creates directories at the given locations.*/
- def createDirectories(d: List[File], log: Logger): Option[String] =
- d match
- {
- case Nil => None
- case head :: tail => createDirectory(head, log) orElse createDirectories(tail, log)
- }
- /** The maximum number of times a unique temporary filename is attempted to be created.*/
- private val MaximumTries = 10
- /** Creates a temporary directory and returns it.*/
- def createTemporaryDirectory(log: Logger): Either[String, File] =
- {
- def create(tries: Int): Either[String, File] =
- {
- if(tries > MaximumTries)
- Left("Could not create temporary directory.")
- else
- {
- val randomName = "sbt_" + java.lang.Integer.toHexString(random.nextInt)
- val f = new File(temporaryDirectory, randomName)
-
- if(createDirectory(f, log).isEmpty)
- Right(f)
- else
- create(tries + 1)
- }
- }
- create(0)
- }
-
- def withTemporaryDirectory(log: Logger)(action: File => Option[String]): Option[String] =
- doInTemporaryDirectory(log: Logger)(file => action(file).toLeft(())).left.toOption
- /** Creates a temporary directory and provides its location to the given function. The directory
- * is deleted after the function returns.*/
- def doInTemporaryDirectory[T](log: Logger)(action: File => Either[String, T]): Either[String, T] =
- {
- def doInDirectory(dir: File): Either[String, T] =
- {
- Control.trapAndFinally("", log)
- { action(dir) }
- { delete(dir, true, log) }
- }
- createTemporaryDirectory(log).right.flatMap(doInDirectory)
- }
- def withTemporaryFile[T](log: Logger, prefix: String, postfix: String)(action: File => Either[String, T]): Either[String, T] =
- {
- Control.trap("Error creating temporary file: ", log)
- {
- val file = File.createTempFile(prefix, postfix)
- Control.trapAndFinally("", log)
- { action(file) }
- { file.delete() }
- }
- }
-
- /** Copies the files declared in sources to the destinationDirectory
- * directory. The source directory hierarchy is flattened so that all copies are immediate
- * children of destinationDirectory. Directories are not recursively entered.*/
- def copyFlat(sources: Iterable[Path], destinationDirectory: Path, log: Logger) =
- {
- val targetSet = new scala.collection.mutable.HashSet[Path]
- copyImpl(sources, destinationDirectory, log)
- {
- source =>
- {
- val from = source.asFile
- val toPath = destinationDirectory / from.getName
- targetSet += toPath
- val to = toPath.asFile
- if(!to.exists || from.lastModified > to.lastModified && !from.isDirectory)
- {
- log.debug("Copying " + source + " to " + toPath)
- copyFile(from, to, log)
- }
- else
- None
- }
- }.toLeft(readOnly(targetSet))
- }
- private def copyImpl(sources: Iterable[Path], destinationDirectory: Path, log: Logger)
- (doCopy: Path => Option[String]): Option[String] =
- {
- val target = destinationDirectory.asFile
- val creationError =
- if(target.isDirectory)
- None
- else
- createDirectory(target, log)
- def copy(sources: List[Path]): Option[String] =
- {
- sources match
- {
- case src :: remaining =>
- {
- doCopy(src) match
- {
- case None => copy(remaining)
- case error => error
- }
- }
- case Nil => None
- }
- }
- creationError orElse ( Control.trapUnit("", log) { copy(sources.toList) } )
- }
- /** Retrieves the content of the given URL and writes it to the given File. */
- def download(url: URL, to: File, log: Logger) =
- {
- readStream(url, log) { inputStream =>
- writeStream(to, log) { outputStream =>
- transfer(inputStream, outputStream, log)
- }
- }
- }
-
- /**
- * Equivalent to {@code copy(sources, destinationDirectory, false, log)}.
- */
- def copy(sources: Iterable[Path], destinationDirectory: Path, log: Logger): Either[String, Set[Path]] =
- copy(sources, destinationDirectory, false, log)
-
- /**
- * Equivalent to {@code copy(sources, destinationDirectory, overwrite, false, log)}.
- */
- def copy(sources: Iterable[Path], destinationDirectory: Path, overwrite: Boolean, log: Logger): Either[String, Set[Path]] =
- copy(sources, destinationDirectory, overwrite, false, log)
-
- /** Copies the files declared in sources to the destinationDirectory
- * directory. Directories are not recursively entered. The destination hierarchy matches the
- * source paths relative to any base directories. For example:
- *
- * A source (basePath ###) / x / y is copied to destinationDirectory / x / y.
- *
- * @param overwrite if true, existing destination files are always overwritten
- * @param preserveLastModified if true, the last modified time of copied files will be set equal to
- * their corresponding source files.
- */
- def copy(sources: Iterable[Path], destinationDirectory: Path,
- overwrite: Boolean, preserveLastModified: Boolean, log: Logger): Either[String, Set[Path]] =
- {
- val targetSet = new scala.collection.mutable.HashSet[Path]
- copyImpl(sources, destinationDirectory, log)
- {
- source =>
- {
- val from = source.asFile
- val toPath = Path.fromString(destinationDirectory, source.relativePath)
- targetSet += toPath
- val to = toPath.asFile
- if(!to.exists || overwrite || from.lastModified > to.lastModified)
- {
- val result =
- if(from.isDirectory)
- createDirectory(to, log)
- else
- {
- log.debug("Copying " + source + " to " + toPath)
- copyFile(from, to, log)
- }
- if (result.isEmpty && preserveLastModified)
- touchExisting(to, from.lastModified, log)
- else
- result
- }
- else
- None
- }
- }.toLeft(readOnly(targetSet))
- }
-
- /** Copies the files declared in sources to the targetDirectory
- * directory. The source directory hierarchy is flattened so that all copies are immediate
- * children of targetDirectory. Directories are not recursively entered.*/
- def copyFilesFlat(sources: Iterable[File], targetDirectory: Path, log: Logger) =
- {
- require(targetDirectory.asFile.isDirectory, "Target '" + targetDirectory + "' is not a directory.")
- val byName = new scala.collection.mutable.HashMap[String, File]
- for(source <- sources) byName.put(source.getName, source)
- val uniquelyNamedSources = byName.values
- val targetSet = new scala.collection.mutable.HashSet[Path]
- def copy(source: File): Option[String] =
- {
- if(source.isDirectory)
- copyAll(source.listFiles.toList)
- else if(source.exists)
- {
- val targetPath = targetDirectory / source.getName
- targetSet += targetPath
- if(!targetPath.exists || source.lastModified > targetPath.lastModified)
- {
- log.debug("Copying " + source + " to " + targetPath)
- copyFile(source, targetPath.asFile, log)
- }
- else
- None
- }
- else
- None
- }
- def copyAll(sources: List[File]): Option[String] =
- sources match
- {
- case head :: tail =>
- copy(head) match
- {
- case None => copyAll(tail)
- case x => x
- }
- case Nil => None
- }
-
- Control.trap("Error copying files: ", log) { copyAll(uniquelyNamedSources.toList).toLeft(readOnly(targetSet)) }
- }
- /** Copies sourceFile to targetFile. If targetFile
- * exists, it is overwritten. Note that unlike higher level copies in FileUtilities, this
- * method always performs the copy, even if sourceFile is older than targetFile.*/
- def copyFile(sourceFile: Path, targetFile: Path, log: Logger): Option[String] =
- copyFile(sourceFile.asFile, targetFile.asFile, log)
- /** Copies sourceFile to targetFile. If targetFile
- * exists, it is overwritten. Note that unlike higher level copies in FileUtilities, this
- * method always performs the copy, even if sourceFile is older than targetFile.*/
- def copyFile(sourceFile: File, targetFile: File, log: Logger): Option[String] =
- {
- require(sourceFile.exists, "Source file '" + sourceFile.getAbsolutePath + "' does not exist.")
- require(!sourceFile.isDirectory, "Source file '" + sourceFile.getAbsolutePath + "' is a directory.")
- readChannel(sourceFile, log)(
- in => writeChannel(targetFile, log) {
- out => {
- val copied = out.transferFrom(in, 0, in.size)
- if(copied == in.size)
- None
- else
- Some("Could not copy '" + sourceFile + "' to '" + targetFile + "' (" + copied + "/" + in.size + " bytes copied)")
- }
- }
- )
- }
-
- /** Synchronizes the contents of the sourceDirectory directory to the
- * targetDirectory directory.*/
- def sync(sourceDirectory: Path, targetDirectory: Path, log: Logger): Option[String] =
- syncPaths((sourceDirectory ###) ** AllPassFilter, targetDirectory, log)
- def syncPaths(sources: PathFinder, targetDirectory: Path, log: Logger): Option[String] =
- {
- copy(sources.get, targetDirectory, log).right.flatMap
- { copiedTo => prune(targetDirectory, copiedTo, log).toLeft(()) }.left.toOption
- }
- def prune(directory: Path, keepOnly: Iterable[Path], log: Logger): Option[String] =
- {
- val existing = ((directory ###) ** AllPassFilter).get
- val toRemove = scala.collection.mutable.HashSet(existing.toSeq: _*)
- toRemove --= keepOnly
- if(log.atLevel(Level.Debug))
- toRemove.foreach(r => log.debug("Pruning " + r))
- clean(toRemove, true, log)
- }
-
- /** Copies the contents of the source directory to the target directory .*/
- def copyDirectory(source: Path, target: Path, log: Logger): Option[String] =
- copyDirectory(source.asFile, target.asFile, log)
- /** Copies the contents of the source directory to the target directory .*/
- def copyDirectory(source: File, target: File, log: Logger): Option[String] =
- {
- require(source.isDirectory, "Source '" + source.getAbsolutePath + "' is not a directory.")
- require(!target.exists, "Target '" + target.getAbsolutePath + "' already exists.")
- def copyDirectory(sourceDir: File, targetDir: File): Option[String] =
- createDirectory(targetDir, log) orElse copyContents(sourceDir, targetDir)
- def copyContents(sourceDir: File, targetDir: File): Option[String] =
- sourceDir.listFiles.foldLeft(None: Option[String])
- {
- (result, file) =>
- result orElse
- {
- val targetFile = new File(targetDir, file.getName)
- if(file.isDirectory)
- copyDirectory(file, targetFile)
- else
- copyFile(file, targetFile, log)
- }
- }
- copyDirectory(source, target)
- }
-
-
- /** Deletes the given file recursively.*/
- def clean(file: Path, log: Logger): Option[String] = clean(file :: Nil, log)
- /** Deletes the given files recursively.*/
- def clean(files: Iterable[Path], log: Logger): Option[String] = clean(files, false, log)
- /** Deletes the given files recursively. quiet determines the logging level.
- * If it is true, each file in files is logged at the info level.
- * If it is false, the debug level is used.*/
- def clean(files: Iterable[Path], quiet: Boolean, log: Logger): Option[String] =
- deleteFiles(Path.getFiles(files), quiet, log)
-
- private def deleteFiles(files: Iterable[File], quiet: Boolean, log: Logger): Option[String] =
- ((None: Option[String]) /: files)( (result, file) => result orElse delete(file, quiet, log))
- private def delete(file: File, quiet: Boolean, log: Logger): Option[String] =
- {
- def logMessage(message: => String)
- {
- log.log(if(quiet) Level.Debug else Level.Info, message)
- }
- Control.trapUnit("Error deleting file " + file + ": ", log)
- {
- if(file.isDirectory)
- {
- logMessage("Deleting directory " + file)
- deleteFiles(wrapNull(file.listFiles), true, log)
- file.delete
- }
- else if(file.exists)
- {
- logMessage("Deleting file " + file)
- file.delete
- }
- None
- }
- }
-
- /** Appends the given String content to the provided file using the default encoding.
- * A new file is created if it does not exist.*/
- def append(file: File, content: String, log: Logger): Option[String] = append(file, content, Charset.defaultCharset, log)
- /** Appends the given String content to the provided file using the given encoding.
- * A new file is created if it does not exist.*/
- def append(file: File, content: String, charset: Charset, log: Logger): Option[String] =
- write(file, content, charset, true, log)
-
- /** Writes the given String content to the provided file using the default encoding.
- * If the file exists, it is overwritten.*/
- def write(file: File, content: String, log: Logger): Option[String] = write(file, content, Charset.defaultCharset, log)
- /** Writes the given String content to the provided file using the given encoding.
- * If the file already exists, it is overwritten.*/
- def write(file: File, content: String, charset: Charset, log: Logger): Option[String] =
- write(file, content, charset, false, log)
- private def write(file: File, content: String, charset: Charset, append: Boolean, log: Logger): Option[String] =
- {
- if(charset.newEncoder.canEncode(content))
- write(file, charset, append, log) { w => w.write(content); None }
- else
- Some("String cannot be encoded by charset " + charset.name)
- }
-
- /** Opens a Writer on the given file using the default encoding,
- * passes it to the provided function, and closes the Writer.*/
- def write(file: File, log: Logger)(f: Writer => Option[String]): Option[String] =
- write(file, Charset.defaultCharset, log)(f)
- /** Opens a Writer on the given file using the given encoding,
- * passes it to the provided function, and closes the Writer.*/
- def write(file: File, charset: Charset, log: Logger)(f: Writer => Option[String]): Option[String] =
- write(file, charset, false, log)(f)
- private def write(file: File, charset: Charset, append: Boolean, log: Logger)(f: Writer => Option[String]): Option[String] =
- fileWriter(charset, append).ioOption(file, Writing, log)(f)
-
- /** Opens a Reader on the given file using the default encoding,
- * passes it to the provided function, and closes the Reader.*/
- def read(file: File, log: Logger)(f: Reader => Option[String]): Option[String] =
- read(file, Charset.defaultCharset, log)(f)
- /** Opens a Reader on the given file using the default encoding,
- * passes it to the provided function, and closes the Reader.*/
- def read(file: File, charset: Charset, log: Logger)(f: Reader => Option[String]): Option[String] =
- fileReader(charset).ioOption(file, Reading, log)(f)
- /** Opens a Reader on the given file using the default encoding,
- * passes it to the provided function, and closes the Reader.*/
- def readValue[R](file: File, log: Logger)(f: Reader => Either[String, R]): Either[String, R] =
- readValue(file, Charset.defaultCharset, log)(f)
- /** Opens a Reader on the given file using the given encoding,
- * passes it to the provided function, and closes the Reader.*/
- def readValue[R](file: File, charset: Charset, log: Logger)(f: Reader => Either[String, R]): Either[String, R] =
- fileReader(charset).io(file, Reading, log)(f)
-
- /** Reads the contents of the given file into a String using the default encoding.
- * The resulting String is wrapped in Right.*/
- def readString(file: File, log: Logger): Either[String, String] = readString(file, Charset.defaultCharset, log)
- /** Reads the contents of the given file into a String using the given encoding.
- * The resulting String is wrapped in Right.*/
- def readString(file: File, charset: Charset, log: Logger): Either[String, String] = readValue(file, charset, log)(readString)
-
- def readString(in: InputStream, log: Logger): Either[String, String] = readString(in, Charset.defaultCharset, log)
- def readString(in: InputStream, charset: Charset, log: Logger): Either[String, String] =
- streamReader.io((in, charset), Reading, log)(readString)
- def readString(in: Reader, log: Logger): Either[String, String] =
- Control.trapAndFinally("Error reading bytes from reader: ", log)
- { readString(in) }
- { in.close() }
- private def readString(in: Reader): Either[String, String] =
- {
- val builder = new StringBuilder
- val buffer = new Array[Char](BufferSize)
- def readNext()
- {
- val read = in.read(buffer, 0, buffer.length)
- if(read >= 0)
- {
- builder.append(buffer, 0, read)
- readNext()
- }
- else
- None
- }
- readNext()
- Right(builder.toString)
- }
- /** Appends the given bytes to the given file. */
- def append(file: File, bytes: Array[Byte], log: Logger): Option[String] =
- writeBytes(file, bytes, true, log)
- /** Writes the given bytes to the given file. If the file already exists, it is overwritten.*/
- def write(file: File, bytes: Array[Byte], log: Logger): Option[String] =
- writeBytes(file, bytes, false, log)
- private def writeBytes(file: File, bytes: Array[Byte], append: Boolean, log: Logger): Option[String] =
- writeStream(file, append, log) { out => out.write(bytes); None }
-
- /** Reads the entire file into a byte array. */
- def readBytes(file: File, log: Logger): Either[String, Array[Byte]] = readStreamValue(file, log)(readBytes)
- def readBytes(in: InputStream, log: Logger): Either[String, Array[Byte]] =
- Control.trapAndFinally("Error reading bytes from input stream: ", log)
- { readBytes(in) }
- { in.close() }
- private def readBytes(in: InputStream): Either[String, Array[Byte]] =
- {
- val out = new ByteArrayOutputStream
- val buffer = new Array[Byte](BufferSize)
- def readNext()
- {
- val read = in.read(buffer)
- if(read >= 0)
- {
- out.write(buffer, 0, read)
- readNext()
- }
- }
- readNext()
- Right(out.toByteArray)
- }
-
- /** Opens an OutputStream on the given file with append=true and passes the stream
- * to the provided function. The stream is closed before this function returns.*/
- def appendStream(file: File, log: Logger)(f: OutputStream => Option[String]): Option[String] =
- fileOutputStream(true).ioOption(file, Appending, log)(f)
- /** Opens an OutputStream on the given file and passes the stream
- * to the provided function. The stream is closed before this function returns.*/
- def writeStream(file: File, log: Logger)(f: OutputStream => Option[String]): Option[String] =
- fileOutputStream(false).ioOption(file, Writing, log)(f)
- private def writeStream(file: File, append: Boolean, log: Logger)(f: OutputStream => Option[String]): Option[String] =
- if(append) appendStream(file, log)(f) else writeStream(file, log)(f)
- /** Opens an InputStream on the given file and passes the stream
- * to the provided function. The stream is closed before this function returns.*/
- def readStream(file: File, log: Logger)(f: InputStream => Option[String]): Option[String] =
- fileInputStream.ioOption(file, Reading, log)(f)
- /** Opens an InputStream on the given file and passes the stream
- * to the provided function. The stream is closed before this function returns.*/
- def readStreamValue[R](file: File, log: Logger)(f: InputStream => Either[String, R]): Either[String, R] =
- fileInputStream.io(file, Reading, log)(f)
- /** Opens an InputStream on the given URL and passes the stream
- * to the provided function. The stream is closed before this function returns.*/
- def readStream(url: URL, log: Logger)(f: InputStream => Option[String]): Option[String] =
- urlInputStream.ioOption(url, Reading, log)(f)
- /** Opens an InputStream on the given URL and passes the stream
- * to the provided function. The stream is closed before this function returns.*/
- def readStreamValue[R](url: URL, log: Logger)(f: InputStream => Either[String, R]): Either[String, R] =
- urlInputStream.io(url, Reading, log)(f)
-
- /** Opens a FileChannel on the given file for writing and passes the channel
- * to the given function. The channel is closed before this function returns.*/
- def writeChannel(file: File, log: Logger)(f: FileChannel => Option[String]): Option[String] =
- fileOutputChannel.ioOption(file, Writing, log)(f)
- /** Opens a FileChannel on the given file for reading and passes the channel
- * to the given function. The channel is closed before this function returns.*/
- def readChannel(file: File, log: Logger)(f: FileChannel => Option[String]): Option[String] =
- fileInputChannel.ioOption(file, Reading, log)(f)
- /** Opens a FileChannel on the given file for reading and passes the channel
- * to the given function. The channel is closed before this function returns.*/
- def readChannelValue[R](file: File, log: Logger)(f: FileChannel => Either[String, R]): Either[String, R] =
- fileInputChannel.io(file, Reading, log)(f)
-
- private[sbt] (a: Array[File]): Array[File] =
- if(a == null)
- new Array[File](0)
- else
- a
-
- /** Writes the given string to the writer followed by a newline.*/
- private[sbt] def writeLine(writer: Writer, line: String)
- {
- writer.write(line)
- writer.write(Newline)
- }
-
- def toFile(url: URL) =
- try { new File(url.toURI) }
- catch { case _: URISyntaxException => new File(url.getPath) }
-
- /** The directory in which temporary files are placed.*/
- val temporaryDirectory = new File(System.getProperty("java.io.tmpdir"))
- def classLocation(cl: Class[_]): URL =
- {
- val codeSource = cl.getProtectionDomain.getCodeSource
- if(codeSource == null) error("No class location for " + cl)
- else codeSource.getLocation
- }
- def classLocationFile(cl: Class[_]): File = toFile(classLocation(cl))
- def classLocation[T](implicit mf: scala.reflect.Manifest[T]): URL = classLocation(mf.erasure)
- def classLocationFile[T](implicit mf: scala.reflect.Manifest[T]): File = classLocationFile(mf.erasure)
-
- lazy val scalaLibraryJar: File = classLocationFile[scala.ScalaObject]
- lazy val scalaCompilerJar: File = classLocationFile[scala.tools.nsc.Settings]
- def scalaJars: Iterable[File] = List(scalaLibraryJar, scalaCompilerJar)
-
- /** The producer of randomness for unique name generation.*/
- private val random = new java.util.Random
-
- private val Reading = "reading"
- private val Writing = "writing"
- private val Appending = "appending"
-}
-
-private abstract class OpenResource[Source, T] extends NotNull
-{
- import OpenResource.{unwrapEither, wrapEither}
- protected def open(src: Source, log: Logger): Either[String, T]
- def ioOption(src: Source, op: String, log: Logger)(f: T => Option[String]) =
- unwrapEither( io(src, op, log)(wrapEither(f)) )
- def io[R](src: Source, op: String, log: Logger)(f: T => Either[String,R]): Either[String, R] =
- open(src, log).right flatMap
- {
- resource => Control.trapAndFinally("Error " + op + " "+ src + ": ", log)
- { f(resource) }
- { close(resource) }
- }
- protected def close(out: T): Unit
-}
-private trait CloseableOpenResource[Source, T <: Closeable] extends OpenResource[Source, T]
-{
- protected def close(out: T): Unit = out.close()
-}
-import scala.reflect.{Manifest => SManifest}
-private abstract class WrapOpenResource[Source, T <: Closeable](implicit srcMf: SManifest[Source], targetMf: SManifest[T]) extends CloseableOpenResource[Source, T]
-{
- private def label[S](m: SManifest[S]) = m.erasure.getSimpleName
- protected def open(source: Source): T
- protected final def open(source: Source, log: Logger): Either[String, T] =
- Control.trap("Error wrapping " + label(srcMf) + " in " + label(targetMf) + ": ", log) { Right(open(source)) }
-}
-private abstract class OpenFile[T] extends OpenResource[File, T]
-{
- protected def open(file: File): T
- protected final def open(file: File, log: Logger): Either[String, T] =
- {
- val parent = file.getParentFile
- if(parent != null)
- FileUtilities.createDirectory(parent, log)
- Control.trap("Error opening " + file + ": ", log) { Right(open(file)) }
- }
-}
-private abstract class CloseableOpenFile[T <: Closeable] extends OpenFile[T] with CloseableOpenResource[File, T]
-private object OpenResource
-{
- private def wrapEither[R](f: R => Option[String]): (R => Either[String, Unit]) = (r: R) => f(r).toLeft(())
- private def unwrapEither(e: Either[String, Unit]): Option[String] = e.left.toOption
-
- def fileOutputStream(append: Boolean) =
- new CloseableOpenFile[FileOutputStream] { protected def open(file: File) = new FileOutputStream(file, append) }
- def fileInputStream = new CloseableOpenFile[FileInputStream]
- { protected def open(file: File) = new FileInputStream(file) }
- def urlInputStream = new CloseableOpenResource[URL, InputStream]
- { protected def open(url: URL, log: Logger) = Control.trap("Error opening " + url + ": ", log) { Right(url.openStream) } }
- def fileOutputChannel = new CloseableOpenFile[FileChannel]
- { protected def open(f: File) = (new FileOutputStream(f)).getChannel }
- def fileInputChannel = new CloseableOpenFile[FileChannel]
- { protected def open(f: File) = (new FileInputStream(f)).getChannel }
- def fileWriter(charset: Charset, append: Boolean) = new CloseableOpenFile[Writer]
- { protected def open(f: File) = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f, append), charset)) }
- def fileReader(charset: Charset) = new CloseableOpenFile[Reader]
- { protected def open(f: File) = new BufferedReader(new InputStreamReader(new FileInputStream(f), charset)) }
- def jarFile(verify: Boolean) = new OpenFile[JarFile]
- { protected def open(f: File) = new JarFile(f, verify)
- override protected def close(j: JarFile) = j.close() }
- def zipFile = new OpenFile[ZipFile]
- { protected def open(f: File) = new ZipFile(f)
- override protected def close(z: ZipFile) = z.close() }
- def streamReader = new WrapOpenResource[(InputStream, Charset), Reader]
- { protected def open(streamCharset: (InputStream, Charset)) = new InputStreamReader(streamCharset._1, streamCharset._2) }
- def gzipInputStream = new WrapOpenResource[InputStream, GZIPInputStream]
- { protected def open(in: InputStream) = new GZIPInputStream(in) }
- def zipInputStream = new WrapOpenResource[InputStream, ZipInputStream]
- { protected def open(in: InputStream) = new ZipInputStream(in) }
- def gzipOutputStream = new WrapOpenResource[OutputStream, GZIPOutputStream]
- { protected def open(out: OutputStream) = new GZIPOutputStream(out)
- override protected def close(out: GZIPOutputStream) = out.finish() }
- def jarOutputStream = new WrapOpenResource[OutputStream, JarOutputStream]
- { protected def open(out: OutputStream) = new JarOutputStream(out) }
- def jarInputStream = new WrapOpenResource[InputStream, JarInputStream]
- { protected def open(in: InputStream) = new JarInputStream(in) }
- def zipEntry(zip: ZipFile) = new CloseableOpenResource[ZipEntry, InputStream] {
- protected def open(entry: ZipEntry, log: Logger) =
- Control.trap("Error opening " + entry.getName + " in " + zip + ": ", log) { Right(zip.getInputStream(entry)) }
- }
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/IntegrationTesting.scala b/sbt_pending/src/main/scala/sbt/IntegrationTesting.scala
deleted file mode 100644
index d09dde5b4..000000000
--- a/sbt_pending/src/main/scala/sbt/IntegrationTesting.scala
+++ /dev/null
@@ -1,94 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Steven Blundy, Mark Harrah, Josh Cough
- */
-package sbt
-
-import ScalaProject.{optionsAsString, javaOptionsAsString}
-
-trait IntegrationTesting extends NotNull
-{
- /** Override to provide pre-test setup. */
- protected def pretests: Option[String] = None
- /** Override to provide post-test cleanup. */
- protected def posttests: Option[String] = None
-}
-trait ScalaIntegrationTesting extends IntegrationTesting
-{ self: ScalaProject =>
-
- protected def integrationTestTask(frameworks: Seq[TestFramework], classpath: PathFinder, analysis: CompileAnalysis, options: => Seq[TestOption]) =
- testTask(frameworks, classpath, analysis, options)
-}
-
-trait BasicScalaIntegrationTesting extends BasicIntegrationTesting with MavenStyleIntegrationTestPaths
-{ self: BasicScalaProject => }
-/** A fully featured integration testing that may be mixed in with any subclass of BasicScalaProject.
- * Pre-suite setup and post-suite cleanup are provide by overriding pretests and posttests respectively.*/
-trait BasicIntegrationTesting extends ScalaIntegrationTesting with IntegrationTestPaths with BasicDependencyProject
-{
- self: BasicScalaProject =>
-
- import BasicScalaIntegrationTesting._
-
- lazy val integrationTestCompile = integrationTestCompileAction
- lazy val integrationTest = integrationTestAction
-
- val integrationTestCompileConditional = new CompileConditional(integrationTestCompileConfiguration, buildCompiler)
-
- protected def integrationTestAction = integrationTestTask(integrationTestFrameworks, integrationTestClasspath, integrationTestCompileConditional.analysis, integrationTestOptions) dependsOn integrationTestCompile describedAs IntegrationTestCompileDescription
- protected def integrationTestCompileAction = integrationTestCompileTask() dependsOn compile describedAs IntegrationTestDescription
-
- protected def integrationTestCompileTask() = task{ integrationTestCompileConditional.run }
-
- def integrationTestOptions: Seq[TestOption] =
- TestSetup(() => pretests) ::
- TestCleanup(() => posttests) ::
- testOptions.toList
- def integrationTestCompileOptions = testCompileOptions
- def javaIntegrationTestCompileOptions: Seq[JavaCompileOption] = testJavaCompileOptions
-
- def integrationTestConfiguration = if(useIntegrationTestConfiguration) Configurations.IntegrationTest else Configurations.Test
- def integrationTestClasspath = fullClasspath(integrationTestConfiguration) +++ optionalClasspath
-
- def integrationTestLabel = "integration-test"
- def integrationTestCompileConfiguration = new IntegrationTestCompileConfig
-
- protected def integrationTestDependencies = new LibraryDependencies(this, integrationTestCompileConditional)
-
- def integrationTestFrameworks = testFrameworks
- override def useIntegrationTestConfiguration = false
- abstract override def extraDefaultConfigurations =
- {
- val superConfigurations = super.extraDefaultConfigurations
- if(useIntegrationTestConfiguration)
- integrationTestConfiguration :: superConfigurations
- else
- superConfigurations
- }
- abstract override def fullUnmanagedClasspath(config: Configuration) =
- {
- val superClasspath = super.fullUnmanagedClasspath(config)
- if(config == integrationTestConfiguration)
- integrationTestCompilePath +++ integrationTestResourcesPath +++ superClasspath
- else
- superClasspath
- }
-
- class IntegrationTestCompileConfig extends BaseCompileConfig
- {
- def label = integrationTestLabel
- def sourceRoots = integrationTestScalaSourceRoots
- def sources = integrationTestSources
- def outputDirectory = integrationTestCompilePath
- def classpath = integrationTestClasspath
- def analysisPath = integrationTestAnalysisPath
- def baseCompileOptions = integrationTestCompileOptions
- def javaOptions = javaOptionsAsString(javaCompileOptions)
- def fingerprints = getFingerprints(integrationTestFrameworks)
- }
-}
-
-object BasicScalaIntegrationTesting
-{
- val IntegrationTestCompileDescription = "Compiles integration test sources."
- val IntegrationTestDescription = "Runs all integration tests detected during compilation."
-}
diff --git a/sbt_pending/src/main/scala/sbt/Main.scala b/sbt_pending/src/main/scala/sbt/Main.scala
deleted file mode 100755
index 61a7e40d0..000000000
--- a/sbt_pending/src/main/scala/sbt/Main.scala
+++ /dev/null
@@ -1,774 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009, 2010 Steven Blundy, Mark Harrah, David MacIver, Mikko Peltonen
- */
-package sbt
-
-import java.io.File
-import scala.collection.immutable.TreeSet
-import complete.HistoryCommands
-import HistoryCommands.{Start => HistoryPrefix}
-
-/** This class is the entry point for sbt. If it is given any arguments, it interprets them
-* as actions, executes the corresponding actions, and exits. If there were no arguments provided,
-* sbt enters interactive mode.*/
-object Main
-{
- val NormalExitCode = 0
- val SetupErrorExitCode = 1
- val SetupDeclinedExitCode = 2
- val LoadErrorExitCode = 3
- val UsageErrorExitCode = 4
- val BuildErrorExitCode = 5
- val ProgramErrorExitCode = 6
- val MaxInt = java.lang.Integer.MAX_VALUE
-}
-
-import Main._
-
-class xMain extends xsbti.AppMain
-{
- final def run(configuration: xsbti.AppConfiguration): xsbti.MainResult =
- {
- def run0(remainingArguments: List[String], buildScalaVersion: Option[String]): xsbti.MainResult =
- {
- // done this way because in Scala 2.7.7, tail recursion in catch blocks is not optimized
- val result = try { Right(run(configuration, remainingArguments, buildScalaVersion)) } catch { case re: ReloadException => Left(re) }
- result match
- {
- case Left(re) => run0(re.remainingArguments, re.buildScalaVersion)
- case Right(r) => r
- }
- }
- run0(configuration.arguments.map(_.trim).toList, None)
- }
- final def run(configuration: xsbti.AppConfiguration, remainingArguments: List[String], buildScalaVersion: Option[String]): xsbti.MainResult =
- {
- val startTime = System.currentTimeMillis
- Project.loadProject(configuration.provider, buildScalaVersion) match
- {
- case err: LoadSetupError =>
- println("\n" + err.message)
- ExitHooks.runExitHooks(Project.bootLogger)
- Exit(SetupErrorExitCode)
- case LoadSetupDeclined =>
- ExitHooks.runExitHooks(Project.bootLogger)
- Exit(SetupDeclinedExitCode)
- case err: LoadError =>
- {
- val log = Project.bootLogger
- println(err.message)
- ExitHooks.runExitHooks(log)
- // Because this is an error that can probably be corrected, prompt user to try again.
- val line =
- try { SimpleReader.readLine("\n Hit enter to retry or 'exit' to quit: ") }
- catch
- {
- case e =>
- log.trace(e)
- log.error(e.toString)
- None
- }
- line match
- {
- case Some(l) => if(!isTerminateAction(l)) run(configuration, remainingArguments, buildScalaVersion) else Exit(NormalExitCode)
- case None => Exit(LoadErrorExitCode)
- }
- }
- case success: LoadSuccess =>
- {
- import success.project
- try
- {
- // in interactive mode, fill all undefined properties
- if(configuration.arguments.length > 0 || fillUndefinedProjectProperties(project.projectClosure.toList.reverse))
- startProject(project, configuration, remainingArguments, startTime)
- else
- Exit(NormalExitCode)
- }
- finally { ExitHooks.runExitHooks(project.log) }
- }
- }
- }
- /** If no arguments are provided, drop to interactive prompt.
- * If the user wants to run commands before dropping to the interactive prompt,
- * make dropping to the interactive prompt the action to perform on failure */
- private def initialize(args: List[String]): List[String] =
- args.lastOption match
- {
- case None => InteractiveCommand :: Nil
- case Some(InteractiveCommand) => (FailureHandlerPrefix + InteractiveCommand) :: args
- case Some(ExitCommand | QuitCommand) => args
- case _ => args ::: ExitCommand :: Nil
- }
- private def startProject(project: Project, configuration: xsbti.AppConfiguration, remainingArguments: List[String], startTime: Long): xsbti.MainResult =
- {
- project.log.info("Building project " + project.name + " " + project.version.toString + " against Scala " + project.buildScalaVersion)
- project.log.info(" using " + project.getClass.getName + " with sbt " + ComponentManager.version + " and Scala " + project.defScalaVersion.value)
- processArguments(project, initialize(remainingArguments), configuration, startTime) match
- {
- case e: xsbti.Exit =>
- printTime(project, startTime, "session")
- if(e.code == NormalExitCode)
- project.log.success("Build completed successfully.")
- else
- project.log.error("Error during build.")
- e
- case r => r
- }
- }
- /** This is the top-level command processing method. */
- private def processArguments(baseProject: Project, arguments: List[String], configuration: xsbti.AppConfiguration, startTime: Long): xsbti.MainResult =
- {
- type OnFailure = Option[String]
- def ExitOnFailure = None
- lazy val interactiveContinue = Some( InteractiveCommand )
- def remoteContinue(port: Int) = Some( FileCommandsPrefix + "-" + port )
- lazy val PHandler = new processor.Handler(baseProject)
-
- // replace in 2.8
- trait Trampoline
- class Done(val r: xsbti.MainResult) extends Trampoline
- class Continue(project: Project, arguments: List[String], failAction: OnFailure) extends Trampoline {
- def apply() = process(project, arguments, failAction)
- }
- def continue(project: Project, arguments: List[String], failAction: OnFailure) = new Continue(project, arguments, failAction)
- def result(r: xsbti.MainResult) = new Done(r)
- def run(t: Trampoline): xsbti.MainResult = t match { case d: Done => d.r; case c: Continue => run(c()) }
-
- def process(project: Project, arguments: List[String], failAction: OnFailure): Trampoline =
- {
- project.log.debug("commands " + failAction.map("(on failure: " + _ + "): ").mkString + arguments.mkString(", "))
- def rememberCurrent(newArgs: List[String]) = rememberProject(rememberFail(newArgs))
- def rememberProject(newArgs: List[String]) =
- if(baseProject.name != project.name && !internal(project)) (ProjectAction + " " + project.name) :: newArgs else newArgs
- def rememberFail(newArgs: List[String]) = failAction.map(f => (FailureHandlerPrefix + f)).toList ::: newArgs
-
- def tryOrFail(action: => Trampoline) = try { action } catch { case e: Exception => logCommandError(project.log, e); failed(BuildErrorExitCode) }
- def reload(args: List[String]) =
- {
- val newID = new ApplicationID(configuration.provider.id, baseProject.sbtVersion.value)
- result( new Reboot(project.defScalaVersion.value, rememberCurrent(args), newID, configuration.baseDirectory) )
- }
- def failed(code: Int) =
- failAction match
- {
- case Some(c) => continue(project, c :: Nil, ExitOnFailure)
- case None => result( Exit(code) )
- }
-
- arguments match
- {
- case "" :: tail => continue(project, tail, failAction)
- case ResetCommand :: tail => JLine.resetTerminal(); continue(project, tail, failAction)
- case x :: tail if x.startsWith(";") => continue(project, x.split("""\s*;\s*""").toList ::: tail, failAction)
- case (ExitCommand | QuitCommand) :: _ => result( Exit(NormalExitCode) )
- case RebootCommand :: tail => reload( tail )
- case InteractiveCommand :: _ => continue(project, prompt(baseProject, project) :: arguments, interactiveContinue)
- case BuilderCommand :: tail =>
- Project.getProjectBuilder(project.info, project.log) match
- {
- case Some(b) => project.log.info("Set current project to builder of " + project.name); continue(b, tail, failAction)
- case None => project.log.error("No project/build directory for " + project.name + ".\n Not switching to builder project."); failed(BuildErrorExitCode)
- }
- case SpecificBuild(version, action) :: tail =>
- if(Some(version) != baseProject.info.buildScalaVersion)
- {
- if(checkVersion(baseProject, version))
- throw new ReloadException(rememberCurrent(action :: tail), Some(version))
- else
- failed(UsageErrorExitCode)
- }
- else
- continue(project, action :: tail, failAction)
-
- case CrossBuild(action) :: tail =>
- if(checkAction(project, action))
- {
- CrossBuild(project, action) match
- {
- case Some(actions) => continue(project, actions ::: tail, failAction)
- case None => failed(UsageErrorExitCode)
- }
- }
- else
- failed(UsageErrorExitCode)
-
- case SetProject(name) :: tail =>
- SetProject(baseProject, name, project) match
- {
- case Some(newProject) => continue(newProject, tail, failAction)
- case None => failed(BuildErrorExitCode)
- }
-
- case action :: tail if action.startsWith(HistoryPrefix) =>
- HistoryCommands(action.substring(HistoryPrefix.length).trim, baseProject.historyPath, JLine.MaxHistorySize, project.log) match
- {
- case Some(commands) =>
- commands.foreach(println) //better to print it than to log it
- continue(project, commands ::: tail, failAction)
- case None => failed(UsageErrorExitCode)
- }
-
- case action :: tail if action.startsWith(FileCommandsPrefix) =>
- getSource(action.substring(FileCommandsPrefix.length).trim, baseProject.info.projectDirectory) match
- {
- case Left(portAndSuccess) =>
- val port = Math.abs(portAndSuccess)
- val previousSuccess = portAndSuccess >= 0
- readMessage(port, previousSuccess) match
- {
- case Some(message) => continue(project, message :: (FileCommandsPrefix + port) :: Nil, remoteContinue(port))
- case None =>
- project.log.error("Connection closed.")
- failed(BuildErrorExitCode)
- }
-
- case Right(file) =>
- readLines(project, file) match
- {
- case Some(lines) => continue(project, lines ::: tail , failAction)
- case None => failed(UsageErrorExitCode)
- }
- }
-
- case action :: tail if action.startsWith(FailureHandlerPrefix) =>
- val errorAction = action.substring(FailureHandlerPrefix.length).trim
- continue(project, tail, if(errorAction.isEmpty) None else Some(errorAction) )
-
- case action :: tail if action.startsWith(ProcessorPrefix) =>
- val processorCommand = action.substring(ProcessorPrefix.length).trim
- val runner = processor.CommandRunner(PHandler.manager, PHandler.defParser, ProcessorPrefix, project.log)
- tryOrFail {
- runner(processorCommand)
- continue(project, tail, failAction)
- }
-
- case PHandler(parsed) :: tail =>
- tryOrFail {
- parsed.processor(parsed.label, project, failAction, parsed.arguments) match
- {
- case s: processor.Success => continue(s.project, s.insertArguments ::: tail, s.onFailure)
- case e: processor.Exit => result( Exit(e.code) )
- case r: processor.Reload => reload( r.insertArguments ::: tail )
- }
- }
-
- case action :: tail =>
- val success = processAction(baseProject, project, action, failAction == interactiveContinue)
- if(success) continue(project, tail, failAction)
- else failed(BuildErrorExitCode)
-
- case Nil =>
- project.log.error("Invalid internal sbt state: no arguments")
- result( Exit(ProgramErrorExitCode) )
- }
- }
- run(process(baseProject, arguments, ExitOnFailure))
- }
- private def internal(p: Project) = p.isInstanceOf[InternalProject]
- private def isInteractive(failureActions: Option[List[String]]) = failureActions == Some(InteractiveCommand :: Nil)
- private def getSource(action: String, baseDirectory: File) =
- {
- try { Left(action.toInt) }
- catch { case _: NumberFormatException => Right(new File(baseDirectory, action)) }
- }
- private def readMessage(port: Int, previousSuccess: Boolean): Option[String] =
- {
- // split into two connections because this first connection ends the previous communication
- xsbt.IPC.client(port) { _.send(previousSuccess.toString) }
- // and this second connection starts the next communication
- xsbt.IPC.client(port) { ipc =>
- val message = ipc.receive
- if(message eq null) None else Some(message)
- }
- }
- object SetProject
- {
- def unapply(s: String) =
- if(s.startsWith(ProjectAction + " "))
- Some(s.substring(ProjectAction.length + 1))
- else
- None
- def apply(baseProject: Project, projectName: String, currentProject: Project) =
- {
- val found = baseProject.projectClosure.find(_.name == projectName)
- found match
- {
- case Some(newProject) => printProject("Set current project to ", newProject)
- case None => currentProject.log.error("Invalid project name '" + projectName + "' (type 'projects' to list available projects).")
- }
- found
- }
- }
- object SpecificBuild
- {
- import java.util.regex.Pattern.{compile,quote}
- val pattern = compile(quote(SpecificBuildPrefix) + """\s*(\S+)\s*(.*)""")
- def unapply(s: String) =
- {
- val m = pattern.matcher(s)
- if(m.matches)
- Some(m.group(1).trim, m.group(2).trim)
- else
- None
- }
- }
- def checkVersion(p: Project, version: String) =
- {
- try { p.getScalaInstance(version); true }
- catch { case e: xsbti.RetrieveException => p.log.error(e.getMessage); false }
- }
- object CrossBuild
- {
- def unapply(s: String) = if(s.startsWith(CrossBuildPrefix) && !s.startsWith(SpecificBuildPrefix)) Some(s.substring(1)) else None
- def apply(project: Project, action: String): Option[List[String]] =
- {
- val againstScalaVersions = project.crossScalaVersions
- if(againstScalaVersions.isEmpty)
- {
- Console.println("Project does not declare any Scala versions to cross-build against, building against current version...")
- Some(action :: Nil)
- }
- else
- {
- if( !againstScalaVersions.forall(v => checkVersion(project, v)) )
- None
- else
- {
- val actions =
- againstScalaVersions.toList.map(SpecificBuildPrefix + _ + " " + action) ::: // build against all versions
- (SpecificBuildPrefix + project.buildScalaVersion) :: // reset to the version before the cross-build
- Nil
- Some(actions)
- }
- }
- }
- }
- private def readLines(project: Project, file: File): Option[List[String]] =
- {
- try { Some(xsbt.FileUtilities.readLines(file)) }
- catch { case e: Exception =>
- project.log.trace(e)
- project.log.error("Error reading commands from file " + file.getAbsolutePath + ": " + e.toString)
- None
- }
- }
- private def prompt(baseProject: Project, project: Project): String =
- {
- // the times for evaluating the lazy vals here are a few hundred ms out of a 2s startup
- lazy val projectNames = baseProject.projectClosure.map(_.name)
- val prefixes = ContinuousExecutePrefix :: CrossBuildPrefix :: Nil
- lazy val scalaVersions = baseProject.crossScalaVersions ++ Seq(baseProject.defScalaVersion.value)
- lazy val methods = project.methods
- lazy val methodCompletions = new ExtraCompletions { def names = methods.keys.toList; def completions(name: String) = methods(name).completions }
- lazy val completors = new Completors(ProjectAction, projectNames, basicCommands, List(GetAction, SetAction), SpecificBuildPrefix, scalaVersions, prefixes, project.taskNames, project.propertyNames, methodCompletions)
- val reader = new LazyJLineReader(baseProject.historyPath, MainCompletor(completors), baseProject.log)
- reader.readLine("> ").getOrElse(ExitCommand)
- }
- /** The name of the command that loads a console with access to the current project through the variable 'project'.*/
- val ProjectConsoleAction = "console-project"
- /** The name of the command that shows the current project and logging level of that project.*/
- val ShowCurrent = "current"
- /** The name of the command that shows all available actions.*/
- val ShowActions = "actions"
- /** The name of the command that sets the currently active project.*/
- val ProjectAction = "project"
- /** The name of the command that shows all available projects.*/
- val ShowProjectsAction = "projects"
- val ExitCommand = "exit"
- val QuitCommand = "quit"
- /** The name of the command that resets JLine. This is necessary when resuming from suspension.*/
- val ResetCommand = "reset"
- /** The name of the command that switches to the builder project.*/
- val BuilderCommand = "builder"
- /** The name of the command that loads the interactive shell.*/
- val InteractiveCommand = "shell"
- /** The list of lowercase command names that may be used to terminate the program.*/
- val TerminateActions: Iterable[String] = ExitCommand :: QuitCommand :: Nil
- /** The name of the command that sets the value of the property given as its argument.*/
- val SetAction = "set"
- /** The name of the command that gets the value of the property given as its argument.*/
- val GetAction = "get"
- /** The name of the command that displays the help message. */
- val HelpAction = "help"
- /** The command for reloading sbt.*/
- val RebootCommand = "reload"
- /** The name of the command that toggles logging stacktraces. */
- val TraceCommand = "trace"
- /** The name of the command that compiles all sources continuously when they are modified. */
- val ContinuousCompileCommand = "cc"
- /** The prefix used to identify a request to execute the remaining input on source changes.*/
- val ContinuousExecutePrefix = "~"
- /** The prefix used to identify a request to execute the remaining input across multiple Scala versions.*/
- val CrossBuildPrefix = "+"
- /** The prefix used to identify a request to execute the remaining input after the next space against the
- * Scala version between this prefix and the space (i.e. '++version action' means execute 'action' using
- * Scala version 'version'. */
- val SpecificBuildPrefix = "++"
- /** The prefix used to identify a file or local port to read commands from. */
- val FileCommandsPrefix = "<"
- /** The prefix used to identify the action to run after an error*/
- val FailureHandlerPrefix = "-"
- /** The prefix used to identify commands for managing processors.*/
- val ProcessorPrefix = "*"
-
- /** The number of seconds between polling by the continuous compile command.*/
- val ContinuousCompilePollDelaySeconds = 1
-
- /** The list of logging levels.*/
- private def logLevels: Iterable[String] = TreeSet.empty[String] ++ Level.values.map(_.toString)
- /** The list of all interactive commands other than logging level.*/
- private def basicCommands: Iterable[String] = TreeSet(ShowProjectsAction, ShowActions, ShowCurrent, HelpAction,
- RebootCommand, TraceCommand, ContinuousCompileCommand, ProjectConsoleAction, BuilderCommand) ++
- logLevels.toList ++ TerminateActions ++
- HistoryCommands.plainCommands
-
- private def processAction(baseProject: Project, currentProject: Project, action: String, isInteractive: Boolean): Boolean =
- action match
- {
- case HelpAction => displayHelp(isInteractive); true
- case ShowProjectsAction => baseProject.projectClosure.foreach(listProject); true
- case ProjectConsoleAction =>
- showResult(Run.projectConsole(currentProject), currentProject.log)
- case _ =>
- if(action.startsWith(SetAction + " "))
- setProperty(currentProject, action.substring(SetAction.length + 1))
- else if(action.startsWith(GetAction + " "))
- getProperty(currentProject, action.substring(GetAction.length + 1))
- else if(action.startsWith(TraceCommand + " "))
- setTrace(currentProject, action.substring(TraceCommand.length + 1))
- else
- handleCommand(currentProject, action)
- }
-
- private def printCmd(name:String, desc:String) = Console.println(" " + name + " : " + desc)
- val BatchHelpHeader = "You may execute any project action or method or one of the commands described below."
- val InteractiveHelpHeader = "You may execute any project action or one of the commands described below. Only one action " +
- "may be executed at a time in interactive mode and is entered by name, as it would be at the command line." +
- " Also, tab completion is available."
- private def displayHelp(isInteractive: Boolean)
- {
- Console.println(if(isInteractive) InteractiveHelpHeader else BatchHelpHeader)
- Console.println("Available Commands:")
-
- printCmd("", "Executes the project specified action.")
- printCmd(" *", "Executes the project specified method.")
- printCmd(" ", "Runs the specified processor.")
- printCmd(ContinuousExecutePrefix + " ", "Executes the project specified action or method whenever source files change.")
- printCmd(FileCommandsPrefix + " file", "Executes the commands in the given file. Each command should be on its own line. Empty lines and lines beginning with '#' are ignored")
- printCmd(CrossBuildPrefix + " ", "Executes the project specified action or method for all versions of Scala defined in crossScalaVersions.")
- printCmd(SpecificBuildPrefix + " ", "Changes the version of Scala building the project and executes the provided command. is optional.")
- printCmd(ProcessorPrefix, "Prefix for commands for managing processors. Run '" + ProcessorPrefix + "help' for details.")
- printCmd(HistoryPrefix, "Prefix for history commands. Run '" + HistoryPrefix+ "' for history command help.")
- printCmd(ShowActions, "Shows all available actions.")
- printCmd(RebootCommand, "Reloads sbt, picking up modifications to sbt.version or scala.version and recompiling modified project definitions.")
- printCmd(HelpAction, "Displays this help message.")
- printCmd(ShowCurrent, "Shows the current project, Scala version, and logging level.")
- printCmd(Level.values.mkString(", "), "Set logging for the current project to the specified level.")
- printCmd(TraceCommand + " " + validTraceArguments, "Configures stack trace logging. " + traceExplanation)
- printCmd(ProjectAction + " ", "Sets the currently active project.")
- printCmd(ShowProjectsAction, "Shows all available projects.")
- printCmd(TerminateActions.elements.mkString(", "), "Terminates the build.")
- printCmd(SetAction + " ", "Sets the value of the property given as its argument.")
- printCmd(GetAction + " ", "Gets the value of the property given as its argument.")
- printCmd(ProjectConsoleAction, "Enters the Scala interpreter with the current project definition bound to the variable 'current' and all members imported.")
- printCmd(BuilderCommand, "Set the current project to be the project definition builder.")
- if(!isInteractive)
- printCmd(InteractiveCommand, "Enters the sbt interactive shell")
- }
- private def listProject(p: Project) = printProject("\t", p)
- private def printProject(prefix: String, p: Project): Unit =
- Console.println(prefix + p.name + " " + p.version)
-
- /** Handles the given command string provided at the command line. Returns false if there was an error*/
- private def handleCommand(project: Project, command: String): Boolean =
- {
- command match
- {
- case GetAction => getArgumentError(project.log)
- case SetAction => setArgumentError(project.log)
- case ProjectAction => setProjectError(project.log)
- case TraceCommand => setTraceError(project.log); true
- case ShowCurrent =>
- printProject("Current project is ", project)
- Console.println("Current Scala version is " + project.buildScalaVersion)
- Console.println("Current log level is " + project.log.getLevel)
- printTraceEnabled(project)
- true
- case ShowActions => showActions(project); true
- case Level(level) => setLevel(project, level); true
- case ContinuousCompileCommand => compileContinuously(project)
- case action if action.startsWith(ContinuousExecutePrefix) => executeContinuously(project, action.substring(ContinuousExecutePrefix.length).trim)
- case action => handleAction(project, action)
- }
- }
- private def showActions(project: Project): Unit = Console.println(project.taskAndMethodList)
-
- // returns true if it succeeded
- private def handleAction(project: Project, action: String): Boolean =
- {
- def show(result: Option[String]): Boolean = showResult(result, project.log)
- val startTime = System.currentTimeMillis
- val result = withAction(project, action)( (name, params) => show(project.call(name, params)))( name => show(project.act(name)))
- printTime(project, startTime, "")
- result
- }
- // returns true if it succeeded
- private def showResult(result: Option[String], log: Logger): Boolean =
- {
- result match
- {
- case Some(errorMessage) => log.error(errorMessage); false
- case None => log.success("Successful."); true
- }
- }
- // true if the action exists
- private def checkAction(project: Project, actionString: String): Boolean =
- withAction(project, actionString)( (n,p) => true)( n => true)
- private def withAction(project: Project, actionString: String)(ifMethod: (String, Array[String]) => Boolean)(ifAction: String => Boolean): Boolean =
- {
- def didNotExist(taskType: String, name: String) =
- {
- project.log.error("No " + taskType + " named '" + name + "' exists.")
- project.log.info("Execute 'help' for a list of commands or 'actions' for a list of available project actions and methods.")
- false
- }
- impl.CommandParser.parse(actionString) match
- {
- case Left(errMsg) => project.log.error(errMsg); false
- case Right((name, parameters)) =>
- if(project.methods.contains(name))
- ifMethod(name, parameters.toArray)
- else if(!parameters.isEmpty)
- didNotExist("method", name)
- else if(project.deepTasks.contains(name))
- ifAction(name)
- else
- didNotExist("action", name)
- }
- }
-
- /** Toggles whether stack traces are enabled.*/
- private def setTrace(project: Project, value: String): Boolean =
- {
- try
- {
- val newValue = if(value == "on") MaxInt else if(value == "off") -1 else if(value == "nosbt") 0 else value.toInt
- project.projectClosure.foreach(_.log.setTrace(newValue))
- printTraceEnabled(project)
- true
- }
- catch { case _: NumberFormatException => setTraceError(project.log) }
- }
- private def printTraceEnabled(project: Project)
- {
- def traceLevel(level: Int) = if(level == 0) " (no sbt stack elements)" else if(level == MaxInt) "" else " (maximum " + level + " stack elements per exception)"
- Console.println("Stack traces are " + (if(project.log.traceEnabled) "enabled" + traceLevel(project.log.getTrace) else "disabled"))
- }
- /** Sets the logging level on the given project.*/
- private def setLevel(project: Project, level: Level.Value)
- {
- project.projectClosure.foreach(_.log.setLevel(level))
- Console.println("Set log level to " + project.log.getLevel)
- }
- /** Prints the elapsed time to the given project's log using the given
- * initial time and the label 's'.*/
- private def printTime(project: Project, startTime: Long, s: String)
- {
- val endTime = System.currentTimeMillis()
- project.log.info("")
- val ss = if(s.isEmpty) "" else s + " "
- project.log.info("Total " + ss + "time: " + (endTime - startTime + 500) / 1000 + " s, completed " + nowString)
- }
- private def nowString =
- {
- import java.text.DateFormat
- val format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM)
- format.format(new java.util.Date)
- }
- /** Provides a partial message describing why the given property is undefined. */
- private def undefinedMessage(property: Project#UserProperty[_]): String =
- {
- property.resolve match
- {
- case vu: UndefinedValue => " is not defined."
- case e: ResolutionException => " has invalid value: " + e.toString
- case _ => ""
- }
- }
- /** Prompts the user for the value of undefined properties. 'first' is true if this is the first time
- * that the current property has been prompted.*/
- private def fillUndefinedProperties(project: Project, properties: List[(String, Project#Property[_])], first: Boolean): Boolean =
- {
- properties match
- {
- case (name, variable) :: tail =>
- {
- val shouldAdvanceOrQuit =
- variable match
- {
- case property: Project#UserProperty[_] =>
- if(first)
- project.log.error(" Property '" + name + "' " + undefinedMessage(property))
- for(newValue <- SimpleReader.readLine(" Enter new value for " + name + " : ")) yield
- {
- try
- {
- property.setStringValue(newValue)
- true
- }
- catch
- {
- case e =>
- project.log.error("Invalid value: " + e.getMessage)
- false
- }
- }
- case _ => Some(true)
- }
- shouldAdvanceOrQuit match
- {
- case Some(shouldAdvance) => fillUndefinedProperties(project, if(shouldAdvance) tail else properties, shouldAdvance)
- case None => false
- }
- }
- case Nil => true
- }
- }
- /** Iterates over the undefined properties in the given projects, prompting the user for the value of each undefined
- * property.*/
- private def fillUndefinedProjectProperties(projects: List[Project]): Boolean =
- {
- projects match
- {
- case project :: remaining =>
- val uninitialized = project.uninitializedProperties.toList
- if(uninitialized.isEmpty)
- fillUndefinedProjectProperties(remaining)
- else
- {
- project.log.error("Project in " + project.info.projectDirectory.getAbsolutePath + " has undefined properties.")
- val result = fillUndefinedProperties(project, uninitialized, true) && fillUndefinedProjectProperties(remaining)
- project.saveEnvironment()
- result
- }
- case Nil => true
- }
- }
- /** Prints the value of the property with the given name in the given project. */
- private def getProperty(project: Project, propertyName: String): Boolean =
- {
- if(propertyName.isEmpty)
- {
- project.log.error("No property name specified.")
- false
- }
- else
- {
- project.getPropertyNamed(propertyName) match
- {
- case Some(property) =>
- property.resolve match
- {
- case u: UndefinedValue => project.log.error("Value of property '" + propertyName + "' is undefined."); false
- case ResolutionException(m, e) => project.log.error(m); false
- case DefinedValue(value, isInherited, isDefault) => Console.println(value.toString); true
- }
- case None =>
- val value = System.getProperty(propertyName)
- if(value == null)
- project.log.error("No property named '" + propertyName + "' is defined.")
- else
- Console.println(value)
- value != null
- }
- }
- }
- /** Separates the space separated property name/value pair and stores the value in the user-defined property
- * with the given name in the given project. If no such property exists, the value is stored in a system
- * property. */
- private def setProperty(project: Project, propertyNameAndValue: String): Boolean =
- {
- val m = """(\S+)(\s+\S.*)?""".r.pattern.matcher(propertyNameAndValue)
- if(m.matches())
- {
- val name = m.group(1)
- val newValue =
- {
- val v = m.group(2)
- if(v == null) "" else v.trim
- }
- def notePending(changed: String): Unit = Console.println(" Build will use " + changed + newValue + " after running 'reload' command or restarting sbt.")
- project.getPropertyNamed(name) match
- {
- case Some(property) =>
- {
- try
- {
- property.setStringValue(newValue)
- property match
- {
- case project.defScalaVersion | project.buildScalaVersions => notePending("Scala ")
- case project.sbtVersion => notePending("sbt ")
- case _ => Console.println(" Set property '" + name + "' = '" + newValue + "'")
- }
- true
- }
- catch { case e =>
- project.log.error("Error setting property '" + name + "' in " + project.environmentLabel + ": " + e.toString)
- false
- }
- finally { project.saveEnvironment().foreach(msg => project.log.error("Error saving environment: " + msg)) }
- }
- case None =>
- {
- System.setProperty(name, newValue)
- project.log.info(" Set system property '" + name + "' = '" + newValue + "'")
- true
- }
- }
- }
- else
- setArgumentError(project.log)
- }
-
- private def compileContinuously(project: Project) = executeContinuously(project, "test-compile")
- private def executeContinuously(project: Project, action: String) =
- {
- def shouldTerminate: Boolean = (System.in.available > 0) && (project.terminateWatch(System.in.read()) || shouldTerminate)
- val actionValid = checkAction(project, action)
- if(actionValid)
- {
- var count = 0
- val sourcesFinder: PathFinder = (Path.emptyPathFinder /: project.topologicalSort)(_ +++ _.watchPaths)
- SourceModificationWatch.watchUntil(sourcesFinder, ContinuousCompilePollDelaySeconds)(shouldTerminate)
- {
- count += 1
- handleAction(project, action)
- Console.println(count + ". Waiting for source changes... (press enter to interrupt)")
- }
- while (System.in.available() > 0) System.in.read()
- }
- actionValid
- }
-
- def validTraceArguments = "'on', 'nosbt', 'off', or "
- def traceExplanation = "'nosbt' prints stack traces up to the first sbt frame. An integer gives the number of frames to show per exception."
- private def isTerminateAction(s: String) = TerminateActions.elements.contains(s.toLowerCase)
- private def setTraceError(log: Logger) = logError(log)("Invalid arguments for 'trace': expected " + validTraceArguments + ".")
- private def setArgumentError(log: Logger) = logError(log)("Invalid arguments for 'set': expected property name and new value.")
- private def getArgumentError(log: Logger) = logError(log)("Invalid arguments for 'get': expected property name.")
- private def setProjectError(log: Logger) = logError(log)("Invalid arguments for 'project': expected project name.")
- private def logError(log: Logger)(s: String) = { log.error(s); false }
-
- private def logCommandError(log: Logger, e: Throwable) =
- e match
- {
- case pe: processor.ProcessorException =>
- if(pe.getCause ne null) log.trace(pe.getCause)
- log.error(e.getMessage)
- case e =>
- log.trace(e)
- log.error(e.toString)
- }
-}
diff --git a/sbt_pending/src/main/scala/sbt/Project.scala b/sbt_pending/src/main/scala/sbt/Project.scala
deleted file mode 100644
index 6bcf4d3b9..000000000
--- a/sbt_pending/src/main/scala/sbt/Project.scala
+++ /dev/null
@@ -1,537 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah, David MacIver
- */
-package sbt
-
-import xsbti.{AppProvider, ScalaProvider}
-import xsbt.{AnalyzingCompiler, ScalaInstance}
-import java.io.File
-import java.net.URLClassLoader
-import scala.collection._
-import FileUtilities._
-import Project._
-
-trait Project extends TaskManager with Dag[Project] with BasicEnvironment
-{
- /** The logger for this project definition. */
- final val log: Logger = logImpl
- protected def logImpl: Logger =
- {
- val lg = new BufferedLogger(new FilterLogger(info.logger))
- lg.setLevel(defaultLoggingLevel)
- lg
- }
- protected def defaultLoggingLevel = Level.Info
-
- trait ActionOption extends NotNull
-
- /** Basic project information. */
- def info: ProjectInfo
- /** The project name. */
- def name: String = projectName.value
- /** The project version. */
- def version: Version = projectVersion.value
- /** The project organization. */
- def organization: String = projectOrganization.value
- /** True if the project should cater to a quick throwaway project setup.*/
- def scratch = projectScratch.value
-
- final type ManagerType = Project
- final type ManagedTask = Project#Task
- /** The tasks declared on this project. */
- def tasks: Map[String, ManagedTask]
- /** The task methods declared on this project */
- def methods: Map[String, MethodTask]
- /** The names of all available tasks that may be called through `act`. These include
- * the names of the Tasks in `tasks` and those of all dependencies.*/
- def taskNames: Iterable[String] = deepTasks.keys.toList
- /** The names of all available method tasks that may be called through `call`. These
- * only include the names of the MethodTasks in `methods` and not those of dependencies.*/
- def methodNames: Iterable[String] = methods.keys.toList
- /** A description of all available method tasks in this project, but not of dependencies. */
- def methodList: String = descriptionList(methods)
- /** A description of all available tasks in this project and all dependencies. If there
- * are different tasks with the same name, only one will be included. */
- def taskList: String = descriptionList(deepTasks)
-
- final def taskName(task: Task) = tasks.find( _._2 eq task ).map(_._1)
- /** A description of all available tasks in this project and all dependencies and all
- * available method tasks in this project, but not of dependencies. If there
- * are different tasks or methods with the same name, only one will be included. */
- def taskAndMethodList: String = descriptionList(tasksAndMethods)
- /** The actions and methods declared on this project. */
- final def tasksAndMethods: Map[String, Described] =
- immutable.TreeMap.empty[String, Described] ++ methods ++ tasks
- private def descriptionList(described: Map[String, Described]): String =
- {
- val buffer = new StringBuilder
- for((name, d) <- described)
- buffer.append("\t" + name + d.description.map(x => ": " + x).getOrElse("") + "\n")
- buffer.toString
- }
- /** Combines the method task maps of this project and all dependencies.*/
- private[sbt] def deepMethods: Map[String, Project#MethodTask] = deep(_.methods)
- /** Combines the task maps of this project and all dependencies.*/
- private[sbt] def deepTasks: Map[String, Project#Task] = deep(_.tasks)
- private def deep[T](p: Project => Map[String, T]): Map[String, T] =
- {
- var tasks: immutable.SortedMap[String,T] = new immutable.TreeMap[String, T]
- for(dependentProject <- topologicalSort)
- tasks ++= p(dependentProject).elements
- tasks
- }
- /** A map of names to projects for all subprojects of this project. These are typically explicitly
- * specified for the project and are different from those specified in the project constructor. The
- * main use within sbt is in ParentProject.*/
- def subProjects: Map[String, Project] = immutable.Map.empty
- def projectClosure: List[Project] = Dag.topologicalSort(this)(p => p.dependencies ++ p.subProjects.values.toList)
-
- def call(name: String, parameters: Array[String]): Option[String] =
- {
- methods.get(name) match
- {
- case Some(method) =>run(method(parameters), name)
- case None => Some("Method '" + name + "' does not exist.")
- }
- }
- private def run(task: Project#Task, taskName: String): Option[String] =
- impl.RunTask(task, taskName, parallelExecution) match
- {
- case Nil => None
- case x => Some(Set(x: _*).mkString("\n"))
- }
-
- /** Executes the task with the given name. This involves executing the task for all
- * project dependencies (transitive) and then for this project. Not every dependency
- * must define a task with the given name. If this project and all dependencies
- * do not define a task with the given name, an error is generated indicating this.*/
- def act(name: String): Option[String] =
- {
- val ordered = topologicalSort
- val definedTasks = ordered.flatMap(_.tasks.get(name).toList)
- def virtualTask(name: String): Task = new Task(None, definedTasks.filter(!_.interactive), false, None)
-
- if(definedTasks.isEmpty)
- Some("Action '" + name + "' does not exist.")
- else
- {
- tasks.get(name) match
- {
- case None =>
- val virtual = virtualTask(name)
- if(virtual.dependencies.size == definedTasks.size)
- run(virtual, name)
- else
- {
- Some("Cannot run interactive action '" + name +
- "' defined on multiple subprojects (change to the desired project with 'project ').")
- }
- case Some(task) => run(task, name)
- }
- }
- }
-
- /** Logs the list of projects at the debug level.*/
- private def showBuildOrder(order: Iterable[Project])
- {
- log.debug("Project build order:")
- order.foreach(x => log.debug(" " + x.name) )
- log.debug("")
- }
-
- /** Converts a String to a path relative to the project directory of this project. */
- implicit def path(component: String): Path = info.projectPath / component
- /** Converts a String to a simple name filter. * has the special meaning: zero or more of any character */
- implicit def filter(simplePattern: String): NameFilter = GlobFilter(simplePattern)
-
- /** Loads the project at the given path and declares the project to have the given
- * dependencies. This method will configure the project according to the
- * project/ directory in the directory denoted by path.*/
- def project(path: Path, deps: Project*): Project = getProject(Project.loadProject(path, deps, Some(this), info.logger, info.app, info.buildScalaVersion), path)
-
- /** Loads the project at the given path using the given name and inheriting this project's version.
- * The builder class is the default builder class, sbt.DefaultProject. The loaded project is declared
- * to have the given dependencies. Any project/build/ directory for the project is ignored.*/
- def project(path: Path, name: String, deps: Project*): Project = project(path, name, Project.DefaultBuilderClass, deps: _*)
-
- /** Loads the project at the given path using the given name and inheriting it's version from this project.
- * The Project implementation used is given by builderClass. The dependencies are declared to be
- * deps. Any project/build/ directory for the project is ignored.*/
- def project[P <: Project](path: Path, name: String, builderClass: Class[P], deps: Project*): P =
- {
- require(builderClass != this.getClass, "Cannot recursively construct projects of same type: " + builderClass.getName)
- project(path, name, info => Project.constructProject(info, builderClass), deps: _*)
- }
- /** Loads the project at the given path using the given name and inheriting it's version from this project.
- * The construct function is used to obtain the Project instance. Any project/build/ directory for the project
- * is ignored. The project is declared to have the dependencies given by deps.*/
- def project[P <: Project](path: Path, name: String, construct: ProjectInfo => P, deps: Project*): P =
- initialize(construct(ProjectInfo(path.asFile, deps, Some(this))(info.logger, info.app, info.buildScalaVersion)), Some(new SetupInfo(name, None, None, false)), log)
-
- /** Initializes the project directories when a user has requested that sbt create a new project.*/
- def initializeDirectories() {}
- /** True if projects should be run in parallel, false if they should run sequentially.
- * This only has an effect for multi-projects. If this project has a parent, this value is
- * inherited from that parent project.*/
- def parallelExecution: Boolean =
- info.parent match
- {
- case Some(parent) => parent.parallelExecution
- case None => false
- }
-
- /** True if a project and its dependencies should be checked to ensure that their
- * output directories are not the same, false if they should not be checked. */
- def shouldCheckOutputDirectories = true
-
- /** The list of directories to which this project writes. This is used to verify that multiple
- * projects have not been defined with the same output directories. */
- def outputDirectories: Iterable[Path] = outputPath :: Nil
- def rootProject = Project.rootProject(this)
- /** The path to the file that provides persistence for properties.*/
- final def envBackingPath = info.builderPath / Project.DefaultEnvBackingName
- /** The path to the file that provides persistence for history. */
- def historyPath: Option[Path] = Some(outputRootPath / ".history")
- def outputPath = crossPath(outputRootPath)
- def outputRootPath: Path = outputDirectoryName
- def outputDirectoryName = DefaultOutputDirectoryName
-
- private def getProject(result: LoadResult, path: Path): Project =
- result match
- {
- case LoadSetupDeclined => Predef.error("No project exists at path " + path)
- case lse: LoadSetupError => Predef.error("Error setting up new project at path " + path + " : " + lse.message)
- case err: LoadError => Predef.error("Error loading project at path " + path + " : " + err.message)
- case success: LoadSuccess => success.project
- }
-
- /** The property for the project's version. */
- final val projectVersion = property[Version]
- /** The property for the project's name. */
- final val projectName = propertyLocalF[String](NonEmptyStringFormat)
- /** The property for the project's organization. Defaults to the parent project's organization or the project name if there is no parent. */
- final val projectOrganization = propertyOptional[String](normalizedName, true)
- /** The property that defines the version of Scala to use with the project definition. This can be different
- * from the version of Scala used to build the project (current version used is buildScalaVersion, available are in buildScalaVersions).
- * This property is only read by `sbt` on startup and reload.*/
- final val defScalaVersion = propertyOptional[String](info.definitionScalaVersion)
- /** The property to specify the sbt revision to use.
- * Note that this can by a dynamic revision (see Ivy documentation for details on dynamic revisions).
- *Therefore, use `sbt.ComponentManager.version` and `timestamp` for actual version information. */
- final val sbtVersion = property[String]
- final val projectInitialize = propertyOptional[Boolean](false)
- final val projectScratch = propertyOptional[Boolean](false, true)
- final val offline = propertyOptional[Boolean](false)
- /** The property that defines the versions of Scala to build this project against as a comma separated string. This can be
- * different from the version of Scala used to build and run the project definition (defined by defScalaVersion).
- * This property is only read by `sbt` on startup and reload. The definitive source for the version of Scala currently
- * being used is buildScalaVersion.*/
- final val buildScalaVersions = propertyOptional[String](defScalaVersion.value, true)
- /** The definitive source for the version of Scala being requested to *build* the project.
- * For the full version information, see buildScalaInstance.actualVersion.*/
- def buildScalaVersion = info.buildScalaVersion.getOrElse(crossScalaVersions.first)
- private[sbt] def isScala27 = buildScalaInstance.actualVersion.startsWith("2.7.")
-
-
- def componentManager = new ComponentManager(info.launcher.globalLock, info.app.components, log)
- def buildScalaInstance = buildScalaInstance0
- final def buildLibraryJar = Path.fromFile(buildScalaInstance.libraryJar)
- final def buildCompilerJar = Path.fromFile(buildScalaInstance.compilerJar)
- final def buildScalaJars = Path.finder { buildScalaInstance.jars }
- final def buildScalaInstance0: ScalaInstance =
- {
- val scalaVersion = buildScalaVersion
- try { getScalaInstance(scalaVersion) }
- catch { case e: xsbti.RetrieveException if info.buildScalaVersion.isEmpty => // only catch the exception if this is the default Scala version
- log.error(e.getMessage)
- SimpleReader.readLine("\nProvide a new Scala version or press enter to exit: ") match
- {
- case Some(v) if v.length > 0=>
- buildScalaVersions() = replace(scalaVersion, v)
- saveEnvironment()
- buildScalaInstance0
- case _ => throw e
- }
- }
- }
- private def replace(originalV: String, newV: String) = buildScalaVersions.value.replaceAll("""\b\Q""" + originalV + """\E\b""", newV)
- def getScalaInstance(version: String) =
- localScalaInstances.find(_.version == version) getOrElse
- xsbt.ScalaInstance(version, info.launcher)
- lazy val localScalaInstances: Seq[ScalaInstance] = localScala ++ info.parent.toList.flatMap(_.localScalaInstances)
- def localScala: Seq[ScalaInstance] = Nil
- lazy val buildCompiler = new AnalyzingCompiler(buildScalaInstance, componentManager, log)
- /** Get a `ScalaInstance` for the Scala version with base directory `home`. The library and compiler jars are
- * assumed to be at `new File(home, "lib/scala-library.jar")` and `new File(home, "lib/scala-compiler.jar")`.
- * The label for this instance is determined by the version String in the `compiler.properties` file in `scala-compiler.jar`.*/
- def defineScala(home: File): ScalaInstance = ScalaInstance(home, info.launcher)
- /** Get a `ScalaInstance` for the Scala version with base directory `home`. The library and compiler jars are
- * assumed to be at `new File(home, "lib/scala-library.jar")` and `new File(home, "lib/scala-compiler.jar")`.
- * `version` is used as the label for this instance.*/
- def defineScala(version: String, home: File): ScalaInstance = ScalaInstance(version, home, info.launcher)
-
- /** If this project is cross-building, returns `base` with an additional path component containing the scala version
- * currently used to build the project. Otherwise, this returns `base`.
- * By default, cross-building is enabled when a project is loaded by the loader and crossScalaVersions is not empty.*/
- def crossPath(base: Path) = if(disableCrossPaths) base else base / crossString
- /** If modifying paths for cross-building is enabled, this returns ScalaVersion.currentString.
- * Otherwise, this returns the empty string. */
- def crossScalaVersionString: String = if(disableCrossPaths) "" else buildScalaVersion
- private def crossString = "scala_" + buildScalaVersion
-
-
- /** True if crossPath should be the identity function.*/
- protected def disableCrossPaths = crossScalaVersions.isEmpty
- /** By default, this is the build.scala.versions property split around whitespace. This can be overridden directly if preferred.*/
- def crossScalaVersions: Seq[String] =
- info.parent match
- {
- case Some(p) => p.crossScalaVersions
- case None => buildScalaVersions.value.split("""\s+""").toList.reverse.removeDuplicates.reverse
- }
- /** A `PathFinder` that determines the files watched when an action is run with a preceeding ~ when this is the current
- * project. This project does not need to include the watched paths for projects that this project depends on.*/
- def watchPaths: PathFinder = Path.emptyPathFinder
- def terminateWatch(key: Int): Boolean = key == 10 || key == 13
-
- protected final override def parentEnvironment = info.parent
-
- // .* included because svn doesn't mark .svn hidden
- def defaultExcludes: FileFilter = (".*" - ".") || HiddenFileFilter
- /** Short for parent.descendentsExcept(include, defaultExcludes)*/
- def descendents(parent: PathFinder, include: FileFilter) = parent.descendentsExcept(include, defaultExcludes)
- override def toString = "Project " + projectName.get.getOrElse("at " + environmentLabel)
-
- def normalizedName = StringUtilities.normalize(name)
-}
-private[sbt] sealed trait LoadResult extends NotNull
-private[sbt] final class LoadSuccess(val project: Project) extends LoadResult
-private[sbt] final class LoadError(val message: String) extends LoadResult
-private[sbt] final object LoadSetupDeclined extends LoadResult
-private[sbt] final class LoadSetupError(val message: String) extends LoadResult
-
-object Project
-{
- val BootDirectoryName = "boot"
- val DefaultOutputDirectoryName = "target"
- val DefaultEnvBackingName = "build.properties"
- val DefaultBuilderClassName = "sbt.DefaultProject"
- val DefaultBuilderClass = Class.forName(DefaultBuilderClassName).asSubclass(classOf[Project])
-
- /** The name of the directory for project definitions.*/
- val BuilderProjectDirectoryName = "build"
- /** The name of the directory for plugin definitions.*/
- val PluginProjectDirectoryName = "plugins"
- /** The name of the class that all projects must inherit from.*/
- val ProjectClassName = classOf[Project].getName
-
- /** The logger that should be used before the root project definition is loaded.*/
- private[sbt] def bootLogger =
- {
- val log = new ConsoleLogger
- log.setLevel(Level.Debug)
- log
- }
-
- private[sbt] def booted = java.lang.Boolean.getBoolean("sbt.boot")
-
- private[sbt] def loadProject(app: AppProvider): LoadResult = loadProject(app, None)
- /** Loads the project in the current working directory. */
- private[sbt] def loadProject(app: AppProvider, buildScalaVersion: Option[String]): LoadResult = loadProject(bootLogger, app, buildScalaVersion)
- /** Loads the project in the current working directory.*/
- private[sbt] def loadProject(log: Logger, app: AppProvider, buildScalaVersion: Option[String]): LoadResult =
- checkOutputDirectories(loadProject(new File("."), Nil, None, log, app, buildScalaVersion))
- /** Loads the project in the directory given by 'path' and with the given dependencies.*/
- private[sbt] def loadProject(path: Path, deps: Iterable[Project], parent: Option[Project], log: Logger, app: AppProvider, buildScalaVersion: Option[String]): LoadResult =
- loadProject(path.asFile, deps, parent, log, app, buildScalaVersion)
- /** Loads the project in the directory given by 'projectDirectory' and with the given dependencies.*/
- private[sbt] def loadProject(projectDirectory: File, deps: Iterable[Project], parent: Option[Project], log: Logger, app: AppProvider, buildScalaVersion: Option[String]): LoadResult =
- {
- val info = ProjectInfo(projectDirectory, deps, parent)(log, app, buildScalaVersion)
- ProjectInfo.setup(info, log) match
- {
- case err: SetupError => new LoadSetupError(err.message)
- case SetupDeclined => LoadSetupDeclined
- case AlreadySetup => loadProject(info, None, log)
- case setup: SetupInfo => loadProject(info, Some(setup), log)
- }
- }
- private def loadProject(info: ProjectInfo, setupInfo: Option[SetupInfo], log: Logger): LoadResult =
- {
- try
- {
- val result =
- for(builderClass <- getProjectDefinition(info, log).right) yield
- initialize(constructProject(info, builderClass), setupInfo, log)
- result.fold(new LoadError(_), new LoadSuccess(_))
- }
- catch
- {
- case ite: java.lang.reflect.InvocationTargetException =>
- {
- val cause =
- if(ite.getCause == null) ite
- else ite.getCause
- errorLoadingProject(cause, log)
- }
- case nme: NoSuchMethodException => new LoadError("Constructor with one argument of type sbt.ProjectInfo required for project definition.")
- case e: Exception => errorLoadingProject(e, log)
- }
- }
- private def errorLoadingProject(e: Throwable, log: Logger) =
- e match
- {
- case _: xsbti.RetrieveException => LoadSetupDeclined
- case _ =>
- log.trace(e)
- new LoadError("Error loading project: " + e.toString)
- }
- /** Loads the project for the given `info` and represented by an instance of 'builderClass'.*/
- private[sbt] def constructProject[P <: Project](info: ProjectInfo, builderClass: Class[P]): P =
- builderClass.getConstructor(classOf[ProjectInfo]).newInstance(info)
- /** Checks the project's dependencies, initializes its environment, and possibly its directories.*/
- private def initialize[P <: Project](p: P, setupInfo: Option[SetupInfo], log: Logger): P =
- {
- def save() = p.saveEnvironment() foreach { errorMsg => log.error(errorMsg) }
- setupInfo match
- {
- case Some(setup) =>
- {
- p.projectName() = setup.name
- for(v <- setup.version)
- p.projectVersion() = v
- for(org <- setup.organization)
- p.projectOrganization() = org
- if(!setup.initializeDirectories)
- p.setEnvironmentModified(false)
- save()
- if(setup.initializeDirectories)
- p.initializeDirectories()
- }
- case None =>
- if(p.projectInitialize.value)
- {
- p.initializeDirectories()
- p.projectInitialize() = false
- save()
- }
- }
- val useName = p.projectName.get.getOrElse("at " + p.info.projectDirectory.getAbsolutePath)
- checkDependencies(useName, p.info.dependencies, log)
- p.buildScalaInstance // done so that build Scala version is initialized on project startup
- p
- }
- /** Compiles the project definition classes and returns the project definition class name
- * and the class loader that should be used to load the definition. */
- private def getProjectDefinition(info: ProjectInfo, buildLog: Logger): Either[String, Class[P] forSome { type P <: Project }] =
- getProjectBuilder(info, buildLog) match
- {
- case Some(builder) => buildProjectDefinition(builder)
- case None => Right(DefaultBuilderClass)
- }
- private def buildProjectDefinition(builderProject: BuilderProject): Either[String, Class[P] forSome { type P <: Project }] =
- builderProject.compile.run.toLeft(()).right.flatMap { ignore =>
- builderProject.projectDefinition.right.map {
- case Some(definition) => getProjectClass[Project](definition, builderProject.projectClasspath, getClass.getClassLoader)
- case None => DefaultBuilderClass
- }
- }
- private[sbt] def getProjectClasspath(project: Project): PathFinder =
- getProjectBuilder(project.info, project.log) match
- {
- case Some(builder) => builder.projectClasspath
- case _ if project.getClass == DefaultBuilderClass => project.info.sbtClasspath
- case _ =>
- project.info.parent match
- {
- case Some(p) => getProjectClasspath(p)
- case None => project.info.sbtClasspath
- }
- }
- private[sbt] def getProjectBuilder(info: ProjectInfo, buildLog: Logger): Option[BuilderProject] =
- {
- if(info.builderProjectPath.asFile.isDirectory)
- {
- val builderInfo = ProjectInfo(info.builderProjectPath.asFile, Nil, None)(buildLog, info.app, Some(info.definitionScalaVersion))
- val builderProject = new BuilderProject(builderInfo, info.pluginsPath, buildLog)
- Some(builderProject)
- }
- else
- None
- }
- /** Verifies that the given list of project dependencies contains no nulls. The
- * String argument should be the project name with the dependencies.*/
- private def checkDependencies(forProject: String, deps: Iterable[Project], log: Logger)
- {
- for(nullDep <- deps.find(_ == null))
- {
- log.error("Project " + forProject + " had a null dependency. This is probably an initialization problem and might be due to a circular dependency.")
- throw new RuntimeException("Null dependency in project " + forProject)
- }
- }
- /** Verifies that output directories of the given project and all of its dependencies are
- * all different. No verification is done if the project overrides
- * 'shouldCheckOutputDirectories' to be false. The 'Project.outputDirectories' method is
- * used to determine a project's output directories. */
- private def checkOutputDirectories(result: LoadResult): LoadResult =
- result match
- {
- case success: LoadSuccess =>
- if(success.project.shouldCheckOutputDirectories)
- checkOutputDirectoriesImpl(success.project)
- else
- success
- case x => x
- }
- /** Verifies that output directories of the given project and all of its dependencies are
- * all different. The 'Project.outputDirectories' method is used to determine a project's
- * output directories. */
- private def checkOutputDirectoriesImpl(project: Project): LoadResult =
- {
- val projects = project.projectClosure
- import scala.collection.mutable.{HashMap, HashSet, Set}
- val outputDirectories = new HashMap[Path, Set[Project]]
- for(p <- projects; path <- p.outputDirectories)
- outputDirectories.getOrElseUpdate(path, new HashSet[Project]) += p
- val shared = outputDirectories.filter(_._2.size > 1)
- if(shared.isEmpty)
- new LoadSuccess(project)
- else
- {
- val sharedString =
- {
- val s =
- for((path, projectsSharingPath) <- shared) yield
- projectsSharingPath.map(_.name).mkString(", ") + " share " + path
- s.mkString("\n\t")
- }
- new LoadError("The same directory is used for output for multiple projects:\n\t" + sharedString +
- "\n (If this is intentional, use 'override def shouldCheckOutputDirectories = false' in your project definition.)")
- }
- }
- import scala.reflect.Manifest
- private[sbt] def getProjectClass[P <: Project](name: String, classpath: PathFinder, additional: ClassLoader)(implicit mf: Manifest[P]): Class[P] =
- {
- val loader =ClasspathUtilities.toLoader(classpath, additional)
- val builderClass = Class.forName(name, false, loader)
- val projectClass = mf.erasure
- require(projectClass.isAssignableFrom(builderClass), "Builder class '" + builderClass + "' does not extend " + projectClass.getName + ".")
- builderClass.asSubclass(projectClass).asInstanceOf[Class[P]]
- }
-
- /** Writes the project name and a separator to the project's log at the info level.*/
- def showProjectHeader(project: Project)
- {
- val projectHeader = "Project " + project.name
- project.log.info("")
- project.log.info(projectHeader)
- project.log.info("=" * projectHeader.length)
- }
-
- def rootProject(p: Project): Project =
- p.info.parent match
- {
- case Some(parent) => rootProject(parent)
- case None => p
- }
-}
diff --git a/sbt_pending/src/main/scala/sbt/ProjectConsole.scala b/sbt_pending/src/main/scala/sbt/ProjectConsole.scala
deleted file mode 100644
index 1462e7396..000000000
--- a/sbt_pending/src/main/scala/sbt/ProjectConsole.scala
+++ /dev/null
@@ -1,79 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package sbt
-
-import scala.tools.nsc.{GenericRunnerCommand, Interpreter, InterpreterLoop, ObjectRunner, Settings}
-import scala.tools.nsc.interpreter.InteractiveReader
-import scala.tools.nsc.reporters.Reporter
-import scala.tools.nsc.util.ClassPath
-
-/** This module is an interface to starting the scala interpreter or runner.*/
-object ProjectConsole
-{
- /** Create a settings object and execute the provided function if the settings are created ok.*/
- private def createSettings(log: Logger)(f: Settings => Option[String]) =
- {
- val command = new GenericRunnerCommand(Nil, message => log.error(message))
- if(command.ok)
- f(command.settings)
- else
- Some(command.usageMsg)
- }
-
- /** Starts a Scala interpreter session with 'project' bound to the value 'current' in the console
- * and the following two lines executed:
- * import sbt._
- * import current._
- */
- def apply(project: Project): Option[String] =
- {
- import project.log
- createSettings(log) { interpreterSettings =>
- createSettings(log) { compilerSettings =>
- log.info("Starting scala interpreter with project definition " + project.name + " ...")
- log.info("")
- Control.trapUnit("Error during session: ", log)
- {
- JLine.withJLine {
- val loop = new ProjectInterpreterLoop(compilerSettings, project)
- executeTrapExit(loop.main(interpreterSettings), log)
- }
- }
- }}
- }
- /** A custom InterpreterLoop with the purpose of creating an interpreter with Project 'project' bound to the value 'current',
- * and the following three lines interpreted:
- * import sbt._
- * import Process._
- * import current._.
- * To do this,
- * 1) The compiler uses a different settings instance: 'compilerSettings', which will have its classpath set to include
- * the Scala compiler and library jars and the classpath used to compile the project.
- * 2) The parent class loader for the interpreter is the loader that loaded the project, so that the project can be bound to a variable
- * in the interpreter.
- */
- private class ProjectInterpreterLoop(compilerSettings: Settings, project: Project) extends InterpreterLoop
- {
- override def createInterpreter()
- {
- val projectLoader = project.getClass.getClassLoader
- val classpath = Project.getProjectClasspath(project)
- val fullClasspath = classpath.get ++ Path.fromFiles(project.info.app.scalaProvider.jars)
- compilerSettings.classpath.value = Path.makeString(fullClasspath)
- project.log.debug(" console-project classpath:\n\t" + fullClasspath.mkString("\n\t"))
-
- in = InteractiveReader.createDefault()
- interpreter = new Interpreter(settings)
- {
- override protected def parentClassLoader = projectLoader
- override protected def newCompiler(settings: Settings, reporter: Reporter) = super.newCompiler(compilerSettings, reporter)
- }
- interpreter.setContextClassLoader()
- interpreter.bind("current", project.getClass.getName, project)
- interpreter.interpret("import sbt._")
- interpreter.interpret("import Process._")
- interpreter.interpret("import current._")
- }
- }
-}
diff --git a/sbt_pending/src/main/scala/sbt/ProjectInfo.scala b/sbt_pending/src/main/scala/sbt/ProjectInfo.scala
deleted file mode 100644
index f2c889dbf..000000000
--- a/sbt_pending/src/main/scala/sbt/ProjectInfo.scala
+++ /dev/null
@@ -1,140 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008 Mark Harrah
- */
-package sbt
-
-import java.io.File
-import xsbti.{AppProvider, ScalaProvider}
-import FileUtilities._
-
-/** Represents the minimal information necessary to construct a Project.
-*
-* `projectDirectory` is the base directory for the project (not the root project directory)
-* `dependencies` are the Projects that this Project depends on.
-* `parent` is the parent Project, or None if this is the root project.
-* `log` is the Logger to use as a base for the default project Logger.
-* `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(projectDirectory: File, dependencies: Iterable[Project], parent: Option[Project])
- (log: Logger, val app: AppProvider, val buildScalaVersion: Option[String]) extends NotNull
-{
- /** The version of Scala running sbt.*/
- def definitionScalaVersion = app.scalaProvider.version
- /** The launcher instance that booted sbt.*/
- def launcher = app.scalaProvider.launcher
-
- val logger = log
- /** The base path for the project, preserving information to the root project directory.*/
- val projectPath: Path =
- {
- val toRoot = parent.flatMap(p => Path.relativize(p.info.projectPath, projectDirectory))
- new ProjectDirectory(projectDirectory, toRoot)
- }
- /** The path to build information. The current location is `project/`.
- * Note: The directory used to be `metadata/`, hence the name of the constant in the implementation.
- * Note 2: Although it is called builderPath, it is not the path to the builder definition, which is `builderProjectPath`*/
- val builderPath = projectPath / ProjectInfo.MetadataDirectoryName
- /** The boot directory contains the jars needed for building the project, including Scala, sbt, processors and dependencies of these.*/
- def bootPath = builderPath / Project.BootDirectoryName
- /** The path to the build definition project.
- * Currently, this is 'project/build'. */
- def builderProjectPath = builderPath / Project.BuilderProjectDirectoryName
- def builderProjectOutputPath = builderProjectPath / Project.DefaultOutputDirectoryName
- /** The path to the plugin definition project. This declares the plugins to use for the build definition.*/
- def pluginsPath = builderPath / Project.PluginProjectDirectoryName
- def pluginsOutputPath = pluginsPath / Project.DefaultOutputDirectoryName
- /** The path to which the source code for plugins are extracted.*/
- def pluginsManagedSourcePath = pluginsPath / BasicDependencyPaths.DefaultManagedSourceDirectoryName
- /** The path to which plugins are retrieved.*/
- def pluginsManagedDependencyPath = pluginsPath / BasicDependencyPaths.DefaultManagedDirectoryName
-
- /** The classpath containing all jars comprising sbt, except for the launcher.*/
- def sbtClasspath = Path.finder(app.mainClasspath)
-}
-
-private[sbt] sealed trait SetupResult extends NotNull
-private[sbt] final object SetupDeclined extends SetupResult
-private[sbt] final class SetupError(val message: String) extends SetupResult
-private[sbt] final object AlreadySetup extends SetupResult
-private[sbt] final class SetupInfo(val name: String, val version: Option[Version], val organization: Option[String], val initializeDirectories: Boolean) extends SetupResult
-
-object ProjectInfo
-{
- val MetadataDirectoryName = "project"
- private val DefaultOrganization = "empty"
-
- def setup(info: ProjectInfo, log: Logger): SetupResult =
- {
- val builderDirectory = info.builderPath.asFile
- if(builderDirectory.exists)
- {
- if(builderDirectory.isDirectory)
- AlreadySetup
- else
- new SetupError("'" + builderDirectory.getAbsolutePath + "' is not a directory.")
- }
- else
- setupProject(info.projectDirectory, log)
- }
- private def setupProject(projectDirectory: File, log: Logger): SetupResult =
- {
- if(confirmPrompt("No project found. Create new project?", false))
- {
- val name = trim(SimpleReader.readLine("Project Name: "))
- if(name.isEmpty)
- new SetupError("Project not created: no name specified.")
- else
- {
- val organization =
- {
- val org = trim(SimpleReader.readLine("Organization [" + DefaultOrganization + "]: "))
- if(org.isEmpty)
- DefaultOrganization
- else
- org
- }
- readVersion(projectDirectory, log) match
- {
- case None => new SetupError("Project not created: no version specified.")
- case Some(version) =>
- if(verifyCreateProject(name, version, organization))
- new SetupInfo(name, Some(version), Some(organization), true)
- else
- SetupDeclined
- }
- }
- }
- else
- SetupDeclined
- }
- private def verifyCreateProject(name: String, version: Version, organization: String): Boolean =
- confirmPrompt("Create new project " + name + " " + version + " with organization " + organization +" ?", true)
-
- private def confirmPrompt(question: String, defaultYes: Boolean) =
- {
- val choices = if(defaultYes) " (Y/n) " else " (y/N) "
- val answer = trim(SimpleReader.readLine(question + choices))
- val yes = "y" :: "yes" :: (if(defaultYes) List("") else Nil)
- yes.contains(answer.toLowerCase)
- }
-
- private def readVersion(projectDirectory: File, log: Logger): Option[Version] =
- {
- val version = trim(SimpleReader.readLine("Version: "))
- if(version.isEmpty)
- None
- else
- {
- Version.fromString(version) match
- {
- case Left(errorMessage) =>
- {
- log.error("Invalid version: " + errorMessage)
- readVersion(projectDirectory, log)
- }
- case Right(v) => Some(v)
- }
- }
- }
- private def trim(s: Option[String]) = s.getOrElse("")
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/ProjectPaths.scala b/sbt_pending/src/main/scala/sbt/ProjectPaths.scala
deleted file mode 100644
index 2752b7008..000000000
--- a/sbt_pending/src/main/scala/sbt/ProjectPaths.scala
+++ /dev/null
@@ -1,302 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008, 2009 Mark Harrah
- */
-package sbt
-
-trait PackagePaths extends NotNull
-{
- def jarPath: Path
- def packageTestJar: Path
- def packageDocsJar: Path
- def packageSrcJar: Path
- def packageTestSrcJar: Path
- def packageProjectZip: Path
-}
-/** These are the paths required by BasicScalaProject.*/
-trait ScalaPaths extends PackagePaths
-{
- /** A PathFinder that selects all main sources.*/
- def mainSources: PathFinder
- /** A PathFinder that selects all test sources.*/
- def testSources: PathFinder
- def mainSourceRoots: PathFinder
- def testSourceRoots: PathFinder
- /** A PathFinder that selects all main resources.*/
- def mainResources: PathFinder
- /** A PathFinder that selects all test resources. */
- def testResources: PathFinder
-
- def mainCompilePath: Path
- def testCompilePath: Path
- def mainAnalysisPath: Path
- def testAnalysisPath: Path
- def mainDocPath: Path
- def testDocPath: Path
- def graphSourcesPath: Path
- def graphPackagesPath: Path
- def mainResourcesOutputPath: Path
- def testResourcesOutputPath: Path
-
- /** A PathFinder that selects all the classes compiled from the main sources.*/
- def mainClasses: PathFinder
- /** A PathFinder that selects all the classes compiled from the test sources.*/
- def testClasses: PathFinder
-
- /** Declares all paths to be packaged by the package action.*/
- def packagePaths: PathFinder
- /** Declares all paths to be packaged by the package-test action.*/
- def packageTestPaths: PathFinder
- /** Declares all sources to be packaged by the package-src action.*/
- def packageSourcePaths: PathFinder
- /** Declares all sources to be packaged by the package-test-src action.*/
- def packageTestSourcePaths: PathFinder
- /** Declares all paths to be packaged by the package-project action.*/
- def packageProjectPaths: PathFinder
-
- /** These are the directories that are created when a user makes a new project from sbt.*/
- protected def directoriesToCreate: List[Path]
- /** The directories to which a project writes are listed here and is used
- * to check a project and its dependencies for collisions.*/
- def outputDirectories: Iterable[Path]
-
- def artifactBaseName: String
-}
-
-trait BasicScalaPaths extends Project with ScalaPaths
-{
- def mainResourcesPath: PathFinder
- def testResourcesPath: PathFinder
- def managedDependencyPath: Path
- def managedDependencyRootPath: Path
- def dependencyPath: Path
-
- protected def sources(base: PathFinder) = descendents(base, sourceExtensions)
- protected def sourceExtensions = "*.scala" | "*.java"
-
- def mainSources =
- {
- val normal = sources(mainSourceRoots)
- if(scratch)
- normal +++ (info.projectPath * sourceExtensions)
- else
- normal
- }
- def testSources = sources(testSourceRoots)
-
- def mainResources = descendents(mainResourcesPath ###, "*")
- def testResources = descendents(testResourcesPath ###, "*")
-
- def mainClasses = (mainCompilePath ###) ** "*.class"
- def testClasses = (testCompilePath ###) ** "*.class"
-
- def packagePaths = mainClasses +++ mainResources
- def packageTestPaths = testClasses +++ testResources
- def packageSourcePaths = mainSources +++ mainResources
- def packageTestSourcePaths = testSources +++ testResources
- def packageProjectPaths = descendents( (info.projectPath ###), "*") --- (packageProjectExcludes ** "*")
- protected def packageProjectExcludes: PathFinder =
- outputRootPath +++ managedDependencyRootPath +++
- info.bootPath +++ info.builderProjectOutputPath +++
- info.pluginsOutputPath +++ info.pluginsManagedSourcePath +++ info.pluginsManagedDependencyPath
-
- override def outputDirectories = outputPath :: managedDependencyPath :: Nil
-}
-
-trait MavenStyleScalaPaths extends BasicScalaPaths with BasicPackagePaths
-{
- import BasicProjectPaths._
-
- def outputPath: Path
-
- def sourceDirectoryName = DefaultSourceDirectoryName
- def mainDirectoryName = DefaultMainDirectoryName
- def scalaDirectoryName = DefaultScalaDirectoryName
- def javaDirectoryName = DefaultJavaDirectoryName
- def resourcesDirectoryName = DefaultResourcesDirectoryName
- def testDirectoryName = DefaultTestDirectoryName
- def mainCompileDirectoryName = DefaultMainCompileDirectoryName
- def testCompileDirectoryName = DefaultTestCompileDirectoryName
- def docDirectoryName = DefaultDocDirectoryName
- def apiDirectoryName = DefaultAPIDirectoryName
- def graphDirectoryName = DefaultGraphDirectoryName
- def mainAnalysisDirectoryName = DefaultMainAnalysisDirectoryName
- def testAnalysisDirectoryName = DefaultTestAnalysisDirectoryName
- def mainResourcesOutputDirectoryName = DefautMainResourcesOutputDirectoryName
- def testResourcesOutputDirectoryName = DefautTestResourcesOutputDirectoryName
-
- def sourcePath = path(sourceDirectoryName)
-
- def mainSourcePath = sourcePath / mainDirectoryName
- def mainScalaSourcePath = mainSourcePath / scalaDirectoryName
- def mainJavaSourcePath = mainSourcePath / javaDirectoryName
- def mainResourcesPath = mainSourcePath / resourcesDirectoryName
- def mainDocPath = docPath / mainDirectoryName / apiDirectoryName
- def mainCompilePath = outputPath / mainCompileDirectoryName
- def mainResourcesOutputPath = outputPath / mainResourcesOutputDirectoryName
- def mainAnalysisPath = outputPath / mainAnalysisDirectoryName
-
- def testSourcePath = sourcePath / testDirectoryName
- def testJavaSourcePath = testSourcePath / javaDirectoryName
- def testScalaSourcePath = testSourcePath / scalaDirectoryName
- def testResourcesPath = testSourcePath / resourcesDirectoryName
- def testDocPath = docPath / testDirectoryName / apiDirectoryName
- def testCompilePath = outputPath / testCompileDirectoryName
- def testResourcesOutputPath = outputPath / testResourcesOutputDirectoryName
- def testAnalysisPath = outputPath / testAnalysisDirectoryName
-
- def docPath = outputPath / docDirectoryName
- def graphPath = outputPath / graphDirectoryName
- def graphPackagesPath = graphPath / "packages"
- def graphSourcesPath = graphPath / "sources"
-
- /** These are the directories that are created when a user makes a new project from sbt.*/
- protected def directoriesToCreate: List[Path] =
- dependencyPath ::
- mainScalaSourcePath ::
- mainResourcesPath ::
- testScalaSourcePath ::
- testResourcesPath ::
- Nil
-
- def mainSourceRoots = (mainJavaSourcePath###) +++ (mainScalaSourcePath##)
- def testSourceRoots = (testJavaSourcePath###) +++ (testScalaSourcePath##)
-}
-
-trait BasicPackagePaths extends ScalaPaths with PackagePaths
-{
- def outputPath: Path
-
- def defaultJarBaseName: String = artifactBaseName
- def defaultJarName = defaultJarBaseName + ".jar"
- def jarPath = outputPath / defaultJarName
- def packageTestJar = defaultJarPath("-test.jar")
- def packageDocsJar = defaultJarPath("-docs.jar")
- def packageSrcJar= defaultJarPath("-src.jar")
- def packageTestSrcJar = defaultJarPath("-test-src.jar")
- def packageProjectZip = defaultJarPath("-project.zip")
- def defaultJarPath(extension: String) = outputPath / (artifactBaseName + extension)
-}
-
-object BasicProjectPaths
-{
- val DefaultSourceDirectoryName = "src"
- val DefaultMainCompileDirectoryName = "classes"
- val DefaultTestCompileDirectoryName = "test-classes"
- val DefaultDocDirectoryName = "doc"
- val DefaultAPIDirectoryName = "api"
- val DefaultGraphDirectoryName = "graph"
- val DefaultMainAnalysisDirectoryName = "analysis"
- val DefaultTestAnalysisDirectoryName = "test-analysis"
- val DefautMainResourcesOutputDirectoryName = "resources"
- val DefautTestResourcesOutputDirectoryName = "test-resources"
-
- val DefaultMainDirectoryName = "main"
- val DefaultScalaDirectoryName = "scala"
- val DefaultJavaDirectoryName = "java"
- val DefaultResourcesDirectoryName = "resources"
- val DefaultTestDirectoryName = "test"
-}
-
-trait WebScalaPaths extends ScalaPaths
-{
- def temporaryWarPath: Path
- def webappResources: PathFinder
- def jettyContextPath: String
- def warPath: Path
-}
-trait MavenStyleWebScalaPaths extends WebScalaPaths with MavenStyleScalaPaths
-{
- import WebProjectPaths._
- def temporaryWarPath = outputPath / webappDirectoryName
- def webappPath = mainSourcePath / webappDirectoryName
- def webappDirectoryName = DefaultWebappDirectoryName
- def jettyContextPath = DefaultJettyContextPath
- def defaultWarName = defaultJarBaseName + ".war"
- def warPath = outputPath / defaultWarName
- /** Additional files to include in the web application. */
- protected def extraWebappFiles: PathFinder = Path.emptyPathFinder
- def webappResources = descendents(webappPath ###, "*") +++ extraWebappFiles
-}
-object WebProjectPaths
-{
- val DefaultWebappDirectoryName = "webapp"
- val DefaultJettyContextPath = "/"
-}
-
-/** Defines default paths for a webstart project. It directly extends WebstartOptions to make
-* it easy to implement and override webstart options in the common case of one webstartTask per
-* project.*/
-trait WebstartPaths extends ScalaPaths
-{
- import WebstartPaths._
-
- def outputPath: Path
- def jnlpPath: Path
-
- def webstartOutputDirectory = outputPath / webstartDirectoryName
-
- def jnlpFile = webstartOutputDirectory / jnlpFileName
- def webstartLibDirectory = webstartOutputDirectory / webstartLibName
- def webstartZip: Option[Path] = Some(outputPath / webstartZipName)
- def jnlpResourcesPath = jnlpPath / BasicProjectPaths.DefaultResourcesDirectoryName
-
- def webstartLibName = DefaultWebstartLibName
- def webstartDirectoryName = DefaultWebstartDirectoryName
-
- def webstartZipName: String
- def jnlpFileName: String
-}
-object WebstartPaths
-{
- val DefaultWebstartDirectoryName = "webstart"
- val DefaultJnlpName = "jnlp"
- val DefaultWebstartLibName = "lib"
-}
-trait MavenStyleWebstartPaths extends WebstartPaths with MavenStyleScalaPaths
-{
- import WebstartPaths._
- def jnlpPath = mainSourcePath / DefaultJnlpName
- def webstartMainJar = jarPath
- def jnlpFileName = DefaultJnlpFileName
- def webstartZipName = artifactBaseName + ".zip"
- def DefaultJnlpFileName = artifactBaseName + ".jnlp"
-}
-
-trait IntegrationTestPaths extends NotNull
-{
- def integrationTestSources: PathFinder
- def integrationTestScalaSourceRoots: PathFinder
- def integrationTestResourcesPath: Path
-
- def integrationTestCompilePath: Path
- def integrationTestAnalysisPath: Path
-}
-trait BasicIntegrationTestPaths extends IntegrationTestPaths
-{
- def integrationTestScalaSourcePath: Path
- def integrationTestScalaSourceRoots: PathFinder = integrationTestScalaSourcePath
- def integrationTestSources = sources(integrationTestScalaSourceRoots)
- protected def sources(base: PathFinder): PathFinder
-}
-trait MavenStyleIntegrationTestPaths extends BasicIntegrationTestPaths with MavenStyleScalaPaths
-{
- import IntegrationTestPaths._
-
- def integrationTestDirectoryName = DefaultIntegrationTestDirectoryName
- def integrationTestCompileDirectoryName = DefaultIntegrationTestCompileDirectoryName
- def integrationTestAnalysisDirectoryName = DefaultIntegrationTestAnalysisDirectoryName
-
- def integrationTestSourcePath = sourcePath / integrationTestDirectoryName
- def integrationTestScalaSourcePath = integrationTestSourcePath / scalaDirectoryName
- def integrationTestResourcesPath = integrationTestSourcePath / resourcesDirectoryName
-
- def integrationTestCompilePath = outputPath / integrationTestCompileDirectoryName
- def integrationTestAnalysisPath = outputPath / integrationTestAnalysisDirectoryName
-}
-
-object IntegrationTestPaths
-{
- val DefaultIntegrationTestDirectoryName = "it"
- val DefaultIntegrationTestCompileDirectoryName = "it-classes"
- val DefaultIntegrationTestAnalysisDirectoryName = "it-analysis"
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/TaskManager.scala b/sbt_pending/src/main/scala/sbt/TaskManager.scala
deleted file mode 100644
index 67ba599b2..000000000
--- a/sbt_pending/src/main/scala/sbt/TaskManager.scala
+++ /dev/null
@@ -1,104 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2008 David MacIver, Mark Harrah
- */
-package sbt
-
-import TaskManager._
-
-trait Described extends NotNull
-{
- def description: Option[String]
-}
-trait TaskManager{
- type ManagerType >: this.type <: TaskManager
- type ManagedTask >: Task <: TaskManager#Task with Dag[ManagedTask]
- /** Creates a task that executes the given action when invoked.*/
- def task(action : => Option[String]) = new Task(None, Nil, false, action)
- /** An interactive task is one that is not executed across all dependent projects when
- * it is called directly. The dependencies of the task are still invoked across all dependent
- * projects, however. */
- def interactiveTask(action: => Option[String]) = new Task(None, Nil, true, action)
- /** Creates a method task that executes the given action when invoked. */
- def task(action: Array[String] => ManagedTask) = new MethodTask(None, action, Nil)
-
- def taskName(t: Task): Option[String]
- final def taskNameString(task: Task): String = taskName(task).getOrElse(UnnamedName)
-
- /** A method task is an action that has parameters. Note that it is not a Task, though,
- * because it requires arguments to perform its work. It therefore cannot be a dependency of
- * a Task..*/
- final class MethodTask(val description: Option[String], action: Array[String] => ManagedTask, getCompletions: => Seq[String]) extends Described
- {
- /** Creates a new method task, identical to this method task, except with thE[String]e given description.*/
- def describedAs(description : String) = new MethodTask(Some(description), action, getCompletions)
- /** Invokes this method task with the given arguments.*/
- def apply(arguments: Array[String]) = action(arguments)
- def manager: ManagerType = TaskManager.this
- def completeWith(add: => Seq[String]) = new MethodTask(description, action, add)
- def completions = getCompletions
- }
-
- sealed class Task(val explicitName: Option[String], val description : Option[String], val dependencies : List[ManagedTask],
- val interactive: Boolean, action : => Option[String]) extends Dag[ManagedTask] with Described
- {
- def this(description : Option[String], dependencies : List[ManagedTask], interactive: Boolean, action : => Option[String]) =
- this(None, description, dependencies, interactive, action)
- checkTaskDependencies(dependencies)
- def manager: ManagerType = TaskManager.this
- def name = explicitName.getOrElse(taskNameString(this))
- private[sbt] def implicitName = taskName(this)
- def named(name: String) = construct(Some(name), description,dependencies, interactive, action)
- override def toString = "Task " + name
-
- /** Creates a new task, identical to this task, except with the additional dependencies specified.*/
- def dependsOn(tasks : ManagedTask*) = setDependencies(tasks.toList ::: dependencies)
- private[sbt] def setDependencies(dependencyList: List[ManagedTask]) =
- {
- checkTaskDependencies(dependencyList)
- construct(explicitName, description, dependencyList, interactive, action)
- }
- /** Creates a new task, identical to this task, except with the given description.*/
- def describedAs(description : String) = construct(explicitName, Some(description), dependencies, interactive, action);
- private[sbt] def invoke = action;
-
- final def setInteractive = construct(explicitName, description, dependencies, true, action)
- final def run = runSequentially(topologicalSort)
- final def runDependenciesOnly = runSequentially(topologicalSort.dropRight(1))
- private def runSequentially(tasks: List[ManagedTask]) = Control.lazyFold(tasks)(_.invoke)
-
- def &&(that : Task) =
- construct(explicitName, None, dependencies ::: that.dependencies, interactive || that.interactive, this.invoke.orElse(that.invoke))
-
- protected def construct(explicitName: Option[String], description: Option[String], dependencies: List[ManagedTask], interactive: Boolean,
- action : => Option[String]): Task = new Task(explicitName, description, dependencies, interactive, action)
- }
- final class CompoundTask private (explicitName: Option[String], description : Option[String], dependencies : List[ManagedTask], interactive: Boolean,
- action : => Option[String], createWork: => SubWork[Project#Task]) extends Task(description, dependencies, interactive, action)
- with CompoundWork[Project#Task]
- {
- def this(createWork: => SubWork[Project#Task]) = this(None, None, Nil, false, None, createWork)
- override protected def construct(explicitName: Option[String], description: Option[String], dependencies: List[ManagedTask],
- interactive: Boolean, action : => Option[String]) = new CompoundTask(explicitName, description, dependencies, interactive, action, createWork)
- def work = createWork
- }
- def dynamic(createTask: => Project#Task) = new CompoundTask(SubWork[Project#Task](checkDynamic(createTask)))
- /** Verifies that the given dynamically created task does not depend on any statically defined tasks.
- * Returns the task if it is valid.*/
- private def checkDynamic(task: Project#Task) =
- {
- for(t <- task.topologicalSort if !(t eq task); staticName <- t.implicitName)
- error("Dynamic task " + task.name + " depends on static task " + staticName)
- task
- }
- private def checkTaskDependencies(dependencyList: List[ManagedTask])
- {
- val nullDependencyIndex = dependencyList.findIndexOf(_ == null)
- require(nullDependencyIndex < 0, "Dependency (at index " + nullDependencyIndex + ") is null. This may be an initialization issue or a circular dependency.")
- val interactiveDependencyIndex = dependencyList.findIndexOf(_.interactive)
- require(interactiveDependencyIndex < 0, "Dependency (at index " + interactiveDependencyIndex + ") is interactive. Interactive tasks cannot be dependencies.")
- }
-}
-object TaskManager
-{
- val UnnamedName = ""
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/impl/CommandParser.scala b/sbt_pending/src/main/scala/sbt/impl/CommandParser.scala
deleted file mode 100644
index a2fab873d..000000000
--- a/sbt_pending/src/main/scala/sbt/impl/CommandParser.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Mark Harrah
- */
-package sbt.impl
-
-import scala.util.parsing.combinator.Parsers
-import scala.util.parsing.input.CharSequenceReader
-import scala.util.parsing.input.CharArrayReader.EofCh
-
-/** Parses a command of the form:
-* identifier argument*
-* where argument may be quoted to include spaces and
-* quotes and backslashes should be escaped.
-*/
-object Arguments
-{
- def apply(commandString: String): Either[String, (String, List[String])] =
- CommandParser.parse(commandString)
-}
-
-/* Most of the complexity is for error handling.*/
-private[sbt] object CommandParser extends Parsers
-{
- type Elem = Char
- def parse(commandString: String): Either[String, (String, List[String])] =
- {
- command(new CharSequenceReader(commandString.trim, 0)) match
- {
- case Success(id ~ args, next) => Right((id, args))
- case err: NoSuccess =>
- {
- val pos = err.next.pos
- Left("Could not parse command: (" + pos.line + "," + pos.column + "): " + err.msg)
- }
- }
- }
- def command = phrase(identifier ~! (argument*))
- def identifier = unquoted | err("Expected identifier")
- def argument = ( (whitespaceChar+) ~> (unquoted | quoted) )
-
- def unquoted: Parser[String] = ((unquotedChar ~! (unquotedMainChar*)) ^^ { case a ~ tail => (a :: tail).mkString("") })
- def quoted: Parser[String] = quote ~> quotedChars <~ (quote | err("Missing closing quote character"))
-
- def quotedChars: Parser[String] = (escape | nonescapeChar)*
- def escape: Parser[Char] = backslash ~> (escapeChar | err("Illegal escape"))
- def escapeChar: Parser[Char] = quote | backslash
- def nonescapeChar: Parser[Char] = elem("", ch => !isEscapeChar(ch) && ch != EofCh)
- def unquotedChar: Parser[Char] = elem("", ch => !isEscapeChar(ch) && !Character.isWhitespace(ch) && ch != EofCh)
- def unquotedMainChar: Parser[Char] = unquotedChar | (errorIfEscape ~> failure(""))
-
- private def errorIfEscape = (not(quote) | err("Unexpected quote character")) ~>
- (not(backslash) | err("Escape sequences can only occur in a quoted argument"))
-
- private def isEscapeChar(ch: Char) = ch == '\\' || ch == '"'
-
- def quote: Parser[Char] = '"'
- def backslash: Parser[Char] = '\\'
- def whitespaceChar: Parser[Char] = elem("whitespace", ch => Character.isWhitespace(ch))
-
- private implicit def toString(p: Parser[List[Char]]): Parser[String] = p ^^ {_ mkString "" }
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/CommandRunner.scala b/sbt_pending/src/main/scala/sbt/processor/CommandRunner.scala
deleted file mode 100644
index 3428036d9..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/CommandRunner.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-/** Parses and executes a command (connects a parser to a runner). */
-class CommandRunner(parser: CommandParsing, execute: Executing)
-{
- def apply(processorCommand: String): Unit =
- parser.parseCommand(processorCommand) match
- {
- case Left(err) => throw new ProcessorException(err)
- case Right(command) => execute(command)
- }
-}
-object CommandRunner
-{
- /** Convenience method for constructing a CommandRunner with the minimal information required.*/
- def apply(manager: Manager, defParser: DefinitionParser, prefix: String, log: Logger): CommandRunner =
- {
- val parser = new CommandParser(defaultErrorMessage(prefix), defParser)
- val info = new InfoImpl(manager, prefix, parser, System.out.println)
- val execute = new Execute(manager, info, log)
- new CommandRunner(parser, execute)
- }
- def defaultErrorMessage(prefix: String) =
- "Invalid processor command. Run " + prefix + "help to see valid commands."
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/Execute.scala b/sbt_pending/src/main/scala/sbt/processor/Execute.scala
deleted file mode 100644
index 5b86b8564..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/Execute.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-/** Executes a parsed command. */
-class Execute(manager: Manager, info: Info, log: Logger) extends Executing
-{
- def apply(command: Command): Unit =
- command match
- {
- case dr: DefineRepository =>
- manager.defineRepository(dr.repo)
- log.info("Defined new processor repository '" + dr.repo + "'")
- case dp: DefineProcessor =>
- manager.defineProcessor(dp.pdef)
- log.info("Defined new processor '" + dp.pdef + "'")
- case rd: RemoveDefinition =>
- val removed = manager.removeDefinition(rd.label)
- log.info("Removed '" + removed + "'")
- case Help => info.help()
- case Show => info.show()
- }
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/Handler.scala b/sbt_pending/src/main/scala/sbt/processor/Handler.scala
deleted file mode 100644
index fc32fb8d0..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/Handler.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-class Handler(baseProject: Project) extends NotNull
-{
- def unapply(line: String): Option[ParsedProcessor] =
- line.split("""\s+""", 2) match
- {
- case Array(label @ GetProcessor(processor), args @ _*) => Some( new ParsedProcessor(label, processor, args.mkString) )
- case _ => None
- }
- private object GetProcessor
- {
- def unapply(name: String): Option[Processor] =
- manager.processorDefinition(name).flatMap(manager.processor)
- }
-
- def lock = baseProject.info.launcher.globalLock
-
- lazy val scalaVersion = baseProject.defScalaVersion.value
- lazy val base = baseProject.info.bootPath / ("scala-" + scalaVersion) / "sbt-processors"
- lazy val persistBase = Path.userHome / ".ivy2" / "sbt"
-
- def retrieveLockFile = base / lockName
- def persistLockFile = persistBase / lockName
- def lockName = "processors.lock"
- def definitionsFile = persistBase / "processors.properties"
- def files = new ManagerFiles(base.asFile, retrieveLockFile.asFile, definitionsFile.asFile)
-
- lazy val defParser = new DefinitionParser
- lazy val manager = new ManagerImpl(files, scalaVersion, new Persist(lock, persistLockFile.asFile, defParser), baseProject.offline.value, baseProject.log)
-}
-class ParsedProcessor(val label: String, val processor: Processor, val arguments: String) extends NotNull
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/Info.scala b/sbt_pending/src/main/scala/sbt/processor/Info.scala
deleted file mode 100644
index cc84f6e33..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/Info.scala
+++ /dev/null
@@ -1,26 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-class InfoImpl(manager: Manager, prefix: String, parser: CommandParser, print: String => Unit) extends Info
-{
- def show()
- {
- print("Processors:\n\t" + manager.processors.values.mkString("\n\t"))
- print("\nProcessor repositories:\n\t" + manager.repositories.values.mkString("\n\t"))
- }
- def help()
- {
- import parser.{ShowCommand, HelpCommand, ProcessorCommand, RemoveCommand, RepositoryCommand}
- val usage =
- (HelpCommand -> "Display this help message") ::
- (ShowCommand -> "Display defined processors and repositories") ::
- (ProcessorCommand -> "Define 'label' to be the processor with the given ID") ::
- (RepositoryCommand -> "Add a repository for searching for processors") ::
- (RemoveCommand -> "Undefine the repository or processor with the given 'label'") ::
- Nil
-
- print("Processor management commands:\n " + (usage.map{ case (c,d) => prefix + "" + c + " " + d}).mkString("\n "))
- }
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/Loader.scala b/sbt_pending/src/main/scala/sbt/processor/Loader.scala
deleted file mode 100644
index 46f6a9096..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/Loader.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-import java.io.File
-import java.net.{URL, URLClassLoader}
-import xsbt.FileUtilities.read
-import xsbt.OpenResource.urlInputStream
-import xsbt.Paths._
-import xsbt.GlobFilter._
-
-import ProcessorException.error
-
-class Loader extends NotNull
-{
- def classNameResource = "sbt.processor"
- def getProcessor(directory: File): Either[Throwable, Processor] = getProcessor( getLoader(directory) )
- private def getProcessor(loader: ClassLoader): Either[Throwable, Processor] =
- {
- val resource = loader.getResource(classNameResource)
- if(resource eq null) Left(new ProcessorException("Processor existed but did not contain '" + classNameResource + "' descriptor."))
- else loadProcessor(loader, resource)
- }
- private def loadProcessor(loader: ClassLoader, resource : URL): Either[Throwable, Processor] =
- try { Right(loadProcessor(loader, className(resource))) }
- catch { case e: Exception => Left(e) }
-
- private def loadProcessor(loader: ClassLoader, className: String): Processor =
- {
- val processor = Class.forName(className, true, loader).newInstance
- classOf[Processor].cast(processor)
- }
- private def className(resource: URL): String = urlInputStream(resource) { in => read(in).trim }
- private def getLoader(dir: File) =
- {
- val jars = dir ** "*.jar"
- val jarURLs = jars.files.toArray[File].map(_.toURI.toURL)
- new URLClassLoader(jarURLs, getClass.getClassLoader)
- }
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/Manager.scala b/sbt_pending/src/main/scala/sbt/processor/Manager.scala
deleted file mode 100644
index fd46c128e..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/Manager.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-import java.io.File
-import xsbt.Paths._
-import ProcessorException.error
-
-/** Files needed by ManagerImpl.
-* `retrieveBaseDirectory` is the directory that processors are retrieved under.
-* `retrieveLockFile` is used to synchronize access to that directory.
-* `definitionsFile` is the file to save repository and processor definitions to. It is usually per-user instead of per-project.*/
-class ManagerFiles(val retrieveBaseDirectory: File, val retrieveLockFile: File, val definitionsFile: File)
-
-class ManagerImpl(files: ManagerFiles, scalaVersion: String, persist: Persist, localOnly: Boolean, log: Logger) extends Manager
-{
- import files._
-
- def processorDefinition(label: String): Option[ProcessorDefinition] = processors.get(label)
- def processor(pdef: ProcessorDefinition): Option[Processor] =
- {
- def tryProcessor: Either[Throwable, Processor] =
- (new Loader).getProcessor( retrieveDirectory(pdef) )
-
- // try to load the processor. It will succeed here if the processor has already been retrieved
- tryProcessor.left.flatMap { _ =>
- // if it hasn't been retrieved, retrieve the processor and its dependencies
- retrieveProcessor(pdef, localOnly)
- // try to load the processor now that it has been retrieved
- tryProcessor.left.map { // if that fails, log a warning
- case p: ProcessorException => log.warn(p.getMessage)
- case t => log.trace(t); log.warn(t.toString)
- }
- }.right.toOption
- }
- def defineProcessor(p: ProcessorDefinition)
- {
- checkExisting(p)
- retrieveProcessor(p, localOnly)
- add(p)
- }
- def defineRepository(r: RepositoryDefinition)
- {
- checkExisting(r)
- add(r)
- }
- def removeDefinition(label: String): Definition =
- definitions.removeKey(label) match
- {
- case Some(removed) =>
- saveDefinitions()
- removed
- case None => error("Label '" + label + "' not defined.")
- }
-
- private def retrieveProcessor(p: ProcessorDefinition, localOnly: Boolean): Unit =
- {
- val resolvers = repositories.values.toList.map(toResolver)
- val module = p.toModuleID(scalaVersion)
- ( new Retrieve(retrieveDirectory(p), module, persist.lock, retrieveLockFile, resolvers, log) ).retrieve(localOnly)
- }
- private def add(d: Definition)
- {
- definitions(d.label) = d
- saveDefinitions()
- }
-
- private lazy val definitions = loadDefinitions(definitionsFile)
- def repositories = Map() ++ partialMap(definitions) { case (label, d: RepositoryDefinition) => (label, d) }
- def processors = Map() ++ partialMap(definitions) { case (label, p: ProcessorDefinition) => (label, p) }
-
- private def checkExisting(p: Definition): Unit = definitions.get(p.label) map { d => error ("Label '" + p.label + "' already in use: " + d) }
- private def partialMap[T,S](i: Iterable[T])(f: PartialFunction[T,S]) = i.filter(f.isDefinedAt).map(f)
- private def toResolver(repo: RepositoryDefinition): Resolver = new MavenRepository(repo.label, repo.url)
-
- def retrieveDirectory(p: ProcessorDefinition) = retrieveBaseDirectory / p.group / p.module / p.rev
-
- private def saveDefinitions(): Unit = saveDefinitions(definitionsFile)
- private def saveDefinitions(file: File): Unit = persist.save(file)(definitions.values.toList)
- private def loadDefinitions(file: File): scala.collection.mutable.Map[String, Definition] =
- scala.collection.mutable.HashMap( (if(file.exists) rawLoad(file) else Nil) : _*)
- private def rawLoad(file: File): Seq[(String, Definition)] = persist.load(definitionsFile).map { d => (d.label, d) }
-}
\ No newline at end of file
diff --git a/sbt_pending/src/main/scala/sbt/processor/Parser.scala b/sbt_pending/src/main/scala/sbt/processor/Parser.scala
deleted file mode 100644
index 4d379f522..000000000
--- a/sbt_pending/src/main/scala/sbt/processor/Parser.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2010 Mark Harrah
- */
-package sbt.processor
-
-/** Parses commands. `errorMessage` is the String used when a command is invalid.
-* There is no detailed error reporting.
-* Input Strings are assumed to be trimmed.*/
-class CommandParser(errorMessage: String, defParser: DefinitionParsing) extends CommandParsing
-{
- def parseCommand(line: String): Either[String, Command] =
- defParser.parseDefinition(line) match
- {
- case Some(p: ProcessorDefinition) => Right(new DefineProcessor(p))
- case Some(r: RepositoryDefinition) => Right(new DefineRepository(r))
- case None => parseOther(line)
- }
-
- def parseOther(line: String) =
- line match
- {
- case RemoveRegex(label) => Right(new RemoveDefinition(label))
- case HelpCommand | "" => Right(Help)
- case ShowCommand => Right(Show)
- case _ => Left(errorMessage)
- }
-
- val ShowCommand = "show"
- val HelpCommand = "help"
- val ProcessorCommand = "