Commit Graph
168 Commits
Author SHA1 Message Date
Mai Huy HoàngandClaude Opus 5 983e6a14c0 [2.x] fix: Make sbtn's result line consistent with sbt --server (#9783)
**Problem**
sbt compile through the thin client prints only elapsed time: 2 s, where the
same command in the shell or under sbt --server prints
elapsed time: 2 s, cache 94%, 13 disk cache hits, 24 remote cache hits. The
summary is computed server-side and thrown away: ManagedLogger.success is gated
on Terminal.isSuccessEnabled, and a NetworkChannel's terminal answered
interactive.get || isInWatch, which is false whenever a command is passed on
the command line. The line the user sees is the client's own, built from
wall-clock alone.

**Solution**
Report the line from the server, and have the client print only when the server
will not.

NetworkChannel's terminal reports isSuccessEnabled = true, so the server
writes the line on every channel, and it advertises successLog in its
capabilities. A server from before this sends no such key, which reads as false,
so an older client-server pair behaves as it does today; an unattached client
also always prints, since it renders build/logMessage rather than the proxied
systemOut bytes. Older sbtn keeps printing its own line and so reports
success twice until it updates.

Generated-by: Claude Opus 5

Claude-Session: https://claude.ai/code/session_015BqrfmHbJUph6Kx7gJn3G8

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-09-21 00:06:51 -04:00
Stas Shevchenko 4eba898c9e [2.x] fix: let one client at a time restart the server (#9708)
Two invocations that both find different -D options could interleave, the second
one connecting to the server the first had just started and shutting that down
mid-build. The restart now holds the connection file and reads it again once it
has it, so a replacement that already carries the right options is left alone.
2026-09-12 18:56:21 -04:00
Eugene Yokota f9688c1464 Apply Scalafmt format (Scala 3 syntax) 2026-09-10 14:16:27 -04:00
Albert MeltzerandClaude Opus 5 dbeeb199aa [2.x] fix: Stop a displaced server (#9713)
**Problem**
If a client cannot reach the server, it deletes the portfile. Then it
starts a second server. The first server is displaced: its socket path
now belongs to the second server.

A displaced server keeps running. A dropIfIdle notification cannot
reach it, because the proc file it registered names the socket that
the second server now owns.

**Solution**
The portfile holds the serverId of whichever server wrote it. Watch
that file, and exit when the id is not this server's. Leave the
portfile to the server that owns it.

---------

Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
2026-09-10 12:55:11 -04:00
Stas Shevchenkoandeugene yokota f389e676cd fix: restart the sbt server when -D options change (#9685)
* fix: restart the sbt server when -D options change

* fix: don't restart on completions, wait for the socket

* fix: only trust -D options recorded for this build

* fix: confirm the server left before reporting it gone

* Update protocol/src/main/contraband/portfile.contra

Co-authored-by: eugene yokota <[email protected]>

* fix: record the server -D options as a list

* fix: record the -D options without their values

The connection file keeps the name of each option and a salted digest of it
rather than the option itself, and the comparison follows the JVM in taking the
last definition of a name. A client that is not allowed to restart the server
says which options it cannot pick up instead of staying quiet about them.

* fix: compare the -D options given before a command

A trailing -D option used to switch the whole comparison off, which dropped the
options written before it, and a shutdown request that never reached the server
waited the full timeout before saying so.

* fix: leave a server no client started alone

The connection file says whether its recorded options are the whole story, so a
server an editor keeps is warned about instead of shut down, while one the client
started with no options is still replaced. A restart that cannot reach the server
warns and carries on rather than failing the invocation.

* build: filter NetworkClient clinit in MiMa

---------

Co-authored-by: eugene yokota <[email protected]>
2026-09-08 11:46:36 +09:00
Anatolii Kmetiukandeugene yokota 0da3f6b478 [2.x] Add test result cache opt-out (#9675)
* [2.x] Add test result cache opt-out

* Update main/src/main/scala/sbt/internal/SysProp.scala

Co-authored-by: eugene yokota <[email protected]>

* Use Boolean values for test cache opt-out

---------

Co-authored-by: eugene yokota <[email protected]>
2026-08-26 11:27:05 +09:00
stasimus 56f38a19a4 fix: disable BSP over TCP and gate requests before auth 2026-08-20 10:45:19 +02:00
azdrojowa123andClaude Opus 4.8 3045cd0c46 [2.x] Add a resolvedScalacOptions task that resolves cache placeholders (#9610)
Add a resolvedScalacOptions task that resolves cache placeholders in scalacOptions to absolute machine paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-19 05:36:38 -04:00
eugene yokota 27c3f035e5 [2.x] feat: Test summary (#9602)
**Problem/Solution**
This extends the idea started with TestRecap, and applies it to
both test success and failures.

1. Existing TestResultLogger trait is extended to handle the summary
   rendering.
2. TestSummary enum is added to control the verbosity via
   commandline option, system property, or a setting.
3. Script test captures the log.
2026-08-17 23:54:32 -04:00
kenji yoshida a3dad963f0 [2.x] refactor: Remove redundant String.toString (#9592) 2026-08-13 13:49:06 -04:00
kenji yoshida d9f60b6cfd [2.x] refactor: Add tailrec annotation (#9591) 2026-08-13 13:48:02 -04:00
Eugene Yokota fb233e9411 [2.x] Retire textDocument/definition 2026-08-06 14:02:51 -04:00
Eugene Yokota e6ac4ecffc [2.x] fix: Gate LSP calls behind auth
**Problem**
Some custom LSP calls do not check initialize-handshake,
which over TCP includes token-based authentication.

**Solution**
This adds checkAuthenticated check around sbt/exec etc.
2026-08-06 14:02:51 -04:00
BrianHotopp b0c840105b [2.x] fix: Bound the client boot wait when the forked server never starts (#9549)
The thin client's blockUntilStart loop recursed while the portfile was
missing and the forked process looked valid, with no deadline: a forked
server that died before writing project/target/active.json, or stayed
alive but wedged, hung the client forever with no output. On Windows the
check ignored process death entirely (Properties.isWin short-circuited
the liveness test), making the hang unconditional there.

The wait is now bounded (default 5 minutes, tunable with
-Dsbt.client.boot.timeout.seconds). On expiry the client fails with a
"did not start within N seconds" message and then prints the server's
captured stderr, instead of hanging silently (#9484). The Windows
liveness workaround is preserved; the deadline is what bounds it.

Generated-by: kimi-code/k3 (Oh My Pi)
2026-08-04 15:59:48 -04:00
BrianHotopp c407f37739 [2.x] fix: Don't strand the server when a client dies with a terminal query unanswered (#9527)
A client disconnecting with a terminal control query outstanding could park a
server thread forever, wedging prompts and command dispatch for every client
(#6841, #6840):

- VirtualTerminal.cancelRequests drained only 2 of the 8 pending terminal
  maps, so waiters on the set-echo, raw-mode, attributes, and size queues were
  never woken. It now drains all of them, with offer instead of put so the
  shutdown path itself cannot block on a full queue.
- Raw-mode requests were registered in the set-echo map, so their waiters were
  invisible to any raw-mode-specific handling.
- Closing a channel terminal did not wake readers parked on its input stream;
  close now delivers EOF so a prompt blocked on a dead client's input unwinds.
- The failed-load prompt read its answer byte from System.in, which under
  non-virtual IO is the process's own stdin and never carries client input; it
  now reads the active terminal's input stream.
- ServerSessionImpl.close() could not deliver EOF to the peer while its read
  thread was parked in a native read (the native close is never delivered), so
  the server never noticed orderly client disconnects at all. It now shuts
  down socket input first, which wakes the reader and lets the close through.

Regression test: a raw-protocol client that attaches, triggers the failed-load
prompt without answering the raw-mode query, and disconnects; the server must
shut down cleanly (EOF at the prompt maps to 'q') instead of staying parked
forever. Fails on develop with the server still alive and the command loop
parked in setRawMode; passes with this change. VirtualTerminalSpec pins the
drain across all eight maps and that other channels are untouched.

Generated-by: kimi-code/k3 (Oh My Pi)
2026-08-02 02:35:39 -04:00
BrianHotoppandClaude Fable 5 1bde3d23a9 [2.x] fix: Don't freeze the server when a terminal-properties response is malformed or slow (#9526)
One attached client answering the sbt/terminalpropertiesquery request badly, or
slower than 5 seconds, could freeze the whole server for every client:

- The response handler dropped malformed responses (response.foreach(buffer.put))
  instead of falling back to a default like every sibling handler, so the updater
  thread waiting on the queue timed out with the properties reference still null.
- getProperties(block = true) waits while properties is null, but nothing
  completes it after the updater's one-shot 5-second poll times out: waiters woke
  from the notify, saw null, and waited again with no updater outstanding. The
  1-second lastUpdate throttle also let a caller start waiting with no query in
  flight at all, and the wait condition was checked outside the pending monitor,
  losing wakeups that fired between the check and the wait.
- A response arriving after the poll timeout was delivered into a queue that was
  never deregistered, so it neither set properties nor woke anyone.

The threads that block here include the command loop iterating channels and the
fast-track thread handling attach and cancel, so one bad or briefly-stalled
client wedged prompts, Ctrl-C, and command dispatch server-wide until that
client disconnected.

The properties response handler now falls back to a default like its siblings;
the updater expires its query on timeout, deregistering it (rescuing a response
that raced in) and completing properties with the empty default so waiters
always make progress; and both wait sites hold the pending monitor and gate on
the query in flight. waitForPending gets the same treatment, since it seeds
lazy vals whose initialization otherwise parks every thread touching them.

Regression test: a raw-protocol session that answers every server request with
a result of the wrong shape attaches interactively; a well-behaved batch client
must then still be served twice. Fails on develop with a three-minute timeout
(the server is frozen), passes with this change. A unit spec pins the expiry
semantics, including the late-response rescue.

Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-28 22:58:56 -04:00
Jozef Koval 8e3c25c1f1 [2.x] fix: Make forked run inherit sbt's working directory (#9442)
forked run used the project's baseDirectory as the working directory, while non-forked execution inherits sbt's own working directory — so toggling fork silently changed how relative paths resolved.

forked run (and forked console) now inherit sbt's working directory, consistent with non-forked execution and `sbtn` expectations.
2026-07-26 14:48:37 -04:00
BrianHotoppandClaude Opus 4.8 c78d6af748 [2.x] fix: Complete server teardown before logging so reboot works from sbtn (#9497)
Running reboot in the sbt shell dropped to the OS shell instead of rebooting.
The break was in teardown: Server.shutdown opened with
log.info, and during a client-initiated reboot the terminal in scope is that
client's already-closed virtual terminal, so the log write throws
ClosedChannelException through the terminal proxy. That aborted teardown
before the portfile was deleted and the server socket closed, and the
exception was swallowed by the shutdown hook (whose own error print goes to
the same dead terminal).

Server.shutdown now completes its state cleanup (portfile, tokenfile, running
flag, server socket) before logging, and CommandExchange.shutdown wraps each
channel shutdown and the server shutdown individually so one failing step
cannot skip the rest.

Fixes #9095

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-26 01:06:36 -04:00
Anatolii Kmetiuk 4ed16c96ce [2.x] Fix publishDiagnostics propagation (#9376)
**Problem**
Test is based on https://github.com/sbt/sbt/issues/9345#issuecomment-4718229113 which gives us the following sequence:

1. Metals sends buildTarget/compile.
2. sbt publishes real non-empty diagnostics.
3. Metals sends buildTarget/scalaMainClasses.
4. During that request, sbt emits build/publishDiagnostics with diagnostics: [] and reset: true.
5. The following build/taskFinish still reports errors: 1.

Previously, errors for diagnostics reporting via bsp were collected from a live compilation run. In the sequence above, that is triggered by buildTarget/compile. Then, buildTarget/scalaMainClasses does not trigger such a run for the second time, it uses the cached compilation result. Therefore, the diagnostics is not populated.

**Solution**
The proposed fix modifies sendFailureReport to accept an optional CompileFailed object that contains the diagnostics even in case the actual compiler did not run because the cached result was used. If no problems were found for a file via default means, this CompileFailed object is queried to see if it has any information about problems in a given file.
2026-06-26 12:36:42 -04:00
eugene yokota b9e98b9e8a [2.x] Update to Scala 3.8.4 (#9302) 2026-06-07 20:52:13 -04:00
eugene yokota 315202181c [2.x] ci: Scalafmt 3.11.1 (#9279)
Apply Scalafmt
2026-05-31 16:01:15 -04:00
Full Stack Developer 60cbde453f [2.x] feat: Implement BSP buildTarget/dependencyModules (#9085)
- implement BSP buildTarget/dependencyModules endpoint support in sbt
2026-04-14 23:07:51 -04:00
BrianHotoppandClaude Opus 4.6 d765ba263a [2.x] fix: Return JSON-RPC error for unknown server methods (#9002)
The fallback ServerHandler silently dropped requests with unknown
methods, violating the JSON-RPC spec. Clients like Metals that send
unrecognized requests would never receive a response, potentially
causing timeouts or hangs.

Return a -32601 (Method not found) error response instead.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
2026-04-10 01:33:20 -04:00
kenji yoshida 8ad6ada60f [2.x] Scala 3.8.3 (#8997) 2026-04-05 14:28:47 -04:00
kenji yoshida 6d44aca9b1 Add parentheses (#9000) 2026-03-31 13:48:59 -04:00
Daniil Sivak 9939666a33 [2.x] fix: server-test and related refactoring (#8904)
- TestServer was replaced with ServerSession class, which is located in protocol module and allows you to interact with JSON-RPC sbt server.
2026-03-21 23:45:37 -04:00
bitloi 130a332100 [2.x] feat: sbtn subscription level (#8796)
Closes #4399

- Add subscribeToAll to InitializeOption (protocol); default true for backward compatibility.
- CommandExchange: send broadcast notifyEvent/logMessage only to channels with subscribeToAll.
- TestServer: support subscribeToAll parameter for tests; AbstractServerTest: subscribeToAllForTest.
- ClientSubscriptionTest: assert default client receives build/logMessage when command runs.
- Scripted test server/client-subscription: run show name to exercise server client path.
2026-02-24 21:46:37 -05:00
kenji yoshida f976330759 Scala 3.8.2 (#8805) 2026-02-24 00:29:44 -05:00
Pluto 0cae58403f [2.x] fix: handle --version in sbt 2.x project dirs (sbt#8717) (#8735)
**Problem**
`sbt --version` in sbt 2.x project directories was delegated to the native client, which could try to start/connect to a server instead of printing version info.

**Solution**
Skip native-client delegation when `--version` is requested, and add runner-script tests for sbt 1.x and 2.x project variants.
2026-02-13 09:10:51 -08:00
PandaMan 95c6d42f8e [2.x] fix : BSP compile returns StatusCode.Error on failure (#8104) (#8709)
- BuildServerProtocol: for Result.Inc(cause), return StatusCode.Error for any
  non-InterruptedException (was throwing for non-CompileFailed, causing JSON-RPC
  error instead of BspCompileResult with statusCode Error)
- BuildServerTest: add test 'buildTarget/compile - returns StatusCode.Error
  when compilation fails' (introduce compile error, compile via BSP, assert
  statusCode == Error)
2026-02-07 11:01:49 -05:00
eugene yokota 080ce8f00e [2.x] Extend 2.x universe to BinCompatV (#8667)
**Problem**
Some scripted tests are failing due to the fact that -bin-SNAPSHOT
isn't being recognized.

**Solution**
This fixes sbtApiVersion to recognize BinCompatV.
2026-01-31 23:29:50 -05:00
bitloi 1ad6b88742 [2.x] feat: Per-channel project cursor for multi-client server mode (#8649)
**Problem**
When multiple clients connect to the same sbt server, they all share the same "current project" state. When one client switches projects with `project X`, all other clients see that change.

**Solution**
Store per-channel project cursors in State attributes. Each client maintains its own cursor that tracks which project it has selected.
2026-01-29 23:15:39 -05:00
Eugene Yokota 19ca2911d2 Scala 3.8.1 2026-01-24 04:52:28 -05:00
bitloi c832fad7b5 [2.x] feat: Notify sbtn client when command is queued (#8568)
Fixes #8356

**Problem**

When `sbtn` sends a command while another long-running task (like `console`) is already executing, the client silently blocks with no indication that the command is waiting in a queue.

**Solution**

When a new command arrives via the network channel and another command is currently running, the server now sends an `ExecStatusEvent` notification with status `"Queued"` to the client. The client displays a message like:

```
[info] waiting for: console
```
2026-01-16 16:17:00 -05:00
kenji yoshida 072181499a Fix BuildServerTest (#8475) 2026-01-11 07:20:10 -05:00
Eugene Yokota e3f99d39cb Merge branch '1.12.x' into wip/merge-1.12.x 2026-01-05 00:08:21 -05:00
xuwei-k 70960744e7 Scala 2.12.21 2025-12-09 17:28:03 +09:00
Eugene Yokota 6a2e0a9b04 [2.x] perf: Avoid copying directories
**Problem**
Directory copying is showing up as performance hot spots.

**Solution**
This avoid copying classes or resources.
2025-11-17 05:25:59 -05:00
xuwei-k 64357d7e2a Scala 3.7.3 2025-09-09 12:31:28 +09:00
Eugene Yokota cad02c05e0 Comment out reload test 2025-08-16 14:53:05 -04:00
xuwei-k 5581f5fd1a Scala 3.7.2 2025-07-30 09:55:46 +09:00
Eugene Yokota 6a7b56a645 Default to cached task
This flips the default `:=` operation to the cached task.
To opt out of the cache, use `Def.uncached(...)` or
mark the key with `@cacheLevel(include = Array.empty)`
2025-06-21 08:54:51 +09:00
xuwei-k b1eff478ce Scala 3.7.1 2025-06-03 07:50:08 +09:00
Eugene Yokota 967ecb49bc deps: Scala 3.7.0 2025-05-11 01:30:07 -04:00
Eugene Yokota de5c9b1869 Scala 3.6.4 2025-03-10 01:51:32 -04:00
Eugene Yokota 8db8c79d33 Implement client-side run
**Problem**
`run` task has been emulated via function call inside of a sandboxed classloader,
and blocking the command processing of sbt server loop.
This poses isolation and availability issues.

**Solution**
This implements client-side run where the server creates a sandbox environment, and sends the information to the client,
and the client forks a new JVM to perform the run.
The client-side behavior has been implemented in sbtn side already.
2025-03-09 15:00:24 -04:00
Eugene Yokota 2c3c0f4a7c Merge branch '1.10.x' into wip/merge-1.10.x 2025-03-08 19:05:30 -05:00
Eugene Yokota 5d5fe21ec5 Revert run switching on 1.x
**Problem**
client-side run apparently won't work for Scala.JS,
so forcing sbtn users to client-side run will break the Scala.JS users.

**Solution**
This reverts the client-side run on sbt 1.x, while retaining the
mechanism for sbt 2.x usages via sbtn.
Now, if `run / connectInput := true` is true, stdout will not display on sbtn.
2025-03-03 04:59:36 -05:00
Eugene Yokota a18ed19cbc fix: Use JDK path, not JRE path
**Problem**
There are a few places where javaHome or java path is set,
using java.home system property. The problem is that it points to JRE,
not JDK, so it would break on Java compilation etc.

**Solution**
If the path ends with jre, go up one directory.
2025-03-03 02:31:44 -05:00
Eugene Yokota 67265638c6 Implement client-side run
**Problem**
`run` task blocks the server, but during the run the server is just
waiting for the built program to finish.

**Solution**
This implements client-side run where the server creates a sandbox
environment, and sends the information to the client,
and the client forks a new JVM to perform the run.
2025-03-02 20:45:04 -05:00