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)