diff --git a/src/main/scala/sbt/Fork.scala b/src/main/scala/sbt/Fork.scala index 278a77843..a095126c0 100644 --- a/src/main/scala/sbt/Fork.scala +++ b/src/main/scala/sbt/Fork.scala @@ -1,13 +1,14 @@ /* sbt -- Simple Build Tool - * Copyright 2009 Mark Harrah + * Copyright 2009 Mark Harrah, Vesa Vilhonen */ package sbt -import java.io.File +import java.io.{File,OutputStream} abstract class ForkJava extends NotNull { def javaHome: Option[File] = None + def outputStrategy: Option[OutputStrategy] = None } abstract class ForkScala extends ForkJava { @@ -18,16 +19,23 @@ trait ForkScalaRun extends ForkScala def workingDirectory: Option[File] = None def runJVMOptions: Seq[String] = Nil } + trait ForkScalaCompiler extends ForkScala { def compileJVMOptions: Seq[String] = Nil } +sealed abstract class OutputStrategy extends NotNull +case object StdoutOutput extends OutputStrategy +case class BufferedOutput(logger: Logger) extends OutputStrategy +case class CustomOutput(output: OutputStream) extends OutputStrategy + import java.lang.{ProcessBuilder => JProcessBuilder} object Fork { private val ScalacMainClass = "scala.tools.nsc.Main" private val ScalaMainClass = "scala.tools.nsc.MainGenericRunner" + val java = new ForkJava("java") val javac = new ForkJava("javac") val scala = new ForkScala(ScalaMainClass) @@ -38,35 +46,35 @@ object Fork val home = javaHome.getOrElse(new File(System.getProperty("java.home"))) new File(new File(home, "bin"), name) } + final class ForkJava(commandName: String) extends NotNull { def apply(javaHome: Option[File], options: Seq[String], log: Logger): Int = - apply(javaHome, options, None, log) - def apply(javaHome: Option[File], options: Seq[String], workingDirectory: File, log: Logger): Int = - apply(javaHome, options, Some(workingDirectory), log) - def apply(javaHome: Option[File], options: Seq[String], workingDirectory: Option[File], log: Logger): Int = - apply(javaHome, options, workingDirectory, Map.empty, log) - /** env is additional environment variables*/ - def apply(javaHome: Option[File], options: Seq[String], workingDirectory: Option[File], env: Map[String, String], log: Logger): Int = + apply(javaHome, options, None, Map.empty, BufferedOutput(log)) + def apply(javaHome: Option[File], options: Seq[String], workingDirectory: Option[File], env: Map[String, String], outputStrategy: OutputStrategy): Int = { val executable = javaCommand(javaHome, commandName).getAbsolutePath val command = (executable :: options.toList).toArray - log.debug("Forking java process: " + command.mkString(" ") + workingDirectory.map("\n\tin " + _.getAbsolutePath).getOrElse("")) val builder = new JProcessBuilder(command : _*) workingDirectory.foreach(wd => builder.directory(wd)) val environment = builder.environment for( (key, value) <- env ) environment.put(key, value) - Process(builder) ! log + outputStrategy match { + case StdoutOutput => Process(builder) ! + case BufferedOutput(logger) => Process(builder) ! logger + case CustomOutput(output) => (Process(builder) #> output).run.exitValue() + } } } + final class ForkScala(mainClassName: String) extends NotNull { def apply(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], log: Logger): Int = - apply(javaHome, jvmOptions, scalaJars, arguments, None, log) - def apply(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], workingDirectory: File, log: Logger): Int = - apply(javaHome, jvmOptions, scalaJars, arguments, Some(workingDirectory), log) + apply(javaHome, jvmOptions, scalaJars, arguments, None, BufferedOutput(log)) def apply(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], workingDirectory: Option[File], log: Logger): Int = + apply(javaHome, jvmOptions, scalaJars, arguments, workingDirectory, BufferedOutput(log)) + def apply(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], workingDirectory: Option[File], outputStrategy: OutputStrategy): Int = { val scalaClasspath = if(scalaJars.isEmpty) @@ -76,7 +84,7 @@ object Fork val scalaClasspathString = "-Xbootclasspath/a:" + scalaClasspath.map(_.getAbsolutePath).mkString(File.pathSeparator) val mainClass = if(mainClassName.isEmpty) Nil else mainClassName :: Nil val options = jvmOptions ++ (scalaClasspathString :: mainClass ::: arguments.toList) - Fork.java(javaHome, options, workingDirectory, log) + Fork.java(javaHome, options, workingDirectory, Map.empty, outputStrategy) } } -} \ No newline at end of file +} diff --git a/src/main/scala/sbt/Run.scala b/src/main/scala/sbt/Run.scala index 370efb667..c2af54046 100644 --- a/src/main/scala/sbt/Run.scala +++ b/src/main/scala/sbt/Run.scala @@ -1,5 +1,5 @@ /* sbt -- Simple Build Tool - * Copyright 2008, 2009 Mark Harrah + * Copyright 2008, 2009 Mark Harrah, Vesa Vilhonen */ package sbt @@ -27,7 +27,10 @@ class ForkRun(config: ForkScalaRun) extends ScalaRun def run(mainClass: String, classpath: Iterable[Path], options: Seq[String], log: Logger): Option[String] = { val scalaOptions = classpathOption(classpath) ::: mainClass :: options.toList - val exitCode = Fork.scala(config.javaHome, config.runJVMOptions, config.scalaJars, scalaOptions, config.workingDirectory, log) + val exitCode = config.outputStrategy match { + case Some(strategy) => Fork.scala(config.javaHome, config.runJVMOptions, config.scalaJars, scalaOptions, config.workingDirectory, strategy) + case None => Fork.scala(config.javaHome, config.runJVMOptions, config.scalaJars, scalaOptions, config.workingDirectory, log) + } processExitCode(exitCode, "runner") } private def classpathOption(classpath: Iterable[Path]) = "-cp" :: Path.makeString(classpath) :: Nil @@ -167,4 +170,4 @@ object Run extends ScalaRun interpreter.interpret("import current._") } } -} \ No newline at end of file +} diff --git a/src/main/scala/sbt/impl/ProcessImpl.scala b/src/main/scala/sbt/impl/ProcessImpl.scala index af7c7dd90..993c9068f 100644 --- a/src/main/scala/sbt/impl/ProcessImpl.scala +++ b/src/main/scala/sbt/impl/ProcessImpl.scala @@ -1,5 +1,5 @@ /* sbt -- Simple Build Tool - * Copyright 2009 Mark Harrah + * Copyright 2009 Mark Harrah, Vesa Vilhonen */ package sbt @@ -412,4 +412,4 @@ object Uncloseable def apply(out: OutputStream): OutputStream = new FilterOutputStream(out) { override def close() {} } def protect(in: InputStream): InputStream = if(in eq System.in) Uncloseable(in) else in def protect(out: OutputStream): OutputStream = if( (out eq System.out) || (out eq System.err)) Uncloseable(out) else out -} \ No newline at end of file +}