Skip to content

Commit 45a59ec

Browse files
authored
Merge pull request #133 from gradlex-org/capability-version-override
Allow overriding a capability with a different capability version
2 parents 3cccdc6 + 1f223f6 commit 45a59ec

File tree

3 files changed

+106
-7
lines changed

3 files changed

+106
-7
lines changed

src/main/java/org/gradlex/jvm/dependency/conflict/detection/rules/CapabilityDefinitionRule.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,16 @@ public CapabilityDefinitionRule(CapabilityDefinition definition) {
3838
public final void execute(ComponentMetadataContext context) {
3939
if (shouldApply(context.getDetails().getId())) {
4040
context.getDetails().allVariants(variant -> {
41-
variant.withCapabilities(capabilities -> capabilities.addCapability(
42-
definition.getGroup(), definition.getCapabilityName(), getVersion(context.getDetails().getId())
43-
));
41+
variant.withCapabilities(capabilities -> {
42+
// remove capability if it already exists so that it can be added back
43+
// with a potentially different version
44+
capabilities.removeCapability(
45+
definition.getGroup(), definition.getCapabilityName()
46+
);
47+
capabilities.addCapability(
48+
definition.getGroup(), definition.getCapabilityName(), getVersion(context.getDetails().getId())
49+
);
50+
});
4451
additionalAdjustments(variant);
4552
});
4653
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package org.gradlex.jvm.dependency.conflict.test
2+
3+
import org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild
4+
import spock.lang.Specification
5+
6+
import static org.gradlex.jvm.dependency.conflict.test.fixture.GradleBuild.GRADLE6_TEST
7+
8+
class CapabilityWithDifferentVersionsTest extends Specification {
9+
10+
@Delegate
11+
GradleBuild build = new GradleBuild()
12+
13+
def "does not fail if capability is added several times with different versions"() {
14+
given:
15+
buildFile << """
16+
plugins {
17+
id("org.gradlex.jvm-dependency-conflict-detection") apply false
18+
id("java-library")
19+
}
20+
repositories.mavenCentral()
21+
dependencies.components {
22+
withModule("com.google.guava:guava") {
23+
allVariants {
24+
withCapabilities {
25+
addCapability("com.google.guava", "listenablefuture",
26+
"9999.0-empty-to-avoid-conflict-with-guava")
27+
}
28+
}
29+
}
30+
}
31+
32+
apply(plugin = "org.gradlex.jvm-dependency-conflict-detection")
33+
34+
dependencies {
35+
api("com.google.guava:guava:33.0.0-jre")
36+
}
37+
38+
tasks.register("printJars") {
39+
println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name })
40+
}
41+
"""
42+
if (GRADLE6_TEST) { configureEnvAttribute() }
43+
44+
expect:
45+
printJars()
46+
}
47+
48+
def "does not fail with empty listenable future dependency on the classpath"() {
49+
given:
50+
buildFile << """
51+
plugins {
52+
id("org.gradlex.jvm-dependency-conflict-resolution")
53+
id("java-library")
54+
}
55+
tasks.withType<JavaCompile>().configureEach {
56+
options.release.set(17)
57+
}
58+
repositories.mavenCentral()
59+
dependencies {
60+
implementation(platform("com.google.cloud:spring-cloud-gcp-dependencies:5.2.0"))
61+
implementation("com.google.cloud:spring-cloud-gcp-starter-bigquery")
62+
}
63+
64+
tasks.register("printJars") {
65+
println(configurations.compileClasspath.get().files.joinToString("\\n") { it.name })
66+
}
67+
"""
68+
if (GRADLE6_TEST) { configureEnvAttribute() }
69+
70+
expect:
71+
printJars()
72+
}
73+
74+
void configureEnvAttribute() {
75+
buildFile << """
76+
val envAttribute = Attribute.of("org.gradle.jvm.environment", String::class.java)
77+
configurations.compileClasspath {
78+
attributes.attribute(envAttribute, "standard-jvm")
79+
}
80+
"""
81+
}
82+
}

src/test/groovy/org/gradlex/jvm/dependency/conflict/test/GuavaClasspathTest.groovy

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ class GuavaClasspathTest extends Specification {
1717

1818
static allGuavaVersions() {
1919
[
20+
['33.2.0', 'jre' , [errorProne: '2.26.1', j2objc: '3.0.0', jsr305: '3.0.2', checker: '3.42.0', failureaccess: '1.0.2']],
21+
['33.2.0', 'android', [errorProne: '2.26.1', j2objc: '3.0.0', jsr305: '3.0.2', checker: '3.42.0', failureaccess: '1.0.2']],
22+
['33.1.0', 'jre' , [errorProne: '2.26.1', j2objc: '3.0.0', jsr305: '3.0.2', checker: '3.42.0', failureaccess: '1.0.2']],
23+
['33.1.0', 'android', [errorProne: '2.26.1', j2objc: '3.0.0', jsr305: '3.0.2', checker: '3.42.0', failureaccess: '1.0.2']],
24+
['33.0.0', 'jre' , [errorProne: '2.23.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.41.0', failureaccess: '1.0.2']],
25+
['33.0.0', 'android', [errorProne: '2.23.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.41.0', failureaccess: '1.0.2']],
26+
['32.1.3', 'jre' , [errorProne: '2.21.1', j2objc: '2.8', jsr305: '3.0.2', checker: '3.37.0', failureaccess: '1.0.1']],
27+
['32.1.3', 'android', [errorProne: '2.21.1', j2objc: '2.8', jsr305: '3.0.2', checker: '3.37.0', failureaccess: '1.0.1']],
28+
['32.1.2', 'jre' , [errorProne: '2.18.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.33.0', failureaccess: '1.0.1']],
29+
['32.1.2', 'android', [errorProne: '2.18.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.33.0', failureaccess: '1.0.1']],
2030
['32.1.1', 'jre' , [errorProne: '2.18.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.33.0', failureaccess: '1.0.1']],
2131
['32.1.1', 'android', [errorProne: '2.18.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.33.0', failureaccess: '1.0.1']],
2232
['32.0.1', 'jre' , [errorProne: '2.18.0', j2objc: '2.8', jsr305: '3.0.2', checker: '3.33.0', failureaccess: '1.0.1']],
@@ -111,12 +121,12 @@ class GuavaClasspathTest extends Specification {
111121
result.add([it[0], it[1], it[2], 'standard-jvm', 'runtimeClasspath'])
112122
}
113123
}
114-
if (System.getProperty("gradleVersionUnderTest") == "7.5.1") {
124+
if (System.getProperty("gradleVersionUnderTest") == "7.6.4") {
115125
// only do all permutations for one Gradle version
116126
return result
117127
}
118128
// reduced amount of permutations
119-
return result.subList(0, 32)
129+
return result.subList(0, 80)
120130
}
121131

122132
@Unroll
@@ -160,7 +170,7 @@ class GuavaClasspathTest extends Specification {
160170
"""
161171

162172
expect:
163-
expectedClasspath(guavaVersion, jvmEnv, classpath, dependencyVersions) == printJars().output.split('\n') as Set
173+
expectedClasspath(guavaVersion, jvmEnv, classpath, dependencyVersions) == printJars().output.split('\n') as TreeSet
164174

165175
where:
166176
[guavaVersion, versionSuffix, dependencyVersions, jvmEnv, classpath] << allGuavaCombinations(true)
@@ -169,7 +179,7 @@ class GuavaClasspathTest extends Specification {
169179
Set<String> expectedClasspath(String guavaVersion, String jvmEnv, String classpath, Map<String, String> dependencyVersions) {
170180
int majorGuavaVersion = guavaVersion.substring(0, 2) as Integer
171181
String jarSuffix = majorGuavaVersion < 22 ? '' : jvmEnv == 'android' ? 'android' : (guavaVersion == '22.0' || guavaVersion == '23.0') ? '' : 'jre'
172-
Set<String> result = ["guava-${guavaVersion}${jarSuffix? '-' : ''}${jarSuffix}.jar"]
182+
Set<String> result = ["guava-${guavaVersion}${jarSuffix? '-' : ''}${jarSuffix}.jar"] as TreeSet
173183
if (dependencyVersions.failureaccess) {
174184
result += "failureaccess-${dependencyVersions.failureaccess}.jar"
175185
}

0 commit comments

Comments
 (0)