Commit Graph
491 Commits
Author SHA1 Message Date
eugene yokota 8753a98161 [2.x] fix: sbtn to retry on corrupt active.json (#9617)
**Problem**
sbtn gets stuck when active.json is corrupt.

**Solution**
Delete active.json, and retry.
2026-08-19 02:26:44 -04:00
BrianHotopp e8f40d68c3 [2.x] fix: sbtn to log connection errors
onClose now logs sbt server disconnected when the close wasn't initiated by the client.

Generated-by: Oh My Pi (kimi-code/k3)
2026-08-17 14:08:21 -04:00
kenji yoshida c5eac14c14 [2.x] refactor: Remove unused code (#9589) 2026-08-13 14:50:30 -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
eugene yokota 67924298f2 [2.x] fix: Fixes sbtn stdin race condition (#9521)
**Problem**
There's a race condition between per-byte readSystemIn notification
and one-byte-read thread lifecycle.

Note: One-byte-read thread was introduced as a solution to the problem
that switching the terminal between raw and canonical mode cannot happen
if it's blocked by read.

**Solution**
This eliminates the thread lifecycle issue by keeping the thread alive
throughout the lifecycle of sbtn itself.
read is still called on demand by the server readSystemIn notification.
2026-07-27 19:52:30 -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
Kevin Lee 97a1dc360b [2.x] fix: Fixes three test-classloader / jar-handle leaks in the sbt server JVM (#9485)
Three independent, pre-existing retention bugs kept the classloader of a
finished in-process test run -- and the open jar handles it holds -- alive
for the rest of the server session.

- JUnitXmlTestsListener: testSuite is an InheritableThreadLocal, so
  threads spawned during a run (e.g. async-framework pool workers) inherit
  a copy of the suite reference that remove() cannot reach.

- TestRecap.collect: the recap is stashed on State.attributes and outlives
  the command, so it must not retain live throwables.

- ClassLoaderCache: loaders evicted from delegate by clearExpiredLoaders
  are unreachable from the map and never enqueued on the ReferenceQueue, so
  neither clear()/close() nor the cleanup thread could ever close them.

SuiteResult now documents the retention hazard on throwables. Adds
deterministic, cross-platform tests for all three severed chains.
2026-07-23 18:05:37 -04:00
eugene yokota 3f073b0059 [2.x] Use JDK's Unix domain socket for bootserver (#9427)
Use JDK's Unix domain socket for bootserver.
2026-07-22 23:57:13 -04:00
BrianHotoppandClaude Opus 4.8 3de18d446f [2.x] fix: Propagate -java-home to a server the thin client starts (#9448)
The thin client (sbtn) parsed the launcher value flags (-java-home, -mem,
-jvm-debug, -sbt-dir, ...) but then dropped them. The space form was consumed
and discarded; the flag=value form fell through to the residual arguments and
was forwarded to the server verbatim, where --java-home=/path was rejected as a
command (`Not a valid command: --`).

When the client had to start a server (none running, no --server), the consumed
-java-home never reached the forked sbt launcher, so the server came up under
the default JVM and, in CI where the intended JDK is only reachable via
-java-home, failed to connect.

parseArgs now captures the consumed launcher value flags (both `flag value` and
`flag=value`) into Arguments.launcherValueArgs, and the cold-start fork re-passes
them to the sbt launcher so the server runs under the requested JVM. The client
tokenizes arguments by splitting on whitespace, which would otherwise fragment a
value that contains spaces (a Windows path like C:\Program Files\Java); parseArgs
tracks those split boundaries and rejoins a value flag's value. An empty flag=
value and a dangling flag with no value are consumed but not propagated, since
the launcher's require_arg would otherwise fail the fork.

The fork command construction is extracted into a pure, package-visible
serverCommand so a test can assert the propagated flag reaches the started
server. The sbt-launch-jar path is unchanged: it invokes java directly, with no
launcher to interpret the flag.

Fixes #9418

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-16 10:14:20 +09:00
eugene yokota 45a4e88adb [2.x] Tweak server startup message (#9429)
**Problem/Solution**
sbt 2.x uses client-server by default.
This makes the message a bit more obvious when the build is using a client.
2026-07-11 12:51:47 -04:00
BrianHotoppandClaude Fable 5 bcd7fe1fbc [2.x] fix: Probe for a live server before refusing to start (#9337)
Any IOException while creating the boot io socket was wrapped in
ServerAlreadyBootingException and reported as "sbt thinks that server
is already booting" with a stack trace, and non-interactive
invocations exited with code 2. Permission or path-length problems
with XDG_RUNTIME_DIR or the temp directory and Windows named-pipe
access errors all hit this, blocking sbt entirely (#6777). Raw
IOExceptions from the constructor (socket directory creation) were
not caught at all and crashed startup.

getSocketOrExit now connects to the socket (BootServerSocketProbe,
shared with the test suite) to check for a live server before
believing the exception.

Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-01 17:02:50 -04:00
Anatolii Kmetiuk 1d7b0d66c3 Fix #9358: preserve --allow-empty and --sbt-create in sbtArguments (#9370) 2026-06-23 15:03:21 +09:00
Eugene Yokota 0bab2066df [2.x] Reimplement FarmHash
**Problem**
sbtn and server uses FarmHash.

**Solution**
This reimplements FarmHash using Scala.
2026-05-31 16:07:28 -04:00
eugene yokota 315202181c [2.x] ci: Scalafmt 3.11.1 (#9279)
Apply Scalafmt
2026-05-31 16:01:15 -04:00
eugene yokota ffa8c14ca6 [2.x] Migrate FarmHash usage to xxhash64 (#9267)
Problem
ZAHa, which we use for FarmHash, uses Unsafe.

Solution
This ports xxhash64 to Scala.
2026-05-30 19:14:53 -04:00
kenji yoshida 6a1222ad06 [2.x] fix: Remove explicit equals and hashCode in LabeledFunctions (#9228) 2026-05-16 23:57:41 -04:00
kenji yoshida f454c05fe1 [2.x] refactor: Use scala.util.Using.resource instead of try-finally (#9230) 2026-05-16 05:51:07 -04:00
Eugene Yokota bf678f2d6a [2.x] fix: Fixes ctrl-c handling
**Problem**
Ctrl-C during client-side run gets interpreted in sbtn,
and shuts down the shell.

**Solution**
Ignore ctrl-c during client-side run.
2026-04-25 03:36:32 -04:00
bitloi 936a7e1ffb [2.x] fix: clear compiler bridge zinc cache on reboot dev (#9057)
Reboot dev now removes zinc/org.scala-sbt under the resolved global zinc
directory (same layout as ZincComponentManager secondary cache).

Closes #5735
2026-04-13 04:28:43 -04:00
eugene yokota 25dd9b7363 [2.x] fix: Fixes client-side run status (#9081)
**Problem**
In sbt 2.x, if we execute a run task from the shell,
and if the program fails, it ends up taking down the entire shell
because client-side run rethrows, which is not desirable
for the sbt shell.

**Solution**
1. Omit printing out success for ClientJobParams, which is the runinfo.
2. Print out success or error on the client-side for shell usage case.
2026-04-13 00:41:35 -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
Dream 544f56695a [2.x] feat: Add cacheVersion setting for global cache invalidation (#8993)
* [2.x] feat: Add cacheVersion setting for global cache invalidation

**Problem**
There was no escape hatch to invalidate all task caches when needed.

**Solution**
Add `Global / cacheVersion` setting that incorporates into the cache key
hash. Changing it invalidates all caches. Defaults to reading system
property `sbt.cacheversion`, or else 0L. When 0L, the hash is identical
to the previous behavior (backward compatible).

Fixes #8992

* [2.x] refactor: Simplify BuildWideCacheConfiguration and add cacheVersion test

- Replace auxiliary constructors with default parameter values
- Add unit test verifying cacheVersion invalidates the cache

* [2.x] fix: Restore auxiliary constructors for binary compatibility

* [2.x] test: Improve cacheVersion scripted test and add release note

- Scripted test now verifies cache invalidation via a counter
  that increments only when the task body actually executes
- Add release note documenting the cacheVersion setting
2026-04-01 11:23:10 +09: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
BitToby be305eb3a5 fix: Use sbt script in BSP config instead of hardcoded Java path (#8920)
**Problem**

sbt bspConfig writes the absolute path of the current Java binary into .bsp/sbt.json. When the user switches Java versions (via sdkman, cs java, etc.) or removes that JDK, the IDE fails to start the sbt BSP server because the hardcoded path is stale or gone.

**Solution**

When an sbt launcher script is available (via `sbt.script` system property or PATH lookup), generate:

"argv": ["/path/to/sbt", "bsp"]
2026-03-19 20:57:53 -04:00
DreamandClaude Opus 4.6 dc90f160df [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 <[email protected]>
2026-03-12 20:51:07 -04:00
kenji yoshida 963e38256c [2.x] ci: Update java file formatter plugin (#8892) 2026-03-10 11:19:48 -04:00
chrisrock1124 dd66216309 [2.x] fix: sbt --client fails if -mem is provided (#8831)
The bash launcher's runNativeClient() passed all original CLI args to
sbtn, only stripping --client. This caused sbtn to receive launcher
flags like -mem 10000, which NetworkClient.parseArgs() misclassified:
-mem went to sbtArguments and 10000 went to commandArgs, resulting in
a broken server start command.
2026-03-05 01:30:03 -05:00
Dream 8d9a0027e2 [2.x] fix: Print server stderr on startup failure (#8816)
**Problem**
When the sbt server fails to start (e.g. wrong JDK version), the client
only shows "failed to connect to server" hiding the actual error. The
server stderr is redirected to /dev/null to prevent Linux pipe buffer
deadlocks (#8442), so diagnostic output is lost.

**Solution**
Redirect server stderr to a temp file instead of /dev/null. When the
server fails to start (portfile never appears), read and print the temp
file contents before throwing ServerFailedException. The temp file is
cleaned up eagerly on both success and failure paths.

Fixes #8812
2026-02-26 00:31:09 -05: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
Eve 44b9ca7c2d [2.x] feat: client-side run env inheritance (#8752)
merge current env into client-side run env
2026-02-17 14:07:54 -05:00
eugene yokota edd7061f15 [2.x] Minimalist console (#8722)
**Problem**
Forked console currently pulls in full Zinc, which includes JLine.

**Solution**
This implements a lighter-weight, full Java ForkConsoleMain,
which no longer depends on JLine.
2026-02-09 10:55:44 -05:00
bitloi d633de5c3f [2.x] fix: Detect alias/task key name conflicts (#8659)
Problem
When a user defines an alias with a name that matches an existing task or setting key (e.g., `alias c = compile` when a custom task `c` exists), the alias silently wins and shadows the task.

Solution
Detect conflicts at alias creation time and fail with an error message:
```
Alias 'c' conflicts with a task or setting key of the same name. Use a different alias name to avoid ambiguity.
```
2026-01-31 17:56:42 -05:00
Dream a5f915bf87 [2.x] test: Migrate ClassLoaderCacheTest to verify.BasicTestSuite (#8534) 2026-01-19 17:13:21 -05:00
E.G 0ec5144a63 [2.x] test: Migrate parser specs to verify.BasicTestSuite (#8551)
Migrate the following test files from ScalaTest's AnyFlatSpec to
verify.BasicTestSuite, following the pattern established by other
test files in the sbt codebase:

- SizeParserSpec.scala (util-complete)
- MultiParserSpec.scala (main-command)

Changes in all files:
- Replace AnyFlatSpec class with BasicTestSuite object
- Convert 'should ... in' syntax to 'test(...)' syntax
- Use Scala 3 syntax with colon indentation
- Add 'end' markers
- Add explicit types where needed

Related to the ongoing test migration effort.
2026-01-18 14:33:04 -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
eugene yokota 4d7e0633a8 Revert "[2.x] feat: Enable musl static linking for sbtn on JDK 17+ (#8464)" (#8557)
This reverts commit e16298521b.
2026-01-16 00:06:28 -05:00
aka James4u dce915e794 [2.x] fix: Error "Exception in thread "sbt-socket-server" java.lang.NullPointerException" on exit (#8448)
Fixes #8538

The code was calling e.getMessage.contains() without checking if getMessage()
returns null. Changed to use Option(e.getMessage).exists() to safely handle
null values.
2026-01-15 11:06:51 -05:00
MkDev11 e16298521b [2.x] feat: Enable musl static linking for sbtn on JDK 17+ (#8464)
** Problem **

The sbtn (sbt thin client) native image on Linux currently depends on glibc because ipcsocket uses JNI for Unix domain sockets. When building with musl for static linking, the JNI library fails to load since musl doesn't support `dlopen`.

** Solution **

Instead of upgrading to ipcsocket 2.x (which isn't ready for production), I created a `UnixDomainSocketFactory` that detects JDK 17+ at runtime and uses the native `java.net.UnixDomainSocketAddress` API directly via reflection. This completely bypasses JNI on modern JDKs.

For older JDKs (8 and 11), the factory falls back to ipcsocket 1.6.3, which is stable and well-tested.

** How It Works **

The factory checks at startup whether `java.net.UnixDomainSocketAddress` is available:

- **JDK 17+**: Uses native NIO Unix domain sockets (no JNI, no native libraries)
- **JDK 8/11**: Falls back to ipcsocket's JNI-based implementation

This approach:
- Enables musl static linking on JDK 17+ without any native dependencies
- Maintains full backward compatibility with older JDKs
- Keeps the stable ipcsocket 1.6.3 instead of the unstable 2.x
2026-01-13 23:14:45 -05:00
Match 88e2f2704f [2.x] fix: Fixes --no-colors setting for sbtn (#8517) 2026-01-13 14:44:09 -05:00
MkDev11 add43bd230 feat: Set terminal window title when running applications (#8492)
Set window title to 'sbt <command>: <org> % <name> % <version>' when
running sbt run, runMain, bgRun, or bgRunMain.

For server-side runs, window title is set directly. For client-side runs (sbtn), window title is passed via RunInfo protocol
and set by NetworkClient.

Fixes #7586
2026-01-12 02:32:52 -05:00
calm329 476730aba2 fix: Prevent server subprocess hang on Linux (#8442) 2026-01-11 21:00:57 -08:00
xuwei-k c0fe4dfb10 Add tailrec annotation 2026-01-11 16:33:45 +09:00
Martin Duhem 37037357a3 Fix help command arguments parsing
Previously, some additional code was used to parse the arguments to the
`help` command and ensure that the remaining commands were consistent
with the desired state of sbt.

While this code worked well in sbt 1.x, and was helpful in getting `sbt
help new` to work as expected, this does not work in sbt 2, and is
actually not required.

This patch removes the additional code, which fixes the `help` command
in sbt.
2025-12-18 17:49:32 +01:00
Eugene Yokota d1e0a5a35d cleanFull 2025-11-23 14:45:21 -05:00
Eugene Yokota c8edb171ee [2.x] Adds cleanExpunge command
**Problem**
We might want to clear the disk cache.

**Solution**
This adds cleanExpunge command.
2025-11-22 23:12:18 -05:00
Eugene Yokota 4265b92aa4 perf: Cache content hash of binary files
**Problem**
sha256 is currently a bottleneck for no-op compilation.

**Solution**
This adds a local, in-memory cache of sha256 hashes of binary files
using their timestamp and file size.
The size of the digest cache can be configured using localDigestCacheByteSize,
which is set to 1MB by default.
2025-11-11 15:59:42 -05:00
Eugene Yokota 645908f597 Apply Contraband 2025-09-28 21:28:21 -04:00
xuwei-k 1a882b0dc3 remove some format: off comments 2025-09-24 18:49:30 +09:00
Eugene Yokota 2fa3159f18 Update to Contraband 0.8.0 2025-09-19 00:46:34 -04:00