mirror of https://github.com/sbt/sbt.git
[2.x] feat: Support --autostart=false and --no-server in sbtn client (#8895)
**Problem** When sbtn (native thin client) can't find a running sbt server, it prompts to start one. There was no way to opt out of server auto-start from the client side, which is needed for CI environments and scripting (sbt/sbt#7079). **Solution** Reuse the existing sbt.server.autostart system property in NetworkClient to control whether sbtn should attempt to start a server. When no server is running and sbt.server.autostart=false, sbtn exits with an error instead of prompting. Support setting this property via: - sbtn --no-server compile (sets sbt.server.autostart=false) - sbtn --autostart=false compile (new flag following sbt conventions) - sbtn -Dsbt.server.autostart=false compile (direct system property) - sbt --autostart=false compile (bash runner and sbtw) This follows sbt's naming conventions for properties/options: positive property names with =false opt-out (like --color=false, --supershell=false). Fixes sbt/sbt#7079 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ab503ca51e
commit
dc90f160df
|
|
@ -151,6 +151,8 @@ class NetworkClient(
|
|||
private lazy val noStdErr = arguments.completionArguments.contains("--no-stderr") &&
|
||||
!sys.env.contains("SBTN_AUTO_COMPLETE") && !sys.env.contains("SBTC_AUTO_COMPLETE")
|
||||
private def shutdownOnly = arguments.commandArguments == Seq(Shutdown)
|
||||
private lazy val serverAutoStart: Boolean =
|
||||
sys.props.get("sbt.server.autostart").forall(_.toLowerCase == "true")
|
||||
|
||||
private def mkSocket(file: File): (Socket, Option[String]) = ClientSocket.socket(file, useJNI)
|
||||
|
||||
|
|
@ -189,6 +191,9 @@ class NetworkClient(
|
|||
if (shutdownOnly) {
|
||||
console.appendLog(Level.Info, "no sbt server is running. ciao")
|
||||
System.exit(0)
|
||||
} else if (!serverAutoStart) {
|
||||
console.appendLog(Level.Error, "no sbt server is running (sbt.server.autostart=false)")
|
||||
System.exit(1)
|
||||
} else if (promptCompleteUsers) {
|
||||
val msg = if (noTab) "" else "No sbt server is running. Press <tab> to start one..."
|
||||
errorStream.print(s"\n$msg")
|
||||
|
|
@ -1187,7 +1192,7 @@ object NetworkClient {
|
|||
completionArguments,
|
||||
sbtScript,
|
||||
bsp,
|
||||
sbtLaunchJar
|
||||
sbtLaunchJar,
|
||||
)
|
||||
}
|
||||
private[client] val completions = "--completions"
|
||||
|
|
@ -1246,8 +1251,6 @@ object NetworkClient {
|
|||
"--timings",
|
||||
"-traces",
|
||||
"--traces",
|
||||
"-no-server",
|
||||
"--no-server",
|
||||
"-no-share",
|
||||
"--no-share",
|
||||
"-no-global",
|
||||
|
|
@ -1264,6 +1267,8 @@ object NetworkClient {
|
|||
"-supershell=",
|
||||
"--color=",
|
||||
"-color=",
|
||||
"--autostart=",
|
||||
"-autostart=",
|
||||
)
|
||||
private[client] def parseArgs(args: Array[String]): Arguments = {
|
||||
val defaultSbtScript = if (Properties.isWin) "sbt.bat" else "sbt"
|
||||
|
|
@ -1302,6 +1307,12 @@ object NetworkClient {
|
|||
i += 1
|
||||
launchJar = Option(sanitized(i).replace("%20", " "))
|
||||
case "-bsp" | "--bsp" => bsp = true
|
||||
case "-no-server" | "--no-server" =>
|
||||
System.setProperty("sbt.server.autostart", "false")
|
||||
case a if a.startsWith("--autostart=") =>
|
||||
System.setProperty("sbt.server.autostart", a.stripPrefix("--autostart="))
|
||||
case a if a.startsWith("-autostart=") =>
|
||||
System.setProperty("sbt.server.autostart", a.stripPrefix("-autostart="))
|
||||
case a if launcherValueFlags.contains(a) =>
|
||||
if (i + 1 < sanitized.length) i += 1
|
||||
case a if launcherNoValueFlags.contains(a) => ()
|
||||
|
|
@ -1329,7 +1340,7 @@ object NetworkClient {
|
|||
completionArguments.toSeq,
|
||||
sbtScript.getOrElse(defaultSbtScript).replace("%20", " "),
|
||||
bsp,
|
||||
launchJar
|
||||
launchJar,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,6 +111,38 @@ object NetworkClientParseArgsTest extends BasicTestSuite:
|
|||
val result = parse("-bsp")
|
||||
assert(result.bsp)
|
||||
|
||||
// -- --no-server and --autostart= set sbt.server.autostart --
|
||||
|
||||
test("--no-server sets sbt.server.autostart=false"):
|
||||
try
|
||||
System.clearProperty("sbt.server.autostart")
|
||||
parse("--no-server", "compile")
|
||||
assert(System.getProperty("sbt.server.autostart") == "false")
|
||||
finally System.clearProperty("sbt.server.autostart")
|
||||
|
||||
test("-no-server sets sbt.server.autostart=false"):
|
||||
try
|
||||
System.clearProperty("sbt.server.autostart")
|
||||
parse("-no-server", "compile")
|
||||
assert(System.getProperty("sbt.server.autostart") == "false")
|
||||
finally System.clearProperty("sbt.server.autostart")
|
||||
|
||||
test("--autostart=false sets sbt.server.autostart=false"):
|
||||
try
|
||||
System.clearProperty("sbt.server.autostart")
|
||||
val result = parse("--autostart=false", "compile")
|
||||
assert(System.getProperty("sbt.server.autostart") == "false")
|
||||
assert(!result.sbtArguments.exists(_.contains("autostart")))
|
||||
assert(result.commandArguments.contains("compile"))
|
||||
finally System.clearProperty("sbt.server.autostart")
|
||||
|
||||
test("--autostart=true sets sbt.server.autostart=true"):
|
||||
try
|
||||
System.clearProperty("sbt.server.autostart")
|
||||
parse("--autostart=true", "compile")
|
||||
assert(System.getProperty("sbt.server.autostart") == "true")
|
||||
finally System.clearProperty("sbt.server.autostart")
|
||||
|
||||
test("--sbt-launch-jar is preserved"):
|
||||
val result = parse("--sbt-launch-jar", "/path/to/sbt-launch.jar", "compile")
|
||||
assert(result.sbtLaunchJar.contains("/path/to/sbt-launch.jar"))
|
||||
|
|
|
|||
2
sbt
2
sbt
|
|
@ -732,6 +732,8 @@ map_args () {
|
|||
--supershell=*) options=( "${options[@]}" "-Dsbt.supershell=${1:13}" ) && shift ;;
|
||||
-supershell=*) options=( "${options[@]}" "-Dsbt.supershell=${1:12}" ) && shift ;;
|
||||
-no-server|--no-server) options=( "${options[@]}" "-Dsbt.io.virtual=false" "-Dsbt.server.autostart=false" ) && shift ;;
|
||||
--autostart=*) options=( "${options[@]}" "-Dsbt.server.autostart=${1:13}" ) && shift ;;
|
||||
-autostart=*) options=( "${options[@]}" "-Dsbt.server.autostart=${1:12}" ) && shift ;;
|
||||
--color=*) options=( "${options[@]}" "-Dsbt.color=${1:8}" ) && shift ;;
|
||||
-color=*) options=( "${options[@]}" "-Dsbt.color=${1:7}" ) && shift ;;
|
||||
-no-share|--no-share) options=( "${options[@]}" "${noshare_opts[@]}" ) && shift ;;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ object ArgParser:
|
|||
opt[Int]("mem").action((x, c) => c.copy(mem = Some(x))),
|
||||
opt[String]("supershell").action((x, c) => c.copy(supershell = Some(x))),
|
||||
opt[String]("color").action((x, c) => c.copy(color = Some(x))),
|
||||
opt[String]("autostart").action((x, c) => c.copy(autostart = Some(x))),
|
||||
opt[Int]("jvm-debug").action((x, c) => c.copy(jvmDebug = Some(x))),
|
||||
opt[String]("java-home").action((x, c) => c.copy(javaHome = Some(x))),
|
||||
arg[String]("<arg>")
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ case class LauncherOptions(
|
|||
mem: Option[Int] = None,
|
||||
supershell: Option[String] = None,
|
||||
color: Option[String] = None,
|
||||
autostart: Option[String] = None,
|
||||
jvmDebug: Option[Int] = None,
|
||||
javaHome: Option[String] = None,
|
||||
server: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ object Runner:
|
|||
opts.sbtCache.foreach(v => s = s :+ s"-Dsbt.global.localcache=$v")
|
||||
opts.ivy.foreach(v => s = s :+ s"-Dsbt.ivy.home=$v")
|
||||
opts.color.foreach(v => s = s :+ s"-Dsbt.color=$v")
|
||||
opts.autostart.foreach(v => s = s :+ s"-Dsbt.server.autostart=$v")
|
||||
if opts.timings then
|
||||
s = s ++ Seq("-Dsbt.task.timings=true", "-Dsbt.task.timings.on.shutdown=true")
|
||||
if opts.traces then s = s :+ "-Dsbt.traces=true"
|
||||
|
|
|
|||
Loading…
Reference in New Issue