Skip to content

Fix MavenSettings value equality dropping LST-carried mirrors - #8189

Draft
pdelagrave wants to merge 4 commits into
mainfrom
pierre/maven-settings-value-equality
Draft

Fix MavenSettings value equality dropping LST-carried mirrors#8189
pdelagrave wants to merge 4 commits into
mainfrom
pierre/maven-settings-value-equality

Conversation

@pdelagrave

@pdelagrave pdelagrave commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What's changed?

MavenSettings and its nested types now compare by value. The class was annotated @EqualsAndHashCode(onlyExplicitlyIncluded = true) with no field included, so any two instances were equal and every instance had the same hash code, while the nested list-holder types compared by identity. The lazily computed mavenLocal cache field is excluded from equality, and toString now prints the non-credential fields.

MavenSettings#merge short-circuits on equal inputs and merges profiles, mirrors, servers, and proxies through one shared id-keyed helper, so entries without an id are no longer collapsed onto a single map key.

Since recipes construct a MavenPomDownloader per visited tag, MavenExecutionContextView now memoizes the effective settings and the mapped mirrors per parsed-settings instance (Caffeine, weak keys).

A new MavenCentralMirrorTest pins the guarantee that a mirrorOf=central (or *) mirror carried in an LST's MavenResolutionResult#getMavenSettings() redirects all metadata resolution to the mirror, including the implicitly added Maven Central repository and when the run-time ExecutionContext carries settings without any mirror, and that repo.maven.apache.org is never contacted. Equality and merge regression tests were added to MavenSettingsTest.

What's your motivation?

  • Organizations use <mirrorOf>central</mirrorOf> in their Maven settings to keep all dependency resolution on an internal repository manager, with public Maven Central often blocked at the network level. MavenExecutionContextView#getMirrors(MavenSettings) decides whether supplied settings override the mirrors on the execution context by comparing the two for equality. With the degenerate equals, that comparison always reported "same" whenever the context carried settings, so the mirrors of the effective settings computed per Merge provided and built MavenSettings #4956 were silently discarded and resolution fell through to public Maven Central. In environments where Central is blocked this manifests as long connection timeouts while the recipe run otherwise appears to succeed.

Anything in particular you'd like reviewers to focus on?

  • Value-based equals/hashCode on these mutable Jackson-bound classes: an audit found no hash-keyed or equality-dependent consumer anywhere besides the getMirrors guard, which value equality makes behave as its javadoc describes. I'd appreciate a second opinion on that.
  • MavenSecuritySettings and RawGradleModule carry the same annotation pattern but have no equality consumer today; they were left untouched to keep the change focused.

Have you considered any alternatives or workarounds?

A reference-equality check in the getMirrors guard would fix the known call sites without touching equals, but it leaves the identity-blind equality in place for the next consumer to trip on.

Checklist

  • I've added unit tests to cover both positive and negative cases

`@EqualsAndHashCode(onlyExplicitlyIncluded = true)` with no field included made any
two `MavenSettings` instances equal, so the settings-equality guard in
`MavenExecutionContextView#getMirrors(MavenSettings)` could never detect that supplied
settings differ from those on the execution context. A mirror carried only in an LST's
`MavenResolutionResult#getMavenSettings()` was silently dropped whenever the execution
context also carried settings, sending resolution to public Maven Central instead of
the mirror. Compare all nested settings types by value, excluding the lazily computed
`mavenLocal` cache.
Mirrors, profiles, and servers without an id collapsed onto a single null
map key during `MavenSettings` merge, so all but one such entry were
silently dropped. Merge all four entry types through one shared id-keyed
helper that keeps id-less entries from both sides and cannot collide with
real ids.
Recipes construct a `MavenPomDownloader` per visited tag, and merging plus
value-comparing two settings graphs on every construction is measurable
across large runs. Cache the merged settings and the mapped mirrors per
parsed-settings instance, invalidated when settings or mirrors are replaced
on the context.
…tion

Organizations use `mirrorOf=central` (or `*`) to keep resolution on an internal
repository manager, often with public Maven Central blocked at the network level.
These tests pin the guarantee that a mirror carried in the LST's Maven settings
redirects all metadata resolution to the mirror — including the implicitly added
Maven Central and when run-time execution context settings carry no mirror — and
that `repo.maven.apache.org` is never contacted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

1 participant