mirror of https://github.com/sbt/sbt.git
Create RunFromSourceMain & "sbtOn" command
This commit is contained in:
parent
5b0b9e2ba2
commit
9c32c16ade
|
|
@ -376,17 +376,26 @@ lazy val mainProj = (project in file("main"))
|
|||
// with the sole purpose of providing certain identifiers without qualification (with a package object)
|
||||
lazy val sbtProj = (project in file("sbt"))
|
||||
.dependsOn(mainProj, scriptedSbtProj % "test->test")
|
||||
.enablePlugins(BuildInfoPlugin)
|
||||
.settings(
|
||||
baseSettings,
|
||||
name := "sbt",
|
||||
normalizedName := "sbt",
|
||||
crossScalaVersions := Seq(baseScalaVersion),
|
||||
crossPaths := false,
|
||||
javaOptions ++= Seq("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"),
|
||||
mimaSettings,
|
||||
mimaBinaryIssueFilters ++= sbtIgnoredProblems,
|
||||
addBuildInfoToConfig(Test),
|
||||
buildInfoObject in Test := "TestBuildInfo",
|
||||
buildInfoKeys in Test := Seq[BuildInfoKey](fullClasspath in Compile),
|
||||
connectInput in run in Test := true,
|
||||
)
|
||||
.configure(addSbtCompilerBridge)
|
||||
|
||||
commands in Global += Command.single("sbtOn")((state, dir) =>
|
||||
s"sbtProj/test:runMain sbt.RunFromSourceMain $dir" :: state)
|
||||
|
||||
lazy val sbtIgnoredProblems = {
|
||||
Seq(
|
||||
// Added more items to Import trait.
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.1")
|
|||
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0")
|
||||
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1")
|
||||
addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.10")
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
package sbt
|
||||
|
||||
import scala.annotation.tailrec
|
||||
|
||||
import xsbti._
|
||||
|
||||
object RunFromSourceMain {
|
||||
private val sbtVersion = "1.0.3" // "dev"
|
||||
private val scalaVersion = "2.12.4"
|
||||
|
||||
def main(args: Array[String]): Unit = args match {
|
||||
case Array() => sys.error(s"Must specify working directory as the first argument")
|
||||
case Array(wd, args @ _*) => run(file(wd), args)
|
||||
}
|
||||
|
||||
// this arrangement is because Scala does not always properly optimize away
|
||||
// the tail recursion in a catch statement
|
||||
@tailrec private def run(baseDir: File, args: Seq[String]): Unit =
|
||||
runImpl(baseDir, args) match {
|
||||
case Some((baseDir, args)) => run(baseDir, args)
|
||||
case None => ()
|
||||
}
|
||||
|
||||
private def runImpl(baseDir: File, args: Seq[String]): Option[(File, Seq[String])] =
|
||||
try launch(getConf(baseDir, args)) map exit
|
||||
catch {
|
||||
case r: xsbti.FullReload => Some((baseDir, r.arguments()))
|
||||
case scala.util.control.NonFatal(e) => e.printStackTrace(); errorAndExit(e.toString)
|
||||
}
|
||||
|
||||
@tailrec private def launch(conf: AppConfiguration): Option[Int] =
|
||||
new xMain().run(conf) match {
|
||||
case e: xsbti.Exit => Some(e.code)
|
||||
case _: xsbti.Continue => None
|
||||
case r: xsbti.Reboot => launch(getConf(conf.baseDirectory(), r.arguments()))
|
||||
case x => handleUnknownMainResult(x)
|
||||
}
|
||||
|
||||
private val noGlobalLock = new GlobalLock {
|
||||
def apply[T](lockFile: File, run: java.util.concurrent.Callable[T]) = run.call()
|
||||
}
|
||||
|
||||
private def getConf(baseDir: File, args: Seq[String]): AppConfiguration = new AppConfiguration {
|
||||
def baseDirectory = baseDir
|
||||
def arguments = args.toArray
|
||||
def provider = new AppProvider { appProvider =>
|
||||
def scalaProvider = new ScalaProvider { scalaProvider =>
|
||||
def scalaOrg = "org.scala-lang"
|
||||
def launcher = new Launcher {
|
||||
def getScala(version: String) = getScala(version, "")
|
||||
def getScala(version: String, reason: String) = getScala(version, reason, scalaOrg)
|
||||
def getScala(version: String, reason: String, scalaOrg: String) = scalaProvider
|
||||
def app(id: xsbti.ApplicationID, version: String) = appProvider
|
||||
def topLoader = new java.net.URLClassLoader(Array(), null)
|
||||
def globalLock = noGlobalLock
|
||||
def bootDirectory = file(sys.props("user.home")) / ".sbt" / "boot"
|
||||
def ivyRepositories = Array()
|
||||
def appRepositories = Array()
|
||||
def isOverrideRepositories = false
|
||||
def ivyHome = file(sys.props("user.home")) / ".ivy2"
|
||||
def checksums = Array("sha1", "md5")
|
||||
}
|
||||
def version = scalaVersion
|
||||
def libDir: File = launcher.bootDirectory / s"scala-$version" / "lib"
|
||||
def jar(name: String): File = libDir / s"$name.jar"
|
||||
def libraryJar = jar("scala-library")
|
||||
def compilerJar = jar("scala-compiler")
|
||||
def jars = libDir.listFiles(f => !f.isDirectory && f.getName.endsWith(".jar"))
|
||||
def loader = new java.net.URLClassLoader(jars map (_.toURI.toURL), null)
|
||||
def app(id: xsbti.ApplicationID) = appProvider
|
||||
}
|
||||
|
||||
def id = ApplicationID(
|
||||
"org.scala-sbt",
|
||||
"sbt",
|
||||
sbtVersion,
|
||||
"sbt.xMain",
|
||||
Seq("xsbti", "extra"),
|
||||
CrossValue.Disabled,
|
||||
Nil
|
||||
)
|
||||
|
||||
def mainClasspath =
|
||||
buildinfo.TestBuildInfo.fullClasspath.iterator
|
||||
.map(s => file(s.stripPrefix("Attributed(").stripSuffix(")")))
|
||||
.toArray
|
||||
|
||||
def loader = new java.net.URLClassLoader(mainClasspath map (_.toURI.toURL), null)
|
||||
def entryPoint = classOf[xMain]
|
||||
def mainClass = classOf[xMain]
|
||||
def newMain = new xMain
|
||||
|
||||
def components = new ComponentProvider {
|
||||
def componentLocation(id: String) = ???
|
||||
def component(componentID: String) = ???
|
||||
def defineComponent(componentID: String, components: Array[File]) = ???
|
||||
def addToComponent(componentID: String, components: Array[File]) = ???
|
||||
def lockFile = ???
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def handleUnknownMainResult(x: MainResult): Nothing = {
|
||||
val clazz = if (x eq null) "" else " (class: " + x.getClass + ")"
|
||||
errorAndExit("Invalid main result: " + x + clazz)
|
||||
}
|
||||
|
||||
private def errorAndExit(msg: String): Nothing = { System.err.println(msg); exit(1) }
|
||||
private def exit(code: Int): Nothing = System.exit(code).asInstanceOf[Nothing]
|
||||
}
|
||||
Loading…
Reference in New Issue