Merge branch 'using-xsbt' of github.com:harrah/sbt into using-xsbt

This commit is contained in:
Mark Harrah 2010-02-06 13:50:36 -05:00
commit 0397a1c450
11 changed files with 46 additions and 114 deletions

View File

@ -225,7 +225,6 @@ trait BasicManagedProject extends ManagedProject with ReflectiveManagedProject w
/** 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
private def isScala27 = buildScalaVersion.startsWith("2.7.")
/** True if the given dependency requires the compatibility test framework. */
private def requiresCompat(m: ModuleID) =
{

View File

@ -13,7 +13,7 @@ sealed abstract class InternalProject extends Project
override final protected def disableCrossPaths = false
override final def shouldCheckOutputDirectories = false
}
private sealed abstract class BasicBuilderProject extends InternalProject with SimpleScalaProject
private sealed abstract class BasicBuilderProject extends InternalProject
{
def sourceFilter = "*.scala" | "*.java"
def jarFilter: NameFilter = "*.jar"
@ -33,13 +33,13 @@ private sealed abstract class BasicBuilderProject extends InternalProject with S
}
def projectClasspath = compilePath +++ libraries +++ sbtJars
def sbtJars = Path.lazyPathFinder { info.app.mainClasspath.map(Path.fromFile) }
def sbtJars = info.sbtClasspath
abstract class BuilderCompileConfiguration extends AbstractCompileConfiguration
{
def projectPath = info.projectPath
def log = BasicBuilderProject.this.log
def options = (Deprecation :: Unchecked :: Nil).map(_.asString)
def options = CompileOptions.Deprecation :: CompileOptions.Unchecked :: Nil
def javaOptions = Nil
def maxErrors = ScalaProject.DefaultMaximumCompileErrors
def compileOrder = CompileOrder.Mixed
@ -111,7 +111,7 @@ private sealed abstract class BasicBuilderProject extends InternalProject with S
override final def methods = Map.empty
}
/** The project definition used to build project definitions. */
private final class BuilderProject(val info: ProjectInfo, val pluginPath: Path, additional: Iterable[Path], rawLogger: Logger) extends BasicBuilderProject
private final class BuilderProject(val info: ProjectInfo, val pluginPath: Path, additional: PathFinder, rawLogger: Logger) extends BasicBuilderProject
{
private lazy val pluginProject =
{
@ -122,7 +122,7 @@ private final class BuilderProject(val info: ProjectInfo, val pluginPath: Path,
}
override def projectClasspath = super.projectClasspath +++
pluginProject.map(_.pluginClasspath).getOrElse(Path.emptyPathFinder) +++
Path.lazyPathFinder{ additional }
additional
def tpe = "project definition"
override def compileTask = super.compileTask dependsOn(pluginProject.map(_.syncPlugins).toList : _*)
@ -210,11 +210,16 @@ class PluginDefinition(val info: ProjectInfo) extends InternalProject with Basic
}
class PluginProject(info: ProjectInfo) extends DefaultProject(info)
{
/* Since plugins are distributed as source, there is no need to append _<scala.version> */
override def moduleID = normalizedName
/* Fix the version used to build to the version currently running sbt. */
override def buildScalaVersion = defScalaVersion.value
override def unmanagedClasspath = super.unmanagedClasspath +++ Path.lazyPathFinder(info.app.mainClasspath.map(Path.fromFile))
/* 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
}

View File

@ -0,0 +1,8 @@
package sbt
object CompileOptions
{
val Deprecation = "-deprecation"
val Unchecked = "-unchecked"
val Verbose = "-verbose"
}

View File

@ -50,8 +50,8 @@ abstract class BasicScalaProject extends ScalaProject with BasicDependencyProjec
def manifestClassPath: Option[String] = None
def dependencies = info.dependencies ++ subProjects.values.toList
val mainCompileConditional = new CompileConditional(mainCompileConfiguration, buildCompiler)
val testCompileConditional = new CompileConditional(testCompileConfiguration, buildCompiler)
lazy val mainCompileConditional = new CompileConditional(mainCompileConfiguration, buildCompiler)
lazy val testCompileConditional = new CompileConditional(testCompileConfiguration, buildCompiler)
def compileOrder = CompileOrder.Mixed
@ -76,8 +76,9 @@ abstract class BasicScalaProject extends ScalaProject with BasicDependencyProjec
/** The options provided to the 'doc' and 'docTest' actions.*/
def documentOptions: Seq[ScaladocOption] =
documentTitle(name + " " + version + " API") ::
windowTitle(name + " " + version + " API") ::
Nil
(if(isScala27) only27Options else Nil)
private def only27Options =
windowTitle(name + " " + version + " API") :: Nil
/** The options provided to the 'test' action..*/
def testOptions: Seq[TestOption] =
TestListeners(testListeners) ::

View File

@ -146,6 +146,7 @@ object Path
{
private[sbt] def addTo(pathSet: Set[Path]) = pathSet ++= paths
}
def finder(files: => Iterable[File]): PathFinder = lazyPathFinder { fromFiles(files) }
/** The separator character of the platform.*/
val sep = java.io.File.separatorChar
@ -223,6 +224,7 @@ object Path
}
def fromFile(file: String): Path = fromFile(new File(file))
def fromFile(file: File): Path = new FilePath(file)
def fromFiles(files: Iterable[File]): Iterable[Path] = files.map(fromFile)
}
/** A path finder constructs a set of paths. The set is evaluated by a call to the <code>get</code>

View File

@ -226,6 +226,7 @@ trait Project extends TaskManager with Dag[Project] with BasicEnvironment
final val buildScalaVersions = propertyOptional[String](defScalaVersion.value, true)
/** The definitive source for the version of Scala being used to *build* the project.*/
def buildScalaVersion = info.buildScalaVersion.getOrElse(crossScalaVersions.first)
private[sbt] def isScala27 = buildScalaVersion.startsWith("2.7.")
def componentManager = new ComponentManager(info.launcher.globalLock, info.app.components, log)
@ -327,24 +328,22 @@ object Project
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 =
loadProject(projectDirectory, deps, parent, getClass.getClassLoader, log, app, buildScalaVersion)
private[sbt] def loadProject(projectDirectory: File, deps: Iterable[Project], parent: Option[Project], additional: ClassLoader, 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, additional, log)
case setup: SetupInfo => loadProject(info, Some(setup), additional, log)
case AlreadySetup => loadProject(info, None, log)
case setup: SetupInfo => loadProject(info, Some(setup), log)
}
}
private def loadProject(info: ProjectInfo, setupInfo: Option[SetupInfo], additional: ClassLoader, log: Logger): LoadResult =
private def loadProject(info: ProjectInfo, setupInfo: Option[SetupInfo], log: Logger): LoadResult =
{
try
{
val result =
for(builderClass <- getProjectDefinition(info, additional, log).right) yield
for(builderClass <- getProjectDefinition(info, log).right) yield
initialize(constructProject(info, builderClass), setupInfo, log)
result.fold(new LoadError(_), new LoadSuccess(_))
}
@ -406,18 +405,18 @@ object Project
}
/** 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, additional: ClassLoader, buildLog: Logger): Either[String, Class[P] forSome { type P <: Project }] =
private def getProjectDefinition(info: ProjectInfo, buildLog: Logger): Either[String, Class[P] forSome { type P <: Project }] =
{
val builderProjectPath = info.builderPath / BuilderProjectDirectoryName
if(builderProjectPath.asFile.isDirectory)
{
val pluginProjectPath = info.builderPath / PluginProjectDirectoryName
val additionalPaths = additional match { case u: URLClassLoader => u.getURLs.map(url => Path.fromFile(FileUtilities.toFile(url))); case _ => Array[Path]() }
val additionalPaths = info.sbtClasspath
val builderInfo = ProjectInfo(builderProjectPath.asFile, Nil, None)(buildLog, info.app, Some(info.definitionScalaVersion))
val builderProject = new BuilderProject(builderInfo, pluginProjectPath, additionalPaths, buildLog)
builderProject.compile.run.toLeft(()).right.flatMap { ignore =>
builderProject.projectDefinition.right.map {
case Some(definition) => getProjectClass[Project](definition, builderProject.projectClasspath, additional)
case Some(definition) => getProjectClass[Project](definition, builderProject.projectClasspath, getClass.getClassLoader)
case None => DefaultBuilderClass
}
}

View File

@ -28,6 +28,8 @@ final case class ProjectInfo(projectDirectory: File, dependencies: Iterable[Proj
def pluginsOutputPath = pluginsPath / Project.DefaultOutputDirectoryName
def pluginsManagedSourcePath = pluginsPath / BasicDependencyPaths.DefaultManagedSourceDirectoryName
def pluginsManagedDependencyPath = pluginsPath / BasicDependencyPaths.DefaultManagedDirectoryName
def sbtClasspath = Path.finder(app.mainClasspath)
}
private[sbt] sealed trait SetupResult extends NotNull

View File

@ -27,11 +27,8 @@ object Resources
private val LoadErrorPrefix = "Error loading initial project: "
}
class Resources(val baseDirectory: File, additional: ClassLoader, app: AppProvider, buildScalaVersion: Option[String])
class Resources(val baseDirectory: File, app: AppProvider, buildScalaVersion: Option[String])
{
def this(baseDirectory: File, provider: AppProvider, buildScalaVersion: Option[String]) =
this(baseDirectory, getClass.getClassLoader, provider, buildScalaVersion)
import Resources._
// The returned directory is not actually read-only, but it should be treated that way
def readOnlyResourceDirectory(group: String, name: String): Either[String, File] =
@ -64,87 +61,4 @@ class Resources(val baseDirectory: File, additional: ClassLoader, app: AppProvid
}
doInTemporaryDirectory(log)(readWrite(readOnly))
}
def withProject[T](projectDirectory: File, log: Logger)(f: Project => WithProjectResult[T]): Either[String, T] =
readWriteResourceDirectory(projectDirectory, log)(withProject(log)(f))
def withProject[T](group: String, name: String, log: Logger)(f: Project => WithProjectResult[T]): Either[String, T] =
readWriteResourceDirectory(group, name, log)(withProject(log)(f))
def withProject[T](log: Logger)(f: Project => WithProjectResult[T])(dir: File): Either[String, T] =
withProject(log, None, new ReloadSuccessExpected(LoadErrorPrefix), dir )(f)
private def withProject[T](log: Logger, previousProject: Option[Project], reload: ReloadProject, dir: File)
(f: Project => WithProjectResult[T]): Either[String, T] =
{
require(previousProject.isDefined || reload != NoReload, "Previous project undefined and reload not requested.")
val loadResult =
if(reload == NoReload && previousProject.isDefined)
Right(previousProject.get)
else
{
val buffered = new BufferedLogger(log)
buffered.setLevel(Level.Debug)
def error(msg: String) =
{
buffered.stopAll()
Left(msg)
}
buffered.recordAll()
resultToEither(Project.loadProject(dir, Nil, None, additional, buffered, app, buildScalaVersion)) match
{
case Left(msg) =>
reload match
{
case ReloadErrorExpected =>
buffered.clearAll()
previousProject.toRight("Initial project load failed.")
case s: ReloadSuccessExpected => error(s.prefixIfError + msg)
case NoReload /* shouldn't happen */=> error(msg)
}
case Right(p) =>
reload match
{
case ReloadErrorExpected => error("Expected project load failure, but it succeeded.")
case _ =>
buffered.clearAll()
Right(p)
}
}
}
loadResult match
{
case Right(project) =>
f(project) match
{
case ContinueResult(newF, newReload) => withProject(log, Some(project), newReload, dir)(newF)
case ValueResult(value) => Right(value)
case err: ErrorResult => error(err.message)
}
case Left(message) => error(message)
}
}
def resultToEither(result: LoadResult): Either[String, Project] =
result match
{
case success: LoadSuccess => Right(success.project)
case err: LoadError => Left(err.message)
case err: LoadSetupError => Left(err.message)
case LoadSetupDeclined => Left("Setup declined")
}
}
sealed trait ReloadProject extends NotNull
final object ReloadErrorExpected extends ReloadProject
final class ReloadSuccessExpected(val prefixIfError: String) extends ReloadProject
final object NoReload extends ReloadProject
sealed trait WithProjectResult[+T] extends NotNull
final case class ContinueResult[T](f: Project => WithProjectResult[T], reload: ReloadProject) extends WithProjectResult[T]
final case class ValueResult[T](value: T) extends WithProjectResult[T]
final class ErrorResult(val message: String) extends WithProjectResult[Nothing]
object ContinueResult
{
def apply[T](f: Project => WithProjectResult[T], prefixIfError: Option[String]) =
{
val reload = prefixIfError match { case None => NoReload; case Some(p) => new ReloadSuccessExpected(p) }
new ContinueResult[T](f, reload)
}
}

View File

@ -19,12 +19,12 @@ trait SimpleScalaProject extends ExecProject
case class CompileOption(val asString: String) extends ActionOption
case class JavaCompileOption(val asString: String) extends ActionOption
val Deprecation = CompileOption("-deprecation")
val Deprecation = CompileOption(CompileOptions.Deprecation)
val ExplainTypes = CompileOption("-explaintypes")
val Optimize = CompileOption("-optimise")
def Optimise = Optimize
val Verbose = CompileOption("-verbose")
val Unchecked = CompileOption("-unchecked")
val Verbose = CompileOption(CompileOptions.Verbose)
val Unchecked = CompileOption(CompileOptions.Unchecked)
val DisableWarnings = CompileOption("-nowarn")
def target(target: Target.Value) = CompileOption("-target:" + target)
object Target extends Enumeration
@ -107,7 +107,7 @@ trait ScalaProject extends SimpleScalaProject with FileTasks with MultiTaskProje
def access(access: Access.Value) = SimpleDocOption("-access:" + access)
def documentBottom(bottomText: String) = CompoundDocOption("-bottom", bottomText)
def documentCharset(charset: String) = CompoundDocOption("-charset", charset)
def documentTitle(title: String) = CompoundDocOption("-doctitle", title)
def documentTitle(title: String) = CompoundDocOption(if(isScala27) "-doctitle" else "-doc-title", title)
def documentFooter(footerText: String) = CompoundDocOption("-footer", footerText)
def documentHeader(headerText: String) = CompoundDocOption("-header", headerText)
def stylesheetFile(path: Path) = CompoundDocOption("-stylesheetfile", path.asFile.getAbsolutePath)

View File

@ -59,6 +59,8 @@ private final class RunTask(root: Task, rootName: String, maximumTasks: Int) ext
else
runTask(action, expandedTaskName(action))
}
private val headerStart = System.getProperty("sbt.start.delimiter", "==")
private val headerEnd = System.getProperty("sbt.end.delimiter", "==")
private def isRoot(t: Task) = t == expandedRoot
/** Will be called in its own thread except for the root task. */
private def runTask(action: Task, actionName: String): Option[String] =
@ -71,10 +73,10 @@ private final class RunTask(root: Task, rootName: String, maximumTasks: Int) ext
banner(ControlEvent.Start, "\n ", "...")
def doRun() =
{
banner(ControlEvent.Header, "\n==", "==")
banner(ControlEvent.Header, "\n" + headerStart, headerStart)
try { action.invoke }
catch { case e: Exception => action.manager.log.trace(e); Some(e.toString) }
finally { banner(ControlEvent.Finish, "==", "==") }
finally { banner(ControlEvent.Finish, headerEnd, headerEnd) }
}
if(buffered)

View File

@ -3,7 +3,7 @@
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<display-name>Test Web Application</display-name>
<servlet>
<servlet-name>Home</servlet-name>