In order to start the sbt server we must use the sbt script because
it is the only way to load the .sbtopts and the .jvmopts file properly.
To do so the sbt script can pass a -Dsbt.script prop to the java server.
It is used in the NetworkClient to start the server, and it is replicated
in the BuildServerConnection file (.bsp/sbt.json).
The problem was that -client was different from --client, which
makes for a confusing user experience. So, this change makes
them the same and re-names -client to --java-client. The value
of this is that hopefully -client and --client being the same
feels more logical to users.
The intellij bsp integration launches sbt with the launcher and runs
-bsp. This doesn't work if sbt is not on intellij's path. To try and
work around this, we can add an option --sbt-launch-jar that is
recognized by the network client and will make it use the launch jar
rather than the sbt script to launch a new server if needed.
Made the bspConfig task dependendant on the bspConfig value.
Changed the bspConfig setting to use a attributeKey so we can use it in the server as well.
The new version provides an apple silicon arm64 jni implementation of
the ipcsocket api. It also adds a jni implementation for getting the max
socket length which is necessary because jna isn't supported on the
apple arm64 platform yet.
There isn't yet a version of the jna available that works with the new
apple silicon using arm64. To workaround this, we can use the jni
implementation by default on arm64 macs. If the user wants to force the
jni implementation for any supported platform, they can opt in with the
`sbt.ipcsocket.jni` system property and/or by setting the serverUseJni
setting.
Network client already supports the -bsp command (since
65ab7c94d0). This commit reworks the
BspClient.run method so that it delegates to the NetworkClient. The
advantage to doing it this way is that improvements to starting up the
sbt server by the thin client will automatically propagate to the -bsp
command. The way that it is implemented, all of the output generated
during server startup will be redirected to System.err which is useful
for debugging without messing up the bsp protocol, which relies on only
bsp messages being written to System.out.
The boot server socket was not working correctly when the sbt server was
started by the thin client. This was because it is necessary for us to
create a ConsoleTerminal in order for System.out and System.err to be
properly forwarded to the clients connected over the boot server socket.
As a result, if you started a server instance of sbt with the thin
client, you wouldn't see any output util you connected to the server.
The fix is to just make sure that we create a console terminal if sbt is
run as a subprocess.
When a batch command is run with the thin client, it logs an info
message that the command completed. This is unnecessary given that
completion is implied by the success or failure method that follows. It
made the output look a little different in the thin client vs the
console.
I saw a stacktrace when exiting sbtn on windows due to an interrupted
exception being thrown during thread joining. We only want to throw this
exception if we didn't successfully join the thread. I also noticed that
we would try to join the thread forever. There was supposed to be a
timelimit so that we would eventually stop blocking even if we were
unable to join the thread. The limit was set but not respected.
With sbtn, the system properties are passed in as regular command
arguments. We need to parse them before we call Terminal.withStreams or
else system properties like -Dsbt.color=false are ignored.
EvaluateTask was holding references to SafeState that could be quite
large. This was reported as #5992. In that project, I ran the `ci` task
and observed the OOM as reported. I took a heap dump prior to OOM and
got the retained size graph from visualvm (which took hours to compute).
The lastEvaluatedState was holding a reference to SafeState that was
1.7GB. The project max heap size was set to 2GB. Instead of using the
lastEvaluatedState, we can just use StandardMain.exchange.withState.
The cached instances of state were used for task cancellation and
completions. While it is possible that early on in booting
StandardMain.exchange.withState could return a null state, in practice
this won't happen because it is set early on during the sbt boot
commands.
After this change, I successfully ran the `ci` task in the #5992 issue
project with the same memory parameters as their ci config.
The ConsoleAppender formatEnabledInEnv field was being used both as an
indicator that ansi codes were supported and that color codes are
enabled. There are cases in which general ansi codes are not supported
but color codes are and these use cases need to be handled separately.
To make things more explicit, this commit adds isColorEnabled and
isAnsiSupported to the Terminal companion object so that we can be more
specific about what the requirements are (general ansi escape codes or
just colors). There are a few cases in ConsoleAppender itself where
formatEnabledInEnv was used to set flags for both color and ansi codes.
When that is the case, we use Terminal.isAnsiSupported because when that
is true, colors should at least work but there are terminals that
support color but not general ansi escape codes.
When project/target is a symbolic link, sbt 1.4.0 crashes on startup
because Files.createDirectories will throw a FileAlreadyExistsException.
The fix is to first check if the target directory exists before trying
to create it.
When sbt is starting up and there is an error with the build loading, we
need to read input from the user to determine to restart the build or
not. What is tricky is that there are potentially two sources of input:
thin clients connected through the boot server socket and the actual sbt
console process. If there are not connected thin clients and no system
console is available, we should return -1 in System.in.read, which will
cause sbt to exit.
A user reported that no prompt was displayed when they used sbt from the
jEdit console. The reason no prompt was displayed was because
System.console was null which caused the ConsoleChannel to be
initialized with its prompt set to NoPrompt. I don't remember why it was
doing this but this bug seems worse than whatever it was trying to
address.
In the client test, the sbt server would keep open the the client
connection even after it had exited because the client was only shutting
down its side of the connection. Since in the test it wasn't exiting the
jvm, the read side of the connection was still open.
It is possible for the test cases in ClientTest to block indefinitely.
To avoid that, we can instead run them on a background thread and cancel
the thread if that happens.