From 409c69936e85c23f7f0f1fa1a3fd45eb02e78615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=B6kdemir?= Date: Wed, 14 Oct 2026 12:43:31 +0300 Subject: [PATCH] Fix skipping of version-range candidates --- .../bf/DependencyResolutionSkipper.java | 16 ++++++++++++- .../BfWithSkipperDependencyCollectorTest.java | 20 ++++++++++++++++ .../bf/DependencyResolutionSkipperTest.java | 24 +++++++++++++++++++ .../maven13430/maven13430_library_1.ini | 1 + .../maven13430/maven13430_library_2.ini | 1 + .../maven13430/maven13430_library_3.ini | 2 ++ .../maven13430/maven13430_parent_1.ini | 2 ++ .../maven13430/maven13430_range-asset_1.ini | 1 + .../maven13430/maven13430_root_1.ini | 3 +++ 9 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_1.ini create mode 100644 maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_2.ini create mode 100644 maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_3.ini create mode 100644 maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_parent_1.ini create mode 100644 maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_range-asset_1.ini create mode 100644 maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_root_1.ini diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipper.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipper.java index c27c15f4e2..2e5213924d 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipper.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipper.java @@ -250,6 +250,12 @@ private CacheManager(Function keyFunction) { } boolean isVersionConflict(DependencyNode node) { + if (isRangeDependency(node)) { + // A version range can select a different version than one already seen. Resolve it so its + // dependencies are available to the conflict resolver. + return false; + } + String ga = keyFunction.apply(node.getArtifact()); if (winnerGAs.containsKey(ga)) { Artifact result = winnerGAs.get(ga); @@ -261,12 +267,20 @@ boolean isVersionConflict(DependencyNode node) { void cacheWinner(DependencyNode node) { winners.put(node.getArtifact(), node); - winnerGAs.put(keyFunction.apply(node.getArtifact()), node.getArtifact()); + // A range candidate is not a reliable winner for the versionless key. + if (!isRangeDependency(node)) { + winnerGAs.put(keyFunction.apply(node.getArtifact()), node.getArtifact()); + } } boolean isDuplicate(DependencyNode node) { return winners.containsKey(node.getArtifact()); } + + private static boolean isRangeDependency(DependencyNode node) { + return node.getVersionConstraint() != null + && node.getVersionConstraint().getRange() != null; + } } private static final class CoordinateManager { diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java index 4876e40d59..583984520c 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/BfWithSkipperDependencyCollectorTest.java @@ -140,6 +140,26 @@ void testPoolCacheTransparencyWithTransitiveDependencyManager() throws Dependenc "c under b-alt should have d as a child"); } + @Test + void testVersionRangeCandidateDependenciesAreNotSkipped() throws DependencyCollectionException { + collector = setupCollector(newReader("maven13430/")); + + CollectResult result = collector.collectDependencies( + session, + new CollectRequest(newDep("maven13430:root:ext:1", "compile"), Collections.singletonList(repository))); + + assertEquals(0, result.getExceptions().size()); + + DependencyNode rangeCandidate = path(result.getRoot(), 0, 0); + assertEquals("library", rangeCandidate.getArtifact().getArtifactId()); + assertEquals("3", rangeCandidate.getArtifact().getVersion()); + assertTrue( + rangeCandidate.getChildren().stream() + .anyMatch( + node -> "range-asset".equals(node.getArtifact().getArtifactId())), + "dependencies of the resolved version-range candidate must be collected"); + } + @Test void testSkipperWithDifferentExclusion() throws DependencyCollectionException { collector = setupCollector(newReader("managed/")); diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipperTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipperTest.java index 3f6f5cd9a7..b971a2443a 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipperTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/bf/DependencyResolutionSkipperTest.java @@ -30,6 +30,7 @@ import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.internal.test.util.TestVersion; import org.eclipse.aether.internal.test.util.TestVersionConstraint; +import org.eclipse.aether.util.version.GenericVersionScheme; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -101,6 +102,29 @@ void testSkipVersionConflict() { } } + @Test + void testVersionRangeDoesNotReplaceVersionlessWinner() throws Exception { + DependencyNode pinned = makeDependencyNode("some-group", "A", "1.0"); + DefaultDependencyNode ranged = (DefaultDependencyNode) makeDependencyNode("some-group", "A", "3.0"); + ranged.setVersionConstraint(new GenericVersionScheme().parseVersionConstraint("[2.0,4.0)")); + DependencyNode pinnedAgain = makeDependencyNode("some-group", "A", "1.0"); + + try (DependencyResolutionSkipper.DefaultDependencyResolutionSkipper skipper = + DependencyResolutionSkipper.defaultGACESkipper()) { + assertFalse(skipper.skipResolution(pinned, new ArrayList<>())); + skipper.cache(pinned, new ArrayList<>()); + + assertFalse(skipper.skipResolution(ranged, new ArrayList<>())); + skipper.cache(ranged, new ArrayList<>()); + + assertTrue(skipper.skipResolution(pinnedAgain, new ArrayList<>())); + DependencyResolutionSkipper.DependencyResolutionResult result = + skipper.getResults().get(pinnedAgain); + assertTrue(result.skippedAsDuplicate); + assertFalse(result.skippedAsVersionConflict); + } + } + @Test void testSkipDeeperDuplicateNode() { // A -> B diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_1.ini new file mode 100644 index 0000000000..61a252c235 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_1.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_2.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_2.ini new file mode 100644 index 0000000000..61a252c235 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_2.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_3.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_3.ini new file mode 100644 index 0000000000..dad0a3c16d --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_library_3.ini @@ -0,0 +1,2 @@ +[dependencies] +maven13430:range-asset:ext:1 diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_parent_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_parent_1.ini new file mode 100644 index 0000000000..792ffd5053 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_parent_1.ini @@ -0,0 +1,2 @@ +[dependencies] +maven13430:library:ext:[2,4) diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_range-asset_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_range-asset_1.ini new file mode 100644 index 0000000000..61a252c235 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_range-asset_1.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_root_1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_root_1.ini new file mode 100644 index 0000000000..6fc4dfa04c --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/maven13430/maven13430_root_1.ini @@ -0,0 +1,3 @@ +[dependencies] +maven13430:parent:ext:1 +maven13430:library:ext:1