Merge pull request #3477 from eed3si9n/wip/runissue

Forward `run` task to `bgRun`
This commit is contained in:
eugene yokota 2017-08-27 16:13:25 -04:00 committed by GitHub
commit 6202015335
6 changed files with 65 additions and 15 deletions

View File

@ -5,6 +5,7 @@ import sbt.util.Logger
import Def.{ ScopedKey, Classpath }
import sbt.internal.util.complete._
import java.io.File
import scala.util.Try
abstract class BackgroundJobService extends Closeable {
@ -24,6 +25,12 @@ abstract class BackgroundJobService extends Closeable {
def shutdown(): Unit
def jobs: Vector[JobHandle]
def stop(job: JobHandle): Unit
def waitForTry(job: JobHandle): Try[Unit] = {
// This implementation is provided only for backward compatibility.
Try(waitFor(job))
}
def waitFor(job: JobHandle): Unit
/** Copies classpath to temporary directories. */

View File

@ -503,8 +503,8 @@ object Defaults extends BuildCommon {
selectMainClass := mainClass.value orElse askForMainClass(discoveredMainClasses.value),
mainClass in run := (selectMainClass in run).value,
mainClass := pickMainClassOrWarn(discoveredMainClasses.value, streams.value.log),
runMain := runMainTask(fullClasspath, runner in run).evaluated,
run := runTask(fullClasspath, mainClass in run, runner in run).evaluated,
runMain := foregroundRunMainTask.evaluated,
run := foregroundRunTask.evaluated,
copyResources := copyResourcesTask.value,
// note that we use the same runner and mainClass as plain run
bgRunMain := bgRunMainTask(exportedProductJars,
@ -1168,14 +1168,14 @@ object Defaults extends BuildCommon {
Def.inputTask {
val handle = bgRunMain.evaluated
val service = bgJobService.value
service.waitFor(handle)
service.waitForTry(handle).get
}
// run calls bgRun in the background and waits for the result.
def foregroundRunTask: Initialize[InputTask[Unit]] =
Def.inputTask {
val handle = bgRun.evaluated
val service = bgJobService.value
service.waitFor(handle)
service.waitForTry(handle).get
}
def runMainTask(classpath: Initialize[Task[Classpath]],
scalaRun: Initialize[Task[ScalaRun]]): Initialize[InputTask[Unit]] = {
@ -1540,8 +1540,11 @@ object Defaults extends BuildCommon {
lazy val configSettings
: Seq[Setting[_]] = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig ++ Classpaths.compilerPluginConfig ++ deprecationSettings
lazy val compileSettings
: Seq[Setting[_]] = configSettings ++ (mainBgRunMainTask +: mainBgRunTask +: addBaseSources) ++ Classpaths.addUnmanagedLibrary
lazy val compileSettings: Seq[Setting[_]] =
configSettings ++
(mainBgRunMainTask +: mainBgRunTask +: addBaseSources) ++
Classpaths.addUnmanagedLibrary
lazy val testSettings: Seq[Setting[_]] = configSettings ++ testTasks
lazy val itSettings: Seq[Setting[_]] = inConfig(IntegrationTest)(testSettings)

View File

@ -5,6 +5,7 @@ import java.util.concurrent.atomic.AtomicLong
import java.io.Closeable
import Def.{ ScopedKey, Setting, Classpath }
import scala.concurrent.ExecutionContext
import scala.util.Try
import Scope.GlobalScope
import java.io.File
import sbt.io.{ IO, Hash }
@ -18,6 +19,13 @@ import sbt.internal.util.{ Attributed, ManagedLogger }
private[sbt] abstract class BackgroundJob {
def humanReadableName: String
def awaitTermination(): Unit
/** This waits till the job ends, and returns inner error via `Try`. */
def awaitTerminationTry(): Try[Unit] = {
// This implementation is provided only for backward compatibility.
Try(awaitTermination())
}
def shutdown(): Unit
// this should be true on construction and stay true until
// the job is complete
@ -132,15 +140,27 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
private def withHandle(job: JobHandle)(f: ThreadJobHandle => Unit): Unit = job match {
case handle: ThreadJobHandle @unchecked => f(handle)
case dead: DeadHandle @unchecked => () // nothing to stop or wait for
case _: DeadHandle @unchecked => () // nothing to stop or wait for
case other =>
sys.error(
s"BackgroundJobHandle does not originate with the current BackgroundJobService: $other")
}
private def withHandleTry(job: JobHandle)(f: ThreadJobHandle => Try[Unit]): Try[Unit] =
job match {
case handle: ThreadJobHandle @unchecked => f(handle)
case _: DeadHandle @unchecked => Try(()) // nothing to stop or wait for
case other =>
Try(sys.error(
s"BackgroundJobHandle does not originate with the current BackgroundJobService: $other"))
}
override def stop(job: JobHandle): Unit =
withHandle(job)(_.job.shutdown())
override def waitForTry(job: JobHandle): Try[Unit] =
withHandleTry(job)(_.job.awaitTerminationTry())
override def waitFor(job: JobHandle): Unit =
withHandle(job)(_.job.awaitTermination())
@ -212,6 +232,9 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
@volatile
private var status: Status = Waiting
// This is used to capture exceptions that are caught in this background job.
private var exitTry: Option[Try[Unit]] = None
// double-finally for extra paranoia that we will finishedLatch.countDown
override def run() =
try {
@ -226,7 +249,11 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
throw new RuntimeException("Impossible status of bg thread")
}
}
try { if (go) body() } finally cleanup()
try {
if (go) {
exitTry = Option(Try(body()))
}
} finally cleanup()
} finally finishedLatch.countDown()
private class StopListener(val callback: () => Unit, val executionContext: ExecutionContext)
@ -269,6 +296,12 @@ private[sbt] class BackgroundThreadPool extends java.io.Closeable {
result
}
override def awaitTermination(): Unit = finishedLatch.await()
override def awaitTerminationTry(): Try[Unit] = {
awaitTermination()
exitTry.getOrElse(Try(()))
}
override def humanReadableName: String = taskName
override def isRunning(): Boolean =
status match {

View File

@ -1,6 +1,9 @@
scalaVersion in ThisBuild := "2.12.3"
libraryDependencies ++= Seq(
"com.novocode" % "junit-interface" % "0.5" % "test",
"junit" % "junit" % "4.8" % "test"
"com.novocode" % "junit-interface" % "0.5" % Test,
"junit" % "junit" % "4.8" % Test,
"commons-io" % "commons-io" % "2.5" % Runtime,
)
libraryDependencies += scalaVersion("org.scala-lang" % "scala-compiler" % _ ).value

View File

@ -28,10 +28,11 @@ class Foo {
catch { case _: URISyntaxException => new File(url.getPath) }
}
object Test
{
def main(args: Array[String])
{
object Test {
def main(args: Array[String]): Unit = {
// test that Runtime configuration is included
Class.forName("org.apache.commons.io.ByteOrderMark")
val foo = new Foo
args.foreach { arg => foo.eval(arg) == arg.toInt }
}

View File

@ -17,7 +17,10 @@ def unpackageSettings(name: String) = Seq(
unmanagedSourceDirectories := (baseDirectory.value / name) :: Nil,
excludeFilter in unmanagedResources := (includeFilter in unmanagedSources).value,
unmanagedResourceDirectories := unmanagedSourceDirectories.value,
unpackage := IO.unzip(artifactPath in packageSrc value, baseDirectory.value / name)
unpackage := {
IO.unzip(artifactPath in packageSrc value, baseDirectory.value / name)
IO.delete(baseDirectory.value / name / "META-INF")
}
)
val unpackage = TaskKey[Unit]("unpackage")