Deduplicate executable jar package entries. In the issue, the duplicate was something like:
(resource_managed/.../sbt/sbt.autoplugins, "sbt/sbt.autoplugins")
(classes/.../sbt/sbt.autoplugins, "sbt/sbt.autoplugins")
This is because copyResources copied autoplugin metadata to the classes directory.
Solution: when composing the packageBinMappings, differentiate between artifacts that come from class directory and from outside of it. If there is a duplicate, prefer resource that comes from outside of it.
Fixes#9009.
dependencyMode := DependencyMode.PlusOne strips every internal
project dependency from the compile classpath, even direct ones --
LibA/compile fails with Not found: CoreClass despite
LibA.dependsOn(Core). Direct mode happens to work today, but only by
accident (filterByDirectDeps matches against allDependencies, which
includes projectDependencies -- the bug surface is one step removed).
Root cause: ClasspathImpl.filterByPlusOne resolves the
direct-dep key set from UpdateReport, which only contains externally
resolved (LM) modules. Internal project refs never appear there, so
resolvedDirectKeys is empty for internal entries; plusOneKeys is
likewise empty; the final filter strips every internal classpath
entry whose moduleIDStr identifies an internal project. Diagnosis on
the issue by eureka0928.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes#6886.
dependencyTree, dependencyBrowseTree, and inspect tree re-explore
the same node once per incoming edge. In a DAG with N levels and M
children per node the rendered output is O(M^N) -- the OP needed
>16 GB heap, #7360 has a 6 GB heap dump, and Friendseeker's analysis
on the issue showed the exponential re-traversal directly.
Fix: track a visited set across the renderer's recursion. The first
time a node is encountered it is rendered in full; on subsequent
visits the entry collapses to a one-line +- <id> (*) (ASCII) or a
<id> (*) leaf (JSON), matching Maven's dependency:tree (*)
convention. Cycle detection (separate parents set, (cycle) marker)
is unchanged.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes#2998
When test is run at the prompt in a multi-project build,
sbt aggregates <proj>/test across subprojects. Each subproject's
TestResultLogger emits its own pass/fail summary inline, but the
aggregation layer never restated which projects failed. The final
"sbt.TestsFailedException" line surfaced no project names or failing
test classes, so on CI users had to scrollback-grep through thousands
of log lines to find what broke.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
**Problem**
We need some tooling to debug caching issues.
**Solution**
This adds an exeprimental execution log support,
which shows input and output of cached tasks.
**Problem**
Current MixedAnalyzingCompiler analysis cache caches using the last write,
assuming all writing happens via it. However, this doesn't work with
sbt 2.x caching system where the gz file under it can switch.
**Solution**
This switches to using caffeine caching, which includes file size
and file timestamp for local analysis caching.
**Problem**
Projects defined in subdirectory build.sbt files are
not correctly resolved to the base directory relative to the file.
**Solution**
Call resolveBase.
Bug 1: bgRun forks with inheritIO() instead of LoggedOutput
bgRunTask / bgRunMainTask resolve their fork options via (run / forkOptions), which inherits run / connectInput := true. That has two downstream consequences:
1. ForkRun.configLogged (in run/src/main/scala/sbt/Run.scala) skips installing OutputStrategy.LoggedOutput(log) whenever config.connectInput == true.
2. Fork.apply (in run/src/main/scala/sbt/Fork.scala) sees connectInput && outputStrategy == StdoutOutput and takes the interactiveFork path, which calls jpb.inheritIO().
Bug 2: Background-job log relay drops messages after the spawning task ends
Even after Bug 1 is fixed, LoggedOutput routes the forked process's stdout into the background ManagedLogger, whose appenders include a shared RelayAppender. The relay calls CommandExchange.logMessage(event), which uses isChannelOwner(c) to pick the target channel.
**Problem**
In sbt 2.x, forking still creates layered classloader in the worker process,
which doesn't work for some tests.
**Solution**
This provides an escape hatch to emulate the sbt 1.x semantics of
using the system classpath for testing.
**Problem**
`dependencyTree` with `--browse` can throw when desktop browse is unavailable (for example on Wayland/headless environments), causing command failure.
**Solution**
Handle unsupported desktop/browse actions and runtime browse failures gracefully by logging a warning instead of throwing, and add regression tests for unsupported/throwing desktop scenarios.
Generated-by: Cursor Codex 5.3
**Problem**
When using scala-native, we can't enable semanticdb etc
because of the platform-level platform.
**Solution**
Since compilerPlugin(...) is always going to be JVM,
just add an explicit JVM platform to the given ModuleID.
* Add Test configuration to evictionWarningOptions
* Add Test configuration to default evictionWarningOptions
* Deduplicate eviction errors based on callers.
* Update eviction error test for semantic versioning.
* Group evictions by configuration and update test.
**Problem**
When managedScalaInstance is set to false, we stopped creating
ScalaInstance, but the documentation says the user can
pull in their own dependencies.
**Solution**
Attempt to construct a ScalaInstance from update report
even when managedScalaInstance is set to false.
- Cache AutoPlugin.projectSettings and projectConfigurations via AutoPluginCache so they are evaluated once per plugin instance during build loading, not once per subproject (N×M → M)
- Make GroupedAutoPlugins.globalSettings a lazy val and pre-compute buildSettingsMap to avoid repeated aggregation
Rather than using the FileConverter to replace virtual paths, this uses the rootPaths directly. It only replaces a virtual path in a scalac option if the given segment of the option begins with the root path key.
**Problem**
consoleProject does not work with Scala 3 because the compiler bridge
does not implement REPL binding injection (scala/scala3#5069).
The bindings currentState, extracted, and cpHelpers are never
injected into the REPL session, causing Not found errors.
**Solution**
Work around the missing binding support by storing the three runtime
objects in a static holder (ConsoleProjectBindings) before launching
the REPL, and generating val definitions via initialCommands that
read from the holder. The original bindings are still passed to
Console to preserve Scala 2 backward compatibility.
Pass -Xrepl-interrupt-instrumentation:local to the REPL when the
consoleProject scala instance is 3.8 or newer. In local mode the
instrumented loader skips re-defining classpath classes and falls
through to standard parent-first delegation, so REPL code sees the
same singleton sbt.* and scala.* classes as the surrounding sbt
process — while still keeping interrupt support for REPL-defined code,
preserving Ctrl+C on long-running expressions like
(Compile / compile).eval.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes#3137. Adds discoverable English-name alternatives for the symbolic
cross-build commands using the | parser combinator, making them more
beginner-friendly without adding separate commands.
**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.
In sbt 2.x, running batch commands through the thin client (sbtn) suppresses stack traces for all tasks because the server's shell command unconditionally sets state.interactive = true. This causes LogManager.defaultTraceLevel to return -1 (suppressed) even when the client explicitly signals non-interactive (batch) mode via Attach(interactive=false).
This fixes the shell command to check the originating NetworkChannel's interactive flag before setting state.interactive, so thin client batch commands correctly get Int.MaxValue trace level and display full stack traces.
**Problem**
PomGenerator (introduced in #8873) was missing <description> and <url>
elements that the old Ivy-based MakePom included. Setting `description`
and `homepage` in build.sbt had no effect on the generated pom.xml.
**Solution**
Add makeDescription and makeHomePage helpers to PomGenerator, matching
the behavior of MakePom. Add test assertions for both fields.
Fixes#9054
**Problem**
Like File, Path normally captures the absolute path,
so likely not a good candidate for caching.
**Solution**
Ban it.
---------
Co-authored-by: Anatolii Kmetiuk <anatoliikmt@proton.me>
getFileProperty returned relative File objects when system properties
like sbt.global.base were set to relative paths (e.g. via -sbt-dir
../cache in .sbtopts). This caused an assertion failure in
IO.directoryURI: "Not absolute: ../cache/plugins".
Also fixes misleading scaladoc in SemanticSelector that claimed
`<=1.0` is equivalent to `<1.1.0` — they differ for pre-release
versions like 1.1.0-M1 (#4423).
Fixes#3729
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
**Problem**
When usePipelining := true in a multi-project build, sbt appends
-Ypickle-java and -Ypickle-write <path>/early.jar to scalacOptions
for fast parallel compilation. These flags were being leaked into the Scala
REPL, causing failure on console
**Solution**
Strip pipelining flags before forwarding to the REPL in Deafults.scala.