From b95575c0b2821ac71f7ea48ae0662de4103b414e Mon Sep 17 00:00:00 2001 From: Louis Jacomet Date: Wed, 16 Mar 2022 15:41:54 +0100 Subject: [PATCH] Add support for dependency constraint without version Prior to this change, a published Gradle Module Metadata that contained a constraint without a version definition would result in a null VersionConstraint instead of an empty one. This caused issue during metadata serialization and potentially resolution. The field is not nullable and an empty version constraint is now used as the default value. Fixes #20189 --- ...pendenciesAttributesIntegrationTest.groovy | 59 +++++++++++++++++++ .../parser/GradleModuleMetadataParser.java | 2 +- .../GradleModuleMetadataParserTest.groovy | 4 +- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/DependenciesAttributesIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/DependenciesAttributesIntegrationTest.groovy index ddbf42fc9d2f..9d936c340058 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/DependenciesAttributesIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/attributes/DependenciesAttributesIntegrationTest.groovy @@ -506,6 +506,65 @@ class DependenciesAttributesIntegrationTest extends AbstractModuleDependencyReso 'c1' | 'c2' | 'runtime' | ['org.gradle.status': defaultStatus(), 'org.gradle.usage': 'java-runtime', 'org.gradle.libraryelements': 'jar', 'org.gradle.category': 'library', custom: 'c2'] } + @Issue("https://github.com/gradle/gradle/issues/20182") + @RequiredFeature(feature = GradleMetadataResolveRunner.GRADLE_METADATA, value = "true") + @Unroll("Selects variant #expectedVariant using custom attribute value #dependencyValue overriding configuration attribute #configurationValue using dependency constraint without version") + def "dependency attribute value overrides configuration attribute using dependency constraint without version"() { + given: + repository { + 'org:test:1.0' { + variant('api') { + attribute('custom', 'c1') + } + variant('runtime') { + attribute('custom', 'c2') + } + } + } + + buildFile << """ + configurations.conf.attributes.attribute(CUSTOM_ATTRIBUTE, '$configurationValue') + + dependencies { + constraints { + conf('org:test') { + attributes { + attribute(CUSTOM_ATTRIBUTE, '$dependencyValue') + } + } + } + conf 'org:test:1.0' + } + """ + + when: + repositoryInteractions { + 'org:test:1.0' { + expectResolve() + } + } + succeeds 'checkDeps' + + then: + resolve.expectGraph { + root(":", ":test:") { + module('org:test:1.0') { + configuration = expectedVariant + variant(expectedVariant, expectedAttributes) + } + constraint('org:test', 'org:test:1.0') { + configuration = expectedVariant + variant(expectedVariant, expectedAttributes) + } + } + } + + where: + configurationValue | dependencyValue | expectedVariant | expectedAttributes + 'c2' | 'c1' | 'api' | ['org.gradle.status': defaultStatus(), 'org.gradle.usage': 'java-api', 'org.gradle.libraryelements': 'jar', 'org.gradle.category': 'library', custom: 'c1'] + 'c1' | 'c2' | 'runtime' | ['org.gradle.status': defaultStatus(), 'org.gradle.usage': 'java-runtime', 'org.gradle.libraryelements': 'jar', 'org.gradle.category': 'library', custom: 'c2'] + } + @RequiredFeature(feature = GradleMetadataResolveRunner.GRADLE_METADATA, value = "true") @ToBeFixedForConfigurationCache def "Fails resolution because consumer configuration attributes and constraint attributes conflict"() { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java index 030c47aee756..5edc958813da 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParser.java @@ -439,7 +439,7 @@ private List consumeDependencyConstraints(JsonReader String group = null; String module = null; String reason = null; - VersionConstraint version = null; + VersionConstraint version = DefaultImmutableVersionConstraint.of(); ImmutableAttributes attributes = ImmutableAttributes.EMPTY; reader.beginObject(); diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy index 88abade1f193..feaa387f61fe 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/parser/GradleModuleMetadataParserTest.groovy @@ -381,7 +381,8 @@ class GradleModuleMetadataParserTest extends Specification { "group": "g3", "module": "m3", "version": { "requires": "v3" } - } + }, + { "group": "g4", "module": "m4" } ], "attributes": { "usage": "compile" } }, @@ -404,6 +405,7 @@ class GradleModuleMetadataParserTest extends Specification { 1 * variant1.addDependencyConstraint("g1", "m1", requires("v1"), null, ImmutableAttributes.EMPTY) 1 * variant1.addDependencyConstraint("g2", "m2", prefers("v2"), null, ImmutableAttributes.EMPTY) 1 * variant1.addDependencyConstraint("g3", "m3", requires("v3"), null, ImmutableAttributes.EMPTY) + 1 * variant1.addDependencyConstraint("g4", "m4", emptyConstraint(), null, ImmutableAttributes.EMPTY) 1 * variant1.setAvailableExternally(false) 1 * metadata.addVariant("runtime", attributes(usage: "runtime", packaging: "zip")) >> variant2 1 * variant2.addDependencyConstraint("g3", "m3", prefers("v3"), null, ImmutableAttributes.EMPTY)