diff --git a/build.sbt b/build.sbt index 42feae4f8..86d0eea5c 100644 --- a/build.sbt +++ b/build.sbt @@ -230,7 +230,7 @@ lazy val `sbt-launcher` = project libs ++= { if (scalaBinaryVersion.value == "2.11") Seq( - Deps.caseApp, + Deps.caseApp12, Deps.sbtLauncherInterface, Deps.typesafeConfig ) diff --git a/sbt-launcher/src/main/scala-2.11/coursier/sbtlauncher/MainApp.scala b/sbt-launcher/src/main/scala-2.11/coursier/sbtlauncher/MainApp.scala index c83b7b1d6..9a95df41a 100644 --- a/sbt-launcher/src/main/scala-2.11/coursier/sbtlauncher/MainApp.scala +++ b/sbt-launcher/src/main/scala-2.11/coursier/sbtlauncher/MainApp.scala @@ -6,105 +6,157 @@ import java.nio.file.Files import caseapp._ import com.typesafe.config.ConfigFactory -import coursier.Dependency +import coursier.util.Properties +import coursier.{Dependency, Module} -final case class MainApp( +final case class MainOptions( @ExtraName("org") - organization: String, - name: String, - version: String, - scalaVersion: String, - sbtVersion: String, - mainClass: String, - mainComponents: List[String], - classpathExtra: List[String], - extra: List[String] -) extends App { + organization: String = "", + name: String = "", + version: String = "", + scalaVersion: String = "", + sbtVersion: String = "", + mainClass: String = "", + mainComponents: List[String] = Nil, + classpathExtra: List[String] = Nil, + extra: List[String] = Nil, + addCoursier: Boolean = true +) - val sbtPropFile = new File(sys.props("user.dir") + "/sbt.properties") - val buildPropFile = new File(sys.props("user.dir") + "/project/build.properties") +object MainApp extends CaseApp[MainOptions] { - val propFileOpt = Some(sbtPropFile).filter(_.exists()) - .orElse(Some(buildPropFile).filter(_.exists())) + val debug = sys.props.contains("coursier.sbt-launcher.debug") || sys.env.contains("COURSIER_SBT_LAUNCHER_DEBUG") - val (org0, name0, ver0, scalaVer0, extraDeps0, mainClass0, sbtVersion0) = - propFileOpt match { - case Some(propFile) => - // can't get ConfigFactory.parseFile to work fine here - val conf = ConfigFactory.parseString(new String(Files.readAllBytes(propFile.toPath), StandardCharsets.UTF_8)) - .withFallback(ConfigFactory.defaultReference(Thread.currentThread().getContextClassLoader)) - .resolve() - val sbtConfig = SbtConfig.fromConfig(conf) + def log(msg: String): Unit = + if (debug) + Console.err.println(msg) - (sbtConfig.organization, sbtConfig.moduleName, sbtConfig.version, sbtConfig.scalaVersion, sbtConfig.dependencies, sbtConfig.mainClass, sbtConfig.version) - case None => - require(scalaVersion.nonEmpty, "No scala version specified") - (organization, name, version, scalaVersion, Nil, mainClass, sbtVersion) + def run(options: MainOptions, remainingArgs: RemainingArgs): Unit = { + + val sbtPropFile = new File(sys.props("user.dir") + "/sbt.properties") + val buildPropFile = new File(sys.props("user.dir") + "/project/build.properties") + + val propFileOpt = Some(sbtPropFile).filter(_.exists()) + .orElse(Some(buildPropFile).filter(_.exists())) + + val (org0, name0, ver0, scalaVer0, extraDeps0, mainClass0, sbtVersion0) = + propFileOpt match { + case Some(propFile) => + log(s"Parsing $propFile") + + // can't get ConfigFactory.parseFile to work fine here + val conf = ConfigFactory.parseString(new String(Files.readAllBytes(propFile.toPath), StandardCharsets.UTF_8)) + .withFallback(ConfigFactory.defaultReference(Thread.currentThread().getContextClassLoader)) + .resolve() + val sbtConfig = SbtConfig.fromConfig(conf) + + (sbtConfig.organization, sbtConfig.moduleName, sbtConfig.version, sbtConfig.scalaVersion, sbtConfig.dependencies, sbtConfig.mainClass, sbtConfig.version) + case None => + require(options.scalaVersion.nonEmpty, "No scala version specified") + ( + options.organization, + options.name, + options.version, + options.scalaVersion, + Nil, + options.mainClass, + options.sbtVersion + ) + } + + val (extraParseErrors, extraModuleVersions) = + coursier.util.Parse.moduleVersions(options.extra, options.scalaVersion) + + if (extraParseErrors.nonEmpty) { + ??? } - val (extraParseErrors, extraModuleVersions) = coursier.util.Parse.moduleVersions(extra, scalaVersion) - - if (extraParseErrors.nonEmpty) { - ??? - } - - val extraDeps = extraModuleVersions.map { - case (mod, ver) => - Dependency(mod, ver) - } - - val launcher = new Launcher( - scalaVer0, - // FIXME Add org & moduleName in this path - new File(s"${sys.props("user.dir")}/target/sbt-components/components_scala$scalaVer0${if (sbtVersion0.isEmpty) "" else "_sbt" + sbtVersion0}"), - new File(s"${sys.props("user.dir")}/target/ivy2") - ) - - launcher.registerScalaComponents() - - if (sbtVersion0.nonEmpty) - launcher.registerSbtInterfaceComponents(sbtVersion0) - - val appId = ApplicationID( - org0, - name0, - ver0, - mainClass0, - mainComponents.toArray, - crossVersioned = false, - xsbti.CrossValue.Disabled, - classpathExtra.map(new File(_)).toArray - ) - - val appProvider = launcher.app(appId, extraDeps0 ++ extraDeps: _*) - - val appMain = appProvider.newMain() - - val appConfig = AppConfiguration( - remainingArgs.toArray, - new File(sys.props("user.dir")), - appProvider - ) - - val thread = Thread.currentThread() - val previousLoader = thread.getContextClassLoader - - val result = - try { - thread.setContextClassLoader(appProvider.loader()) - appMain.run(appConfig) - } finally { - thread.setContextClassLoader(previousLoader) + val extraDeps = extraModuleVersions.map { + case (mod, ver) => + Dependency(mod, ver) } - result match { - case _: xsbti.Continue => - case e: xsbti.Exit => - sys.exit(e.code()) - case _: xsbti.Reboot => - sys.error("Not able to reboot yet") + val coursierDeps = + if (options.addCoursier && sbtVersion0.nonEmpty) + Seq( + Dependency( + Module( + "io.get-coursier", + "sbt-coursier", + attributes = Map( + "scalaVersion" -> scalaVer0.split('.').take(2).mkString("."), + "sbtVersion" -> sbtVersion0.split('.').take(2).mkString(".") + ) + ), + Properties.version + ) + ) + else + Nil + + log("Creating launcher") + + val launcher = new Launcher( + scalaVer0, + // FIXME Add org & moduleName in this path + new File(s"${sys.props("user.dir")}/target/sbt-components/components_scala$scalaVer0${if (sbtVersion0.isEmpty) "" else "_sbt" + sbtVersion0}"), + new File(s"${sys.props("user.dir")}/target/ivy2") + ) + + log("Registering scala components") + + launcher.registerScalaComponents() + + if (sbtVersion0.nonEmpty) { + log("Registering sbt interface components") + launcher.registerSbtInterfaceComponents(sbtVersion0) + } + + val appId = ApplicationID( + org0, + name0, + ver0, + mainClass0, + options.mainComponents.toArray, + crossVersioned = false, + xsbti.CrossValue.Disabled, + options.classpathExtra.map(new File(_)).toArray + ) + + log("Getting app provider") + + val appProvider = launcher.app(appId, extraDeps0 ++ extraDeps ++ coursierDeps: _*) + + log("Creating main") + + val appMain = appProvider.newMain() + + val appConfig = AppConfiguration( + remainingArgs.args.toArray, + new File(sys.props("user.dir")), + appProvider + ) + + val thread = Thread.currentThread() + val previousLoader = thread.getContextClassLoader + + val result = + try { + thread.setContextClassLoader(appProvider.loader()) + appMain.run(appConfig) + } finally { + thread.setContextClassLoader(previousLoader) + } + + log("Done") + + result match { + case _: xsbti.Continue => + case e: xsbti.Exit => + sys.exit(e.code()) + case _: xsbti.Reboot => + sys.error("Not able to reboot yet") + } } } - -object Main extends AppOf[MainApp] diff --git a/sbt.properties b/sbt.properties deleted file mode 100644 index 7de236491..000000000 --- a/sbt.properties +++ /dev/null @@ -1,17 +0,0 @@ -sbt.version=0.13.8 - -plugins = [ - "io.get-coursier:sbt-coursier:1.0.0-M15-5" - "io.get-coursier:sbt-shading:1.0.0-M15-5" - "org.xerial.sbt:sbt-pack:0.8.2" - "org.scala-js:sbt-scalajs:0.6.14" - "com.jsuereth:sbt-pgp:1.0.0" - "org.scoverage:sbt-scoverage:1.4.0" - "org.tpolecat:tut-plugin:0.4.8" - "com.typesafe.sbt:sbt-proguard:0.2.2" - "com.typesafe:sbt-mima-plugin:0.1.13" -] - -dependencies = [ - "org.scala-sbt:scripted-plugin:"${sbt.version} -]