Skip to content

Fix dependency-reduced-pom exclusion loss for classifier-distinct duplicate deps (Maven 4)#820

Open
ascheman wants to merge 1 commit into
apache:masterfrom
aschemaven:mshade-819-drp-classifier-exclusions
Open

Fix dependency-reduced-pom exclusion loss for classifier-distinct duplicate deps (Maven 4)#820
ascheman wants to merge 1 commit into
apache:masterfrom
aschemaven:mshade-819-drp-classifier-exclusions

Conversation

@ascheman

Copy link
Copy Markdown
Contributor

What

Fixes the generated dependency-reduced-pom.xml dropping an <exclusion> on one of two classifier-distinct duplicate variants of a dependency under Maven 4 (e.g. b:0.2 keeps the exclusion, b:0.2:alt loses it).

Why

ShadeMojo.updateExcludesInDeps() walks a single conflict-resolved collect graph. Under Maven 4 the resolver prunes the duplicate transitive node (omitted for duplicate) under one variant, so the exclusion is re-attached to only that variant. This is stable, intended resolver behaviour (not a resolver bug); shade's own dependency keying is already classifier-aware.

Fix

Collect that graph with verbose conflict resolution (ConflictResolver.CONFIG_PROP_VERBOSE = STANDARD) on a copied session, so the omitted-duplicate node is retained as a marker; the existing walk then re-attaches the exclusion to both variants. Localized to the single collectDependencies call; no behaviour change on Maven 3.

Test

Covered by the existing ITs dep-reduced-pom-exclusions and MSHADE-467_parallel-dependency-reduced-pom (red on Maven 4 / green on Maven 3 before; green on both after). Full -P run-its verified locally: 83/0 on both Maven 4.0.0-SNAPSHOT and Maven 3.9.16.

Closes #819

Under Maven 4, ShadeMojo.updateExcludesInDeps() walks a single
conflict-resolved collect graph. The resolver prunes the duplicate
transitive node ("omitted for duplicate") under one of two
classifier-distinct variants of the same artifact, so the generated
dependency-reduced-pom keeps the <exclusion> on only one variant.

Collect that graph with verbose conflict resolution
(ConflictResolver.CONFIG_PROP_VERBOSE = STANDARD) so the omitted-duplicate
node is retained as a marker; the existing walk then re-attaches the
exclusion to both variants. No behaviour change on Maven 3.9.16.

Covered by the existing dep-reduced-pom-exclusions and
MSHADE-467_parallel-dependency-reduced-pom ITs.

Closes apache#819

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ascheman

Copy link
Copy Markdown
Contributor Author

Note on Maven 4 coverage: this repo's PR matrix runs Maven 3.9.16 only, so the green checks here confirm there is no Maven 3 regression but do not exercise the Maven 4 path this fixes.

For the Maven 4 evidence I ran the full -P run-its suite against the latest Apache Maven 4.0.0-SNAPSHOT distribution on a fork branch (informational job that downloads the snapshot dist and runs the ITs):

Locally the suite is also 83/0 on both Maven 4.0.0-SNAPSHOT and Maven 3.9.16.

@hboutemy
hboutemy requested a review from cstamas July 18, 2026 20:39
@hboutemy

Copy link
Copy Markdown
Member

one aspect surprises me: I thought that the change in Maven 4 was tied to Resolver 2
then I tested with Maven 3.10.0-RC1: 3.10 does not suffer from the same issue as Maven 4.0

is Maven 4.0 using Resolver 2 not exactly the same way as Maven 3.10 on these conflict-resolved dependencies?

@cstamas having your review on this PR would help, please, to be sure that analysis and update to m-shade-p is completely understood and accepted by people who really understand (I don't really understand myself :) )

@cstamas

cstamas commented Jul 19, 2026

Copy link
Copy Markdown
Member

one aspect surprises me: I thought that the change in Maven 4 was tied to Resolver 2 then I tested with Maven 3.10.0-RC1: 3.10 does not suffer from the same issue as Maven 4.0

is Maven 4.0 using Resolver 2 not exactly the same way as Maven 3.10 on these conflict-resolved dependencies?

Exactly the same issue in my eye as well. IF there are differences seen between Resolver 1 and Resolver 2, I would like to understand them better.

@ascheman can you create some simple reproducer for me to play with it?

@ascheman

Copy link
Copy Markdown
Contributor Author

@cstamas here you go — standalone reproducer (stock shade 3.6.0, no plugin build needed): https://github.com/aschemaven/mshade-819-reproducer

./run.sh <maven-home> builds a tiny project (test -> a (excl c); a -> b + b:alt; b -> c, artifacts in a bundled file repo) and prints which deps in the generated dependency-reduced-pom.xml carry the exclusion. Results here:

Maven b b:alt
3.9.16 (Resolver 1.x) 1 1
3.10.0-rc-1 (Resolver 2.0.20) 1 1
4.0.0-rc-5 1 0
4.0.x-SNAPSHOT (e1f82346) 1 0

So @hboutemy's observation holds: same Resolver 2 line, different outcome — the delta is on the Maven side, not the resolver version. Two more data points from the reproducer:

  • 4.0.0-rc-5 with -Daether.conflictResolver.verbose=trueb:alt gets its exclusion back. That is effectively what this PR does, scoped to the single collectDependencies call in updateExcludesInDeps instead of the whole session.
  • Both 3.10.0-rc-1 and 4.0.0-rc-5 use BfDependencyCollector (per -X), so it is not the collector implementation either.

What I don't understand myself yet: why 3.10's collected graph retains the duplicate c node under b:alt with verbose unset while 4.0's does not — that difference is exactly what the reproducer should let you dig into.

On test coverage: the existing ITs (dep-reduced-pom-exclusions, MSHADE-467_parallel-dependency-reduced-pom) already cover this scenario and go red/green accordingly — once #810 enables the Maven 4 CI they become the permanent guard. The reproducer just takes the shade build out of the loop for bisecting the Maven side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dependency-reduced POM drops <exclusion> on classifier-distinct duplicate dependencies (Maven 4)

3 participants