Merge pull request #6593 from adpi2/fix-6575

Use `-Dsbt.script` to start sbt server
This commit is contained in:
eugene yokota 2021-07-22 12:09:35 -04:00 committed by GitHub
commit ab05465ef4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 10 deletions

View File

@ -330,6 +330,18 @@ class NetworkClient(
val cmd = arguments.sbtLaunchJar match {
case Some(lj) =>
if (log) {
val sbtScript = if (Properties.isWin) "sbt.bat" else "sbt"
console.appendLog(Level.Warn, s"server is started using sbt-launch jar directly")
console.appendLog(
Level.Warn,
"this is not the recommended way: .sbtopts and .jvmopts files are not loaded and SBT_OPTS is ignored"
)
console.appendLog(
Level.Warn,
s"either upgrade $sbtScript to its latest version or make sure it is accessible from $$PATH, and run 'sbt bspConfig'"
)
}
List("java") ++ arguments.sbtArguments ++
List("-jar", lj, DashDashDetachStdio, DashDashServer)
case _ =>
@ -1045,7 +1057,8 @@ object NetworkClient {
private[client] val noStdErr = "--no-stderr"
private[client] val sbtBase = "--sbt-base-directory"
private[client] def parseArgs(args: Array[String]): Arguments = {
var sbtScript = if (Properties.isWin) "sbt.bat" else "sbt"
val defaultSbtScript = if (Properties.isWin) "sbt.bat" else "sbt"
var sbtScript = Properties.propOrNone("sbt.script")
var launchJar: Option[String] = None
var bsp = false
val commandArgs = new mutable.ArrayBuffer[String]
@ -1067,11 +1080,10 @@ object NetworkClient {
sbtScript = a
.split("--sbt-script=")
.lastOption
.map(_.replaceAllLiterally("%20", " "))
.getOrElse(sbtScript)
.orElse(sbtScript)
case "--sbt-script" if i + 1 < sanitized.length =>
i += 1
sbtScript = sanitized(i).replaceAllLiterally("%20", " ")
sbtScript = Some(sanitized(i))
case a if a.startsWith("--sbt-launch-jar=") =>
launchJar = a
.split("--sbt-launch-jar=")
@ -1091,12 +1103,17 @@ object NetworkClient {
}
val base = new File("").getCanonicalFile
if (!sbtArguments.contains("-Dsbt.io.virtual=true")) sbtArguments += "-Dsbt.io.virtual=true"
if (!sbtArguments.exists(_.startsWith("-Dsbt.script"))) {
sbtScript.foreach { sbtScript =>
sbtArguments += s"-Dsbt.script=$sbtScript"
}
}
new Arguments(
base,
sbtArguments.toSeq,
commandArgs.toSeq,
completionArguments.toSeq,
sbtScript,
sbtScript.getOrElse(defaultSbtScript).replaceAllLiterally("%20", " "),
bsp,
launchJar
)

View File

@ -7,12 +7,14 @@
package sbt.internal.bsp
import java.io.File
import sbt.internal.bsp
import sbt.internal.bsp.codec.JsonProtocol.BspConnectionDetailsFormat
import sbt.io.IO
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
import java.io.File
import java.nio.file.{ Files, Paths }
import scala.util.Properties
object BuildServerConnection {
final val name = "sbt"
final val bspVersion = "2.0.0-M5"
@ -21,14 +23,25 @@ object BuildServerConnection {
private final val SbtLaunchJar = "sbt-launch(-.*)?\\.jar".r
private[sbt] def writeConnectionFile(sbtVersion: String, baseDir: File): Unit = {
import bsp.codec.JsonProtocol._
val bspConnectionFile = new File(baseDir, ".bsp/sbt.json")
val javaHome = System.getProperty("java.home")
val classPath = System.getProperty("java.class.path")
val sbtScript = Option(System.getProperty("sbt.script"))
.orElse(sbtScriptInPath)
.map(script => s"-Dsbt.script=$script")
// IntelliJ can start sbt even if the sbt script is not accessible from $PATH.
// To do so it uses its own bundled sbt-launch.jar.
// In that case, we must pass the path of the sbt-launch.jar to the BSP connection
// so that the server can be started.
// A known problem in that situation is that the .sbtopts and .jvmopts are not loaded.
val sbtLaunchJar = classPath
.split(File.pathSeparator)
.find(jar => SbtLaunchJar.findFirstIn(jar).nonEmpty)
.map(_.replaceAllLiterally(" ", "%20"))
.map(jar => s"--sbt-launch-jar=$jar")
val argv =
Vector(
s"$javaHome/bin/java",
@ -38,9 +51,21 @@ object BuildServerConnection {
classPath,
"xsbt.boot.Boot",
"-bsp"
) ++ sbtLaunchJar.map(jar => s"--sbt-launch-jar=$jar")
) ++ sbtScript.orElse(sbtLaunchJar)
val details = BspConnectionDetails(name, sbtVersion, bspVersion, languages, argv)
val json = Converter.toJson(details).get
IO.write(bspConnectionFile, CompactPrinter(json), append = false)
}
private def sbtScriptInPath: Option[String] = {
// For those who use an old sbt script, the -Dsbt.script is not set
// As a fallback we try to find the sbt script in $PATH
val fileName = if (Properties.isWin) "sbt.bat" else "sbt"
val envPath = Option(System.getenv("PATH")).getOrElse("")
val allPaths = envPath.split(File.pathSeparator).map(Paths.get(_))
allPaths
.map(_.resolve(fileName))
.find(file => Files.exists(file) && Files.isExecutable(file))
.map(_.toString.replaceAllLiterally(" ", "%20"))
}
}

11
sbt
View File

@ -299,6 +299,16 @@ addDefaultMemory() {
fi
}
addSbtScriptProperty () {
if [[ "${java_args[@]}" == *-Dsbt.script=* ]]; then
:
else
sbt_script=$0
sbt_script=${sbt_script/ /%20}
addJava "-Dsbt.script=$sbt_script"
fi
}
require_arg () {
local type="$1"
local opt="$2"
@ -769,6 +779,7 @@ else
java_version="$(jdk_version)"
vlog "[process_args] java_version = '$java_version'"
addDefaultMemory
addSbtScriptProperty
set -- "${residual_args[@]}"
argumentCount=$#
run