diff --git a/sbt/project/build/ReleaseProject.scala b/sbt/project/build/ReleaseProject.scala
deleted file mode 100644
index d9ad31207..000000000
--- a/sbt/project/build/ReleaseProject.scala
+++ /dev/null
@@ -1,96 +0,0 @@
-/* sbt -- Simple Build Tool
- * Copyright 2009 Mark Harrah
- */
-/*import sbt._
-
-import java.io.File
-
-trait ReleaseProject extends ExecProject
-{ self: SbtProject =>
- def info: ProjectInfo
- lazy val releaseChecks = javaVersionCheck && projectVersionCheck && fullyCheckedOut
- lazy val fullyCheckedOut =
- task
- {
- if(svnArtifactsPath.exists) None
- else Some("You need a fully checked out sbt repository with commit rights to do a release.")
- }
- lazy val javaVersionCheck =
- task
- {
- val javaVersion = System.getProperty("java.version")
- if(!javaVersion.startsWith("1.5."))
- Some("Java version must be 1.5.x (was " + javaVersion + ")")
- else
- None
- }
- lazy val projectVersionCheck =
- task
- {
- def value(a: Option[Int]) = a.getOrElse(0)
- def lessThan(a: Option[Int], b: Option[Int]) = value(a) < value(b)
- version match
- {
- case BasicVersion(major, minor, micro, None) =>
- Version.fromString(sbtVersion.value) match
- {
- case Right(BasicVersion(builderMajor, builderMinor, builderMicro, None))
- if (builderMajor < major || ( builderMajor == major &&
- lessThan(builderMinor, minor) || (builderMinor == minor &&
- lessThan(builderMicro, micro ) ))) =>
- None
- case _ => Some("Invalid builder sbt version. Must be a release version older than the project version. (was: " + sbtVersion.value + ")")
- }
- case _ => Some("Invalid project version. Should be of the form #.#.# (was: " + version + ")")
- }
- }
-
- def svnURL = "https://simple-build-tool.googlecode.com/svn/"
- def latestURL = svnURL + "artifacts/latest"
-
- def svnArtifactsPath = Path.fromFile(info.projectPath.asFile.getParentFile) / "artifacts"
- def svnArtifactPath = svnArtifactsPath / version.toString
- def ivyLocalPath = Path.userHome / ".ivy2" / "local" / "sbt" / "simple-build-tool" / version.toString
- def manualTasks =
- ("Upload launcher jar: " + boot.outputJar.absolutePath) ::
- "Update, build, check and commit Hello Lift example" ::
- Nil
-
- lazy val copyDocs = main.copyTask ( (main.mainDocPath ##) ** "*", svnArtifactPath / "api") dependsOn(main.doc, releaseChecks)
- lazy val copyIvysJars = main.copyTask( (ivyLocalPath ##) ** "*", svnArtifactPath) dependsOn(main.crossPublishLocal, releaseChecks)
-
- lazy val release = manualTaskMessage dependsOn(commitDocs, releaseArtifacts, releaseChecks)
- lazy val releaseArtifacts = nextVersion dependsOn(tag, latestLink, boot.proguard, releaseChecks)
- lazy val manualTaskMessage = task { println("The following tasks must be done manually:\n\t" + manualTasks.mkString("\n\t")); None }
-
- import sbt.ProcessXML._
- lazy val addArtifacts = execTask { svn add {svnArtifactPath} } dependsOn ( copyIvysJars, copyDocs, releaseChecks )
- lazy val commitArtifacts = execTask { svn commit -m "Jars, Ivys, and API Docs for {version.toString}" {svnArtifactPath} } dependsOn(addArtifacts, releaseChecks)
- lazy val tag = execTask { svn copy -m "Tagging {version.toString}" {svnURL}/trunk/ {svnURL}/tags/{version.toString} } dependsOn(releaseChecks)
- lazy val latestLink = (deleteLatestLink && makeLatestLink) dependsOn(commitArtifacts, releaseChecks)
- lazy val makeLatestLink = execTask { svn copy -m "Creating new latest link" {svnURL}/artifacts/{version.toString}/ {latestURL} } dependsOn(releaseChecks)
- lazy val deleteLatestLink = execTask { svn del -m "Deleting old latest link" {latestURL} } dependsOn(releaseChecks)
- lazy val commitProperties = execTask { svn commit -m "Bumping versions" project/build.properties } dependsOn(releaseChecks)
- lazy val commitDocs = execTask { svn commit -m "Updated documentation for {version.toString}" ../wiki/ } dependsOn(releaseChecks)
-
- lazy val nextVersion = (incrementVersions && commitProperties) dependsOn(releaseChecks)
- lazy val incrementVersions = task { incrementVersionNumbers(); None }
- def incrementVersionNumbers(): Unit =
- for( v <- projectVersion)
- {
- sbtVersion() = v.toString
- val incremented = v.asInstanceOf[BasicVersion].incrementMicro // BasicVersion checked by releaseChecks
- import incremented._
- val newVersion = BasicVersion(major, minor, micro, Some("SNAPSHOT"))
- log.info("Changing version to " + newVersion)
- projectVersion() = newVersion
- saveEnvironment
- }
-}
-
-package sbt {
- object ProcessXML {
- implicit def elemToPB(command: scala.xml.Elem): ProcessBuilder =
- impl.CommandParser.parse(command.text.trim).fold(error, Function.tupled(Process.apply))
- }
-}*/
\ No newline at end of file
diff --git a/sbt/src/main/scala/sbt/Logger.scala b/sbt/src/main/scala/sbt/Logger.scala
index b71f4b650..dfd3be94f 100644
--- a/sbt/src/main/scala/sbt/Logger.scala
+++ b/sbt/src/main/scala/sbt/Logger.scala
@@ -137,7 +137,7 @@ final class FilterLogger(delegate: Logger) extends BasicLogger
if(atLevel(Level.Info))
delegate.control(event, message)
}
- def logAll(events: Seq[LogEvent]): Unit = events.foreach(delegate.log)
+ def logAll(events: Seq[LogEvent]): Unit = delegate.logAll(events)
}
/** A logger that can buffer the logging done on it by currently executing Thread and
@@ -354,4 +354,11 @@ object Level extends Enumeration with NotNull
def apply(s: String) = levels.find(s == _.toString)
/** Same as apply, defined for use in pattern matching. */
private[sbt] def unapply(s: String) = apply(s)
+}
+final class LoggerWriter(delegate: Logger, level: Level.Value) extends java.io.Writer
+{
+ override def flush() {}
+ override def close() {}
+ override def write(content: Array[Char], offset: Int, length: Int): Unit =
+ delegate.log(level, new String(content, offset, length))
}
\ No newline at end of file
diff --git a/sbt/src/main/scala/sbt/Path.scala b/sbt/src/main/scala/sbt/Path.scala
index 7a0e4e6b8..12fa4b329 100644
--- a/sbt/src/main/scala/sbt/Path.scala
+++ b/sbt/src/main/scala/sbt/Path.scala
@@ -55,6 +55,19 @@ sealed abstract class Path extends PathFinder with NotNull
def absolutePath: String = asFile.getAbsolutePath
private[sbt] def prependTo(s: String): String
+ /** The last component of this path.*/
+ def name = asFile.getName
+ /** The extension part of the name of this path. This is the part of the name after the last period, or the empty string if there is no period.*/
+ def ext = baseAndExt._2
+ /** The base of the name of this path. This is the part of the name before the last period, or the full name if there is no period.*/
+ def base = baseAndExt._1
+ def baseAndExt: (String, String) =
+ {
+ val nme = name
+ val dot = nme.lastIndexOf('.')
+ if(dot < 0) (nme, "") else (nme.substring(0, dot), nme.substring(dot+1))
+ }
+
/** Equality of Paths is defined in terms of the underlying File.*/
override final def equals(other: Any) =
other match
diff --git a/sbt/src/main/scala/sbt/Project.scala b/sbt/src/main/scala/sbt/Project.scala
index aaf86eec4..39fa9a267 100644
--- a/sbt/src/main/scala/sbt/Project.scala
+++ b/sbt/src/main/scala/sbt/Project.scala
@@ -17,7 +17,7 @@ trait Project extends TaskManager with Dag[Project] with BasicEnvironment
final val log: Logger = logImpl
protected def logImpl: Logger =
{
- val lg = new FilterLogger(new BufferedLogger(info.logger))
+ val lg = new BufferedLogger(new FilterLogger(info.logger))
lg.setLevel(defaultLoggingLevel)
lg
}
@@ -388,6 +388,7 @@ object Project
/** 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) =>
@@ -399,8 +400,7 @@ object Project
p.projectOrganization() = org
if(!setup.initializeDirectories)
p.setEnvironmentModified(false)
- for(errorMessage <- p.saveEnvironment())
- log.error(errorMessage)
+ save()
if(setup.initializeDirectories)
p.initializeDirectories()
}
@@ -409,8 +409,7 @@ object Project
{
p.initializeDirectories()
p.projectInitialize() = false
- for(errorMessage <- p.saveEnvironment())
- log.error(errorMessage)
+ save()
}
}
val useName = p.projectName.get.getOrElse("at " + p.info.projectDirectory.getAbsolutePath)
diff --git a/sbt/src/main/scala/sbt/script/Run.scala b/sbt/src/main/scala/sbt/script/Run.scala
new file mode 100644
index 000000000..7e4281271
--- /dev/null
+++ b/sbt/src/main/scala/sbt/script/Run.scala
@@ -0,0 +1,69 @@
+package sbt.script
+
+ import java.io.PrintWriter
+ import javax.script.{ScriptContext, ScriptEngine, ScriptEngineManager, SimpleScriptContext}
+ import xsbt.OpenResource.fileReader
+ import xsbt.FileUtilities.defaultCharset
+
+object Run
+{
+ def apply(file: Path, project: Project): AnyRef =
+ apply(file, defaultContext(project)_, project)
+ def apply(file: Path, ctx: ScriptContext => Unit, project: Project): AnyRef =
+ apply(file, ctx, defaultLoaders(project))
+ def apply(script: String, language: String, project: Project): AnyRef =
+ apply(script, language, defaultContext(project)_, project)
+ def apply(script: String, language: String, ctx: ScriptContext => Unit, project: Project): AnyRef =
+ apply(script, language, ctx, defaultLoaders(project))
+
+ def apply(file: Path, ctx: ScriptContext => Unit, loaders: Stream[ClassLoader]): AnyRef =
+ {
+ val engine = getEngineByExt(loaders, file.ext)
+ ctx(engine.getContext)
+ apply(file, engine)
+ }
+ def apply(script: String, language: String, ctx: ScriptContext => Unit, loaders: Stream[ClassLoader]): AnyRef =
+ {
+ val engine = getEngineByName(loaders, language)
+ ctx(engine.getContext)
+ engine.eval(script)
+ }
+
+ def defaultContext(project: Project)(ctx: ScriptContext)
+ {
+ ctx.setAttribute("project", project, ScriptContext.ENGINE_SCOPE)
+ // JavaScript implementation in 1.6 depends on this being a PrintWriter
+ ctx.setErrorWriter(new PrintWriter(new LoggerWriter(project.log, Level.Error)))
+ ctx.setWriter(new PrintWriter(new LoggerWriter(project.log, Level.Info)))
+ }
+
+ def apply(file: Path, engine: ScriptEngine): AnyRef =
+ xsbt.OpenResource.fileReader(defaultCharset)(file asFile)( engine.eval )
+
+ def bind(engine: ScriptEngine, bindings: Map[String, AnyRef]): Unit =
+ for( (k, v) <- bindings ) engine.put(k, v)
+
+ def defaultLoaders(project: Project) = Stream(project.getClass.getClassLoader, launcherLoader(project))
+ def launcherLoader(project: Project) = project.info.launcher.topLoader.getParent
+ def defaultBindings(project: Project) = Map("project" -> project)
+
+ def getEngine(loaders: Stream[ClassLoader], get: ScriptEngineManager => ScriptEngine, label: String): ScriptEngine =
+ firstEngine( engines(managers(loaders), get), label)
+
+ def getEngineByName(loaders: Stream[ClassLoader], lang: String): ScriptEngine =
+ getEngine(loaders, _.getEngineByName(lang), "name '" + lang + "'")
+ def getEngineByExt(loaders: Stream[ClassLoader], ext: String): ScriptEngine =
+ getEngine(loaders, _.getEngineByExtension(ext), "extension '" + ext + "'")
+
+ def managers(loaders: Stream[ClassLoader]): Stream[ScriptEngineManager] =
+ loaders.map(new ScriptEngineManager(_))
+ def engines(managers: Stream[ScriptEngineManager], get: ScriptEngineManager => ScriptEngine) =
+ managers.flatMap(getEngine(get))
+ def firstEngine(engines: Stream[ScriptEngine], label: String) =
+ engines.headOption.getOrElse(error("Could not find script engine for " + label))
+ def getEngine(get: ScriptEngineManager => ScriptEngine)(manager: ScriptEngineManager) =
+ {
+ val engine = get(manager)
+ if(engine == null) Nil else engine :: Nil
+ }
+}
\ No newline at end of file
diff --git a/sbt/src/main/scala/sbt/script/Scripts.scala b/sbt/src/main/scala/sbt/script/Scripts.scala
new file mode 100644
index 000000000..da8f43951
--- /dev/null
+++ b/sbt/src/main/scala/sbt/script/Scripts.scala
@@ -0,0 +1,35 @@
+package sbt.script
+
+ import scala.collection.Set
+ import Scripts.{checkName, runScript}
+
+trait Scripts extends Project
+{
+ abstract override def tasks = if(scriptedTasks.isEmpty) super.tasks else Map() ++ super.tasks ++ scriptedTasks
+
+ def scriptSources: PathFinder = info.builderPath / "scripts" * "*.*"
+
+ lazy val scriptedTasks: Map[String, Task] = makeScripted(scriptSources.get)
+
+ def makeScripted(files: Set[Path]): Map[String, Task] = Map() ++ (files map makeScripted)
+ def makeScripted(file: Path): (String, Task) =
+ {
+ val t = scriptedTask(file) named(checkName(file.base))
+ (t.name, t)
+ }
+ def scriptedTask(file: Path): Task = task { runScript(file, this) }
+ def scriptedTask(script: String, language: String): Task = task { runScript(script, language, this) }
+}
+object Scripts
+{
+ def runScript(file: Path, project: Project): Option[String] = getError( Run(file, project) )
+ def runScript(script: String, language: String, project: Project): Option[String] = getError( Run(script, language, project) )
+ def getError(result: AnyRef): Option[String] =
+ result match
+ {
+ case Some(v: String) => Some(v)
+ case _ => None
+ }
+ def checkName(base: String) = base.find(c => !legalID(c)) match { case Some(c) => error("Illegal character in scripted task name '" + base + "': '" + c + "'"); case None => base }
+ def legalID(c: Char) = java.lang.Character.isJavaIdentifierPart(c) || c == '-'
+}