diff --git a/main-command/src/main/scala/sbt/BasicCommandStrings.scala b/main-command/src/main/scala/sbt/BasicCommandStrings.scala index d7da62d90..f7f728a38 100644 --- a/main-command/src/main/scala/sbt/BasicCommandStrings.scala +++ b/main-command/src/main/scala/sbt/BasicCommandStrings.scala @@ -194,6 +194,8 @@ $AliasCommand name= def Client = "client" def ClientDetailed = "Provides an interactive prompt from which commands can be run on a server." + def DashClient = "-client" + def DashDashClient = "--client" def StashOnFailure = "sbtStashOnFailure" def PopOnFailure = "sbtPopOnFailure" diff --git a/main-command/src/main/scala/sbt/BasicCommands.scala b/main-command/src/main/scala/sbt/BasicCommands.scala index 896cd9fe1..cc58497a6 100644 --- a/main-command/src/main/scala/sbt/BasicCommands.scala +++ b/main-command/src/main/scala/sbt/BasicCommands.scala @@ -297,7 +297,7 @@ object BasicCommands { case e :: Nil if e.commandLine == "shell" => Nil case xs => xs map (_.commandLine) }) - NetworkClient.run(arguments) + NetworkClient.run(s0.configuration.baseDirectory, arguments) "exit" :: s0.copy(remainingCommands = Nil) } diff --git a/main-command/src/main/scala/sbt/CommandUtil.scala b/main-command/src/main/scala/sbt/CommandUtil.scala index 4087b5932..6bdfcf0be 100644 --- a/main-command/src/main/scala/sbt/CommandUtil.scala +++ b/main-command/src/main/scala/sbt/CommandUtil.scala @@ -15,6 +15,7 @@ import sbt.internal.util.complete.Parser import sbt.internal.util.complete.DefaultParsers._ import sbt.io.IO +import sbt.io.syntax._ object CommandUtil { def readLines(files: Seq[File]): Seq[String] = @@ -89,4 +90,7 @@ object CommandUtil { details.map { case (k, v) => k + "\n\n " + v } mkString ("\n", "\n\n", "\n") final val HelpPatternFlags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE + + private[sbt] def isSbtBuild(baseDir: File) = + (baseDir / "project").exists() || (baseDir * "*.sbt").get.nonEmpty } diff --git a/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala b/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala index 758f8712d..90ef086e3 100644 --- a/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala +++ b/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala @@ -24,7 +24,7 @@ import sbt.io.syntax._ import sbt.io.IO import sjsonnew.support.scalajson.unsafe.Converter -class NetworkClient(arguments: List[String]) { self => +class NetworkClient(baseDirectory: File, arguments: List[String]) { self => private val channelName = new AtomicReference("_") private val status = new AtomicReference("Ready") private val lock: AnyRef = new AnyRef {} @@ -39,7 +39,7 @@ class NetworkClient(arguments: List[String]) { self => // Open server connection based on the portfile def init(): ServerConnection = { - val portfile = (file("project") / "target" / "active.json").getAbsoluteFile + val portfile = baseDirectory / "project" / "target" / "active.json" if (!portfile.exists) sys.error("server does not seem to be running.") val (sk, tkn) = ClientSocket.socket(portfile) val conn = new ServerConnection(sk) { @@ -190,9 +190,9 @@ class NetworkClient(arguments: List[String]) { self => } object NetworkClient { - def run(arguments: List[String]): Unit = + def run(baseDirectory: File, arguments: List[String]): Unit = try { - new NetworkClient(arguments) + new NetworkClient(baseDirectory, arguments) () } catch { case NonFatal(e) => println(e.getMessage) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 49094156b..720d3c10d 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -64,15 +64,30 @@ import CommandStrings.BootCommand final class xMain extends xsbti.AppMain { def run(configuration: xsbti.AppConfiguration): xsbti.MainResult = { import BasicCommands.early - import BasicCommandStrings.runEarly + import BasicCommandStrings.{ runEarly, DashClient, DashDashClient } import BuiltinCommands.defaults import sbt.internal.CommandStrings.{ BootCommand, DefaultsCommand, InitCommand } - val state = StandardMain.initialState( - configuration, - Seq(defaults, early), - runEarly(DefaultsCommand) :: runEarly(InitCommand) :: BootCommand :: Nil - ) - StandardMain.runManaged(state) + import sbt.internal.client.NetworkClient + + // if we detect -Dsbt.client=true or -client, run thin client. + val clientModByEnv = java.lang.Boolean.getBoolean("sbt.client") + val userCommands = configuration.arguments.map(_.trim) + if (clientModByEnv || (userCommands.exists { cmd => + (cmd == DashClient) || (cmd == DashDashClient) + })) { + val args = userCommands.toList filterNot { cmd => + (cmd == DashClient) || (cmd == DashDashClient) + } + NetworkClient.run(configuration.baseDirectory, args) + Exit(0) + } else { + val state = StandardMain.initialState( + configuration, + Seq(defaults, early), + runEarly(DefaultsCommand) :: runEarly(InitCommand) :: BootCommand :: Nil + ) + StandardMain.runManaged(state) + } } } @@ -861,9 +876,6 @@ object BuiltinCommands { private val sbtVersionRegex = """sbt\.version\s*=.*""".r private def isSbtVersionLine(s: String) = sbtVersionRegex.pattern matcher s matches () - private def isSbtProject(baseDir: File, projectDir: File) = - projectDir.exists() || (baseDir * "*.sbt").get.nonEmpty - private def writeSbtVersionUnconditionally(state: State) = { val baseDir = state.baseDir val sbtVersion = BuiltinCommands.sbtVersion(state) @@ -877,7 +889,7 @@ object BuiltinCommands { if (sbtVersionAbsent) { val warnMsg = s"No sbt.version set in project/build.properties, base directory: $baseDir" try { - if (isSbtProject(baseDir, projectDir)) { + if (isSbtBuild(baseDir)) { val line = s"sbt.version=$sbtVersion" IO.writeLines(buildProps, line :: buildPropsLines) state.log info s"Updated file $buildProps: set sbt.version to $sbtVersion"