diff --git a/run/src/main/scala/sbt/Fork.scala b/run/src/main/scala/sbt/Fork.scala index 88ad0125c..8b88c46a8 100644 --- a/run/src/main/scala/sbt/Fork.scala +++ b/run/src/main/scala/sbt/Fork.scala @@ -5,39 +5,74 @@ package sbt import java.io.{File,OutputStream} +@deprecated("Use ForkOptions", "0.13.0") trait ForkJava { def javaHome: Option[File] def outputStrategy: Option[OutputStrategy] def connectInput: Boolean } +@deprecated("Use ForkOptions", "0.13.0") trait ForkScala extends ForkJava { def scalaJars: Iterable[File] } +@deprecated("Use ForkOptions", "0.13.0") trait ForkScalaRun extends ForkScala { def workingDirectory: Option[File] def runJVMOptions: Seq[String] } -final case class ForkOptions(javaHome: Option[File] = None, outputStrategy: Option[OutputStrategy] = None, scalaJars: Iterable[File] = Nil, workingDirectory: Option[File] = None, runJVMOptions: Seq[String] = Nil, connectInput: Boolean = false, envVars: Map[String,String] = Map.empty) extends ForkScalaRun +final case class ForkOptions(javaHome: Option[File] = None, outputStrategy: Option[OutputStrategy] = None, bootJars: Seq[File] = Nil, workingDirectory: Option[File] = None, runJVMOptions: Seq[String] = Nil, connectInput: Boolean = false, envVars: Map[String,String] = Map.empty) extends ForkScalaRun +{ + @deprecated("Use bootJars.", "0.13.0") + def scalaJars: Iterable[File] = bootJars +} -sealed abstract class OutputStrategy extends NotNull +sealed abstract class OutputStrategy case object StdoutOutput extends OutputStrategy case class BufferedOutput(logger: Logger) extends OutputStrategy case class LoggedOutput(logger: Logger) extends OutputStrategy case class CustomOutput(output: OutputStream) extends OutputStrategy import java.lang.{ProcessBuilder => JProcessBuilder} +sealed class Fork(val commandName: String, val runnerClass: Option[String]) +{ + def apply(config: ForkOptions, arguments: Seq[String]): Int = fork(config, arguments).exitValue() + def fork(config: ForkOptions, arguments: Seq[String]): Process = + { + import config.{envVars => env, _} + val executable = Fork.javaCommand(javaHome, commandName).getAbsolutePath + val options = makeOptions(runJVMOptions, bootJars, arguments) + val command = (executable +: options).toArray + val builder = new JProcessBuilder(command : _*) + workingDirectory.foreach(wd => builder.directory(wd)) + val environment = builder.environment + for( (key, value) <- env ) + environment.put(key, value) + outputStrategy.getOrElse(StdoutOutput) match { + case StdoutOutput => Process(builder).run(connectInput) + case BufferedOutput(logger) => Process(builder).runBuffered(logger, connectInput) + case LoggedOutput(logger) => Process(builder).run(logger, connectInput) + case CustomOutput(output) => (Process(builder) #> output).run(connectInput) + } + } + private[this] def makeOptions(jvmOptions: Seq[String], bootJars: Iterable[File], arguments: Seq[String]): Seq[String] = + { + val boot = if(bootJars.isEmpty) None else Some("-Xbootclasspath/a:" + bootJars.map(_.getAbsolutePath).mkString(File.pathSeparator)) + jvmOptions ++ boot.toList ++ runnerClass.toList ++ arguments + } +} object Fork { private val ScalacMainClass = "scala.tools.nsc.Main" private val ScalaMainClass = "scala.tools.nsc.MainGenericRunner" + private val JavaCommandName = "java" - val java = new ForkJava("java") + val java = new ForkJava(JavaCommandName) val javac = new ForkJava("javac") - val scala = new ForkScala(ScalaMainClass) - val scalac = new ForkScala(ScalacMainClass) + val scala = new Fork(JavaCommandName, Some(ScalaMainClass)) + val scalac = new Fork(JavaCommandName, Some(ScalacMainClass)) private def javaCommand(javaHome: Option[File], name: String): File = { @@ -45,11 +80,9 @@ object Fork new File(new File(home, "bin"), name) } - final class ForkJava(commandName: String) + @deprecated("Use Fork", "0.13.0") + final class ForkJava(commandName: String) extends Fork(commandName, None) { - def apply(config: ForkOptions, arguments: Seq[String]): Int = fork(config, arguments).exitValue() - def fork(config: ForkOptions, arguments: Seq[String]): Process = - fork(config.javaHome, config.runJVMOptions ++ arguments, config.workingDirectory, config.envVars, config.connectInput, config.outputStrategy getOrElse StdoutOutput) @deprecated("Use apply(ForkOptions, Seq[String])", "0.13.0") def apply(javaHome: Option[File], options: Seq[String], log: Logger): Int = apply(javaHome, options, BufferedOutput(log)) @@ -69,6 +102,8 @@ object Fork @deprecated("Use apply(ForkOptions, Seq[String])", "0.13.0") def apply(javaHome: Option[File], options: Seq[String], workingDirectory: Option[File], env: Map[String, String], outputStrategy: OutputStrategy): Int = fork(javaHome, options, workingDirectory, env, false, outputStrategy).exitValue + + @deprecated("Use apply(ForkOptions, Seq[String])", "0.13.0") def fork(javaHome: Option[File], options: Seq[String], workingDirectory: Option[File], env: Map[String, String], connectInput: Boolean, outputStrategy: OutputStrategy): Process = { val executable = javaCommand(javaHome, commandName).getAbsolutePath @@ -87,12 +122,9 @@ object Fork } } + @deprecated("Use Fork", "0.13.0") final class ForkScala(mainClassName: String) { - def apply(options: ForkOptions, arguments: Seq[String]): Int = fork(options, arguments).exitValue() - def fork(options: ForkOptions, arguments: Seq[String]): Process = - fork(options.javaHome, options.runJVMOptions, options.scalaJars, arguments, options.workingDirectory, options.envVars, options.connectInput, options.outputStrategy getOrElse StdoutOutput) - @deprecated("Use apply(ForkOptions, Seq[String])", "0.13.0") def apply(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], log: Logger): Int = apply(javaHome, jvmOptions, scalaJars, arguments, None, BufferedOutput(log)) @@ -109,6 +141,7 @@ object Fork def fork(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], workingDirectory: Option[File], connectInput: Boolean, outputStrategy: OutputStrategy): Process = fork(javaHome, jvmOptions, scalaJars, arguments, workingDirectory, connectInput, outputStrategy) + @deprecated("Use apply(ForkOptions, Seq[String])", "0.13.0") def fork(javaHome: Option[File], jvmOptions: Seq[String], scalaJars: Iterable[File], arguments: Seq[String], workingDirectory: Option[File], env: Map[String,String], connectInput: Boolean, outputStrategy: OutputStrategy): Process = { if(scalaJars.isEmpty) sys.error("Scala jars not specified") diff --git a/run/src/main/scala/sbt/Run.scala b/run/src/main/scala/sbt/Run.scala index 29de50e7b..cc33acc49 100644 --- a/run/src/main/scala/sbt/Run.scala +++ b/run/src/main/scala/sbt/Run.scala @@ -16,7 +16,7 @@ trait ScalaRun class ForkRun(config: ForkOptions) extends ScalaRun { @deprecated("Use the `ForkRun(ForkOptions) constructor`", "0.13.0") - def this(options: ForkScalaRun) = this(ForkOptions(options.javaHome, options.outputStrategy, options.scalaJars, options.workingDirectory, options.runJVMOptions, options.connectInput)) + def this(options: ForkScalaRun) = this(ForkOptions(options.javaHome, options.outputStrategy, options.scalaJars.toSeq, options.workingDirectory, options.runJVMOptions, options.connectInput)) def run(mainClass: String, classpath: Seq[File], options: Seq[String], log: Logger): Option[String] = {