Commit Graph

71 Commits

Author SHA1 Message Date
kenji yoshida d560776a77
[2.x] refactor: Remove nowarn annotation in CoursierDependencyResolution (#9593) 2026-08-14 08:53:42 -04:00
eugene yokota bb141109e1
Merge pull request #9523 from hoangmaihuy/perf/update-report-interning
[2.x] perf: Intern `UpdateReport` values
2026-07-31 00:58:19 -04:00
Mai Huy Hoàng 3a79f269c7
[2.x] perf: Read the resolution's project cache once per report (#9522)
Resolution.projectCache is not a field: it maps projectCache0 into a
version-string-keyed copy on every call. SbtUpdateReport read it once per
dependency, and again per parent POM while assembling inherited licence info, so
for N modules resolved that is N rebuilds of an N-entry immutable map -- turning
a Resolution into an UpdateReport was quadratic in the modules it names.

On a 301-project build this was 61.9% of the CPU update spends, 83% of it
entering through lookupProject.

Read it once per report and reuse it, at every call site including the eviction
loop, which read it three times per conflict. The report produced is unchanged;
only the number of times the same map is built.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 01:17:04 -04:00
Mai Huy Hoàng b4a4b8d827 [2.x] perf: Intern the values an UpdateReport is built of
The projects of a build mostly depend on the same libraries, and each project's
report materializes its own copies of every coordinate it names, so one value
exists once per project that mentions it: on a 302-module monorepo the cached
reports hold 949,492 ModuleReports for 2,036 distinct values.

UpdateReportInterner adds weak pools for ConfigRef, InclExclRule, File,
Artifact, ModuleID, Caller and ModuleReport itself. Pooling the report is worth
more than pooling its parts alone, because sharing it also shares its licenses
vector, extraAttributes map, homepage string and artifacts vector. Reports
carrying a publicationDate are canonicalized but never pooled, since that
java.util.Calendar is mutable; everything else reachable from a ModuleReport is
immutable, so sharing is semantically invisible.

The pools are weak, so a value lives exactly as long as some report references
it and nothing accumulates across a reload.

Two sites cover a freshly resolved report. SbtUpdateReport interns each report
as it builds it rather than sweeping the finished one, so only the module under
construction is ever un-interned. That alone would not survive, though:
coursier memoizes moduleReport on a key that includes the dependees, so each
project builds its own instance of a shared coordinate, and transformDetails
then rebuilt every report to drop the callers -- discarding the sharing and
leaving a copy per module per configuration. Dropping the callers is what makes
those reports value-equal in the first place, so transformDetails now re-interns
what it rebuilds, and only rebuilds when there is something to drop. A scripted
test pins it: two projects resolving one coordinate must end up holding one
ModuleReport instance, on the fresh path and from the cache.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 09:43:09 +07:00
Anatolii Kmetiuk 3a37da86f3
[2.x] fix: Fixes dependency tree rendering on some libraries (#9371)
For the purposes of matching resolved dependencies to reverse-dependency entries, do not use dependency overrides to check equality.
2026-06-23 14:35:44 -04:00
Ali Rashid 3b097cc3cc
[2.x] fix: Fixes publishing platform-specific artifacts (like Scala Native)
**Problem**
Platform suffix is absent in published artifacts.
#9118 partially solved this. It didn't touch publish-side naming though, so the published files still drop the suffix in three places.

**Solution**
This fixes
- ivyless publication names - CoursierArtifactsTasks.coursierPublicationsTask
- ivyless POM <artifactId> (the coordinate written inside the .pom) - PomGenerator.crossVersionDep
- Ivy backend (useIvy := true) - CrossVersion.substituteCross via IvyActions
2026-06-03 21:07:02 -04:00
eugene yokota 315202181c
[2.x] ci: Scalafmt 3.11.1 (#9279)
Apply Scalafmt
2026-05-31 16:01:15 -04:00
BrianHotopp 0ee7323110
[2.x] fix: Parallelize dependency resolution when no progress bar is rendered (#9270)
update held a process-global lock around coursier resolution and artifact
fetching whenever a logger was set OR coursier was not in fallback mode. That
lock exists only to serialize coursier's interactive progress bar, which is
rendered solely when no custom logger is supplied and coursier is not in
fallback mode. The loggerOpt.nonEmpty clause therefore over-serialized the
common non-interactive case (IntelliJ re-imports, CI, any non-TTY run, where
sbt supplies a quiet debug-only logger), making update scale with the number
of modules rather than the number of distinct artifacts.

Fixes #5508.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 15:31:38 -04:00
Eugene Yokota f8504f2a4d Revert "[2.x] fix: Skip Conflict when dependency relocations form a cycle (#8919)"
This reverts commit b24ecddbd6.
2026-05-16 04:25:37 -04:00
xuwei-k 04d9f36414 Use Files.readString instead of readAllBytes 2026-05-13 21:21:18 +09:00
eugene yokota c491f035f8
[2.x] test: Port tests to use lm-coursier (#9205)
**Problem**
Some tests are failing.

**Solution**

* Port EvictionErrorSpec to lm-coursier
* Port EvictionWarningSpec to lm-coursier
* Port InclExclSpec to lm-coursier
* Port ZincComponentCompilerSpec to lm-coursier
* Apparently we still need lmIvy
2026-05-10 04:40:15 -04:00
Anatolii Kmetiuk 4ebacc6e05
[2.x] fix: Include platform suffix in Artifact.artifactName (#9118) 2026-04-21 22:58:34 -04:00
kenji yoshida 9d620f3b1f
[2.x] refactor: Use Files.writeString instead of Files.write (#9093) 2026-04-15 22:29:19 -04:00
Albert Meltzer fdccd8a569
[2.x] Prefer local ScalaModuleInfo over global config (#9028)
Otherwise, a user will never be able to download scala library at any
other version.
2026-04-05 18:41:30 -04:00
kenji yoshida 8ad6ada60f
[2.x] Scala 3.8.3 (#8997) 2026-04-05 14:28:47 -04:00
Dream 9a48ed818f
[2.x] fix: Preserve configuration visibility in ivy.xml when publishing with coursier (#8988)
**Problem**
When publishing with coursier, the `visibility` attribute of `<conf />`
elements in `ivy.xml` was hardcoded to `"public"`. Configurations
defined as hidden (e.g. `scala-tool`) were incorrectly published with
`visibility="public"` instead of `"private"`.

The root cause was that `Inputs.configExtendsSeq` only extracted config
names and extends relationships, discarding the `isPublic` flag from
sbt's `Configuration` objects.

**Solution**
Add a `privateConfigNames: Set[String]` field to the lmcoursier
`Project` data class (with `@since` for backward compatibility).
Populate it from `Configuration.isPublic` in `CoursierInputsTasks`,
and use it in both `IvyXml` implementations to set the correct
visibility attribute.

Fixes sbt/sbt#5455
2026-03-29 00:37:00 -04:00
kenji yoshida 6dcb601f73
Add scalafmt newlines.topLevelStatementBlankLines setting (#8949) 2026-03-21 02:58:49 -04:00
eugene yokota 9a1c41ab1e
[2.x] fix: Fixes non-typelevel scalaOrganization (#8945)
**Problem**
Coursier used to support only org.typelevel as scalaOrganization override.

**Solution**
This uses the newly added parameter in M24.
2026-03-20 12:31:14 -04:00
kenji yoshida 0608a660da
[2.x] refactor: Reduce return statements (#8925) 2026-03-19 20:09:31 -04:00
bitloi b24ecddbd6
[2.x] fix: Skip Conflict when dependency relocations form a cycle (#8919)
**Problem**
Coursier graph.Conflict -> DependencyTree relocation can loop forever when
Maven/Gradle relocation metadata forms a cycle (sbt-site 1.4.1).

**Solution**
Detect relocation cycles with the same step logic as Coursier, skip Conflict
for affected configs, log once per update.

Generated-by: Claude
2026-03-19 16:52:14 -04:00
kenji yoshida 14606c593d
[2.x] ci: Add scalafix DisableSyntax.noReturns (#8922) 2026-03-19 10:48:10 -04:00
Michał Pawlik 3f9bafc153
[2.x] fix: use new constructor for CantDownloadModule (#8905) 2026-03-14 14:39:15 -04:00
Michał Pawlik 866497c6e9
[2.x] Retry on HTTP 5xx during dependency resolution (#8903) 2026-03-14 02:24:20 -04:00
eugene yokota 39fa98ef79
[2.x] Update to Coursier 2.1.25-M24 (#8381)
This forward ports (https://github.com/coursier/sbt-coursier/pull/570), and follows along some of the migrated methods to work through the deprecations.
2026-03-13 22:57:38 -04:00
Dream ed96b4e1e0
[2.x] fix: Populate explicitArtifacts from classifier in UpdateReport (#8874)
**Problem**
When a dependency is declared with a classifier (e.g., classifier "linux-x86_64"),
the UpdateReport > ModuleReport.module.explicitArtifacts is empty. The classifier
data is available as Publication objects during Coursier resolution but is lost
when SbtUpdateReport reconstructs the ModuleID.

**Solution**
In SbtUpdateReport.moduleReport, extract explicit artifacts from Publications
with non-empty classifiers and apply them to the ModuleID used by ModuleReport.
This is done on a per-report copy to avoid mutating the shared moduleId cache.

Fixes #5491
2026-03-04 16:22:48 -05:00
kenji yoshida 4ba457d5d1
Use given instead of implicit val (#8870) 2026-03-03 23:17:28 -05:00
bitloi 09c4856409
[2.x] fix: Unresolved dependency error for Coursier (#8869)
Fixes unresolved dependency path reporting for Coursier (`ResolveException.failedPaths`) and adds a stable scripted regression.

This PR addresses 5168 by reconstructing unresolved dependency caller chains from the Coursier resolution graph and attaching them to `ResolveException.failedPaths`. That allows unresolved warnings to show the full path from the missing module up to the root project.

It also adds and stabilizes `lm-coursier/unresolved-path` scripted coverage by:
- using a local test Maven repo fixture (no flaky remote test dependency)
- checking update stream output via an sbt task (`checkLog`) instead of shell `grep`
- asserting the unresolved path includes missing module, transitive caller, and root project
2026-03-02 23:21:53 -05:00
Dream 0d01cc0b10
[2.x] refactor: Remove Ivy from update path and decouple lm-coursier from lm-ivy (#8832)
- **Remove `ivyModule` from `updateTask0`**: Replace `IvySbt#Module` with `moduleSettings` + `DependencyResolution.moduleDescriptor()`, eliminating the Ivy dependency in the update path.
- **Replace direct Ivy usage in `Load.scala` and `TemplateCommandUtil`**: Use Coursier's `DependencyResolution` API for plugin bootstrapping and template resolution instead of constructing `IvySbt` instances directly.
- **Break `lm-coursier`'s dependency on `lm-ivy`**: Remove `IvySbt#Module` pattern match from `CoursierDependencyResolution`, replace `IBiblioResolver` usage in `Resolvers` with reflection, and switch build dependencies from `lmIvy` to `lmCore`.

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:46:15 -05:00
Daniil Sivak 12cbd877bc
[2.x] fix: excluding artifacts w/o scala version suffix (#7454) (#8756)
**Problem**

Excluding artifacts using `.exclude(org, name)` requires you to
explicitly set scala version in `name`.

**Solution**

- Deprecating `.exclude(org, name)` in favor of new
  `.exclude(OrganizationArtifactName)`
- Fixing `lmcoursier.FromSbt` ignores `excludeRule.crossVersion`
2026-02-25 15:06:16 -05:00
kenji yoshida f976330759
Scala 3.8.2 (#8805) 2026-02-24 00:29:44 -05:00
kenji yoshida 62e43711f2
[2.x] refactor: Remove redundant conversions (#8786) 2026-02-22 23:44:17 -05:00
NeedmeFordev 2f14fd8bb1
implemente using PrettyPrinter instead of CompactPrinter (#8773) 2026-02-20 22:39:41 -05:00
bitloi ef6968e20c Path normalization for Windows + scalafmt
- CacheUrlConversion: normalize paths for comparison (forward slashes)
  and strip leading slash on Windows file URIs so cache matching works.
- Apply scalafmt to touched files.
2026-02-15 05:21:54 +01:00
bitloi afae6daea2 Fix #8741: dependencyLock no longer captures file:// URLs
- Add CacheUrlConversion in lm-coursier internal to convert cache file
  paths back to original repository URLs (single place for logic).
- CoursierDependencyResolution delegates to CacheUrlConversion.
- DependencyLockManager.createFromUpdateReport now accepts optional
  cacheDir; when an artifact has a file URL it either converts via
  cache dir (Coursier layout) or fails with a clear message.
- dependencyLock task passes csrCacheDirectory so lock file gets
  portable HTTPS URLs instead of machine-specific cache paths.

Expectation 1: Lock file contains original Maven Central (or repo) URLs.
Expectation 2: If conversion is not possible, lock creation fails.
2026-02-15 05:12:34 +01:00
PandaMan 3af62be0a3
[2.x] fix: Respect explicit platform settings in dependency resolution (#8697)
**Problem**
When platform is set, it incorrectly adds the platform suffix to implicit Scala library dependencies even though they explicitly set platform to jvm. This causes resolution errors.

**Solution**
Modified addPlatformSuffix to prioritize explicit platform settings on dependencies. If a dependency has an explicit platform, use that instead of the project platform. The project platform should only apply to dependencies without an explicit platform.

Fixes #8665
Generated-by: Claude Sonnet 4.5
2026-02-06 10:16:20 -05:00
bitloi 4c16466672
[2.x] feat: Support Maven BOM (Bill of Materials) (#8675)
**Consuming BOMs**

- You can declare a BOM with `.pomOnly()` and versionless deps with `"*"`:
  - `libraryDependencies += ("com.fasterxml.jackson" % "jackson-bom" % "2.21.0").pomOnly()`
  - `libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % "*"`
- BOMs are passed to Coursier via `Resolve.addBom()`; version `"*"` is resolved from the BOM.

**makePom**

- POM-only dependencies are emitted under `<dependencyManagement><dependencies>...</dependencies></dependencyManagement>` with `<type>pom</type>` and `<scope>import</scope>`.
- Dependencies with version `"*"` are emitted without a `<version>` element so Maven uses the BOM-managed version.

**Ivy / publishLocal emulation**

- When publishing to Ivy (e.g. `publishLocal`), BOM-resolved versions (deps that had `"*"`) are written into the published `ivy.xml` as forced dependencies (`force="true"`), so consumers that depend on this module get those versions.
2026-02-02 10:54:43 -05:00
Eugene Yokota 19ca2911d2 Scala 3.8.1 2026-01-24 04:52:28 -05:00
Eugene Yokota 9813e60fe3 refactor: Clean up infix etc 2026-01-24 04:52:28 -05:00
MkDev11 2a5746cf6c
[2.x] feat: Add dependency lock file support (#2989) (#8581)
**What it does**

When you run `dependencyLock`, sbt generates a `deps.lock` file that captures your resolved dependencies. This file can be checked into version control to ensure reproducible builds across different machines and CI environments.

**New tasks**

- **`dependencyLock`** - Generates the lock file from the current resolution
- **`dependencyLockCheck`** - Validates the lock file is up-to-date (fails build if stale)

**How it works**

The lock file stores a hash of your declared dependencies and resolvers. When dependencies change, the hash changes, and `dependencyLockCheck` will fail until you regenerate the lock file.

If no lock file exists, `dependencyLockCheck` passes silently - this allows gradual adoption.
2026-01-21 19:08:59 -05:00
MkDev11 81b6408f49
[2.x] feat: Add csrLocalArtifactsShouldBeCached setting for caching local artifacts (#8504)
This adds a new setting  that allows users to
configure Coursier's FileCache to cache local file:// artifacts. When enabled,
artifacts from local repositories are copied to the cache directory, which is
useful for scenarios like bundling compiler artifacts in a local repo for
offline use.

Fixes #7547
2026-01-12 19:17:55 -05:00
calm b4f73c9a7b
[2.x] fix: Invalidate update cache across commands when dependencies change (#8501)
**Problem**
When project A's dependencies changed and A was compiled in one command, project B (depending on A) would not invalidate its update cache in a subsequent command. This caused stale classpaths.

The root cause was that `depsUpdated` only checked `!stats.cached`, which only detected fresh resolves within the same command. When a dependency was served from cache (even if resolved fresh in a previous command), `cached` was marked `true`, causing incorrect cache reuse.

Debug scenario from issue:
sbt:aaa> clean
sbt:aaa> a/compile
sbt:aaa> show itTests/depsUpdated
[info] * false   <-- BUG: should be true

**Solution**
Added `stamp: String` field to `UpdateStats` that records when the update was resolved. This stamp persists across commands and enables accurate cross-command comparison:

- If any dependency's stamp > our cached stamp, we re-resolve
- Falls back to `!cached` check for backwards compatibility with old caches
- Using `String` type allows future transition from timestamps to content hashes
2026-01-12 16:17:51 -05:00
xuwei-k c0fe4dfb10 Add tailrec annotation 2026-01-11 16:33:45 +09:00
Eugene Yokota 3581b4a05b fix: Change URL usage to URI 2025-08-10 18:32:04 -04:00
Eugene Yokota 7bb55fc9fb Remove unused code 2025-08-03 16:03:00 -04:00
Eugene Yokota 41a9e3b952 fport: Add Resolver.sonatypeCentralRepo 2025-06-08 02:08:54 -04:00
Matt Dziuban 8b0bcc6fcf Revert use of WeakReferences for SbtUpdateReport cached values 2025-06-07 23:44:29 -04:00
Matt Dziuban 882a10a89f Ensure caching uses weak references for both keys and values 2025-06-07 23:39:22 -04:00
eugene yokota 84ebcd3c34
Merge pull request #8110 from xuwei-k/remove-unused-imports
[2.x] remove unused imports
2025-05-09 02:28:52 -07:00
xuwei-k 237f341d6f add `using` if explicitly providing arguments to methods defined with implicit 2025-05-09 16:48:39 +09:00
xuwei-k fa6daec812 remove unused imports 2025-05-09 16:46:48 +09:00