diff --git a/src/main/scala/sbt/BasicProjectTypes.scala b/src/main/scala/sbt/BasicProjectTypes.scala index bc1644bfa..dc5823a1a 100644 --- a/src/main/scala/sbt/BasicProjectTypes.scala +++ b/src/main/scala/sbt/BasicProjectTypes.scala @@ -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) = { diff --git a/src/main/scala/sbt/BuilderProject.scala b/src/main/scala/sbt/BuilderProject.scala index dff01c173..9545b04bc 100644 --- a/src/main/scala/sbt/BuilderProject.scala +++ b/src/main/scala/sbt/BuilderProject.scala @@ -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 _ */ 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 } \ No newline at end of file diff --git a/src/main/scala/sbt/CompileOptions.scala b/src/main/scala/sbt/CompileOptions.scala new file mode 100644 index 000000000..2c792556f --- /dev/null +++ b/src/main/scala/sbt/CompileOptions.scala @@ -0,0 +1,8 @@ +package sbt + +object CompileOptions +{ + val Deprecation = "-deprecation" + val Unchecked = "-unchecked" + val Verbose = "-verbose" +} \ No newline at end of file diff --git a/src/main/scala/sbt/DefaultProject.scala b/src/main/scala/sbt/DefaultProject.scala index ab854c1dc..ebff0a888 100644 --- a/src/main/scala/sbt/DefaultProject.scala +++ b/src/main/scala/sbt/DefaultProject.scala @@ -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) :: diff --git a/src/main/scala/sbt/Path.scala b/src/main/scala/sbt/Path.scala index 7c9aaa696..9693bfa70 100644 --- a/src/main/scala/sbt/Path.scala +++ b/src/main/scala/sbt/Path.scala @@ -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 get diff --git a/src/main/scala/sbt/Project.scala b/src/main/scala/sbt/Project.scala index 9e7422699..ae2f2abfe 100644 --- a/src/main/scala/sbt/Project.scala +++ b/src/main/scala/sbt/Project.scala @@ -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 } } diff --git a/src/main/scala/sbt/ProjectInfo.scala b/src/main/scala/sbt/ProjectInfo.scala index 9f518a97d..5a59d8111 100644 --- a/src/main/scala/sbt/ProjectInfo.scala +++ b/src/main/scala/sbt/ProjectInfo.scala @@ -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 diff --git a/src/main/scala/sbt/Resources.scala b/src/main/scala/sbt/Resources.scala index 28668ddae..5ea2510f8 100644 --- a/src/main/scala/sbt/Resources.scala +++ b/src/main/scala/sbt/Resources.scala @@ -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) - } } \ No newline at end of file diff --git a/src/main/scala/sbt/ScalaProject.scala b/src/main/scala/sbt/ScalaProject.scala index 4657013e5..bbb3869b4 100644 --- a/src/main/scala/sbt/ScalaProject.scala +++ b/src/main/scala/sbt/ScalaProject.scala @@ -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) diff --git a/src/main/scala/sbt/impl/RunTask.scala b/src/main/scala/sbt/impl/RunTask.scala index 5ce5a6da4..9f1d9a88e 100644 --- a/src/main/scala/sbt/impl/RunTask.scala +++ b/src/main/scala/sbt/impl/RunTask.scala @@ -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) diff --git a/src/sbt-test/web/servlet-direct/src/main/webapp/WEB-INF/web.xml b/src/sbt-test/web/servlet-direct/src/main/webapp/WEB-INF/web.xml index bff12b49b..441ad39bd 100644 --- a/src/sbt-test/web/servlet-direct/src/main/webapp/WEB-INF/web.xml +++ b/src/sbt-test/web/servlet-direct/src/main/webapp/WEB-INF/web.xml @@ -3,7 +3,7 @@ "http://java.sun.com/dtd/web-app_2_3.dtd" > - Archetype Created Web Application + Test Web Application Home