From 25e1b3afc57dab30903bf74d2da64487113ba4a9 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Tue, 5 Feb 2019 18:25:52 +0100 Subject: [PATCH] Allow selection of both the library and platform of a component For published POM files, we want to allow selecting both the library and platform variants of a component. They are effectively different things. This commit makes it possible by assigning a different capability to the platform variants. Fixes #8420 --- .../MavenBomResolveIntegrationTest.groovy | 16 +++++++++---- .../model/DefaultConfigurationMetadata.java | 23 ++++++++++++++++++ ...avaEcosystemVariantDerivationStrategy.java | 24 +++++++++++++------ 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy index e3344e3bd5df..e7d809cb6c87 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/maven/MavenBomResolveIntegrationTest.groovy @@ -19,7 +19,7 @@ package org.gradle.integtests.resolve.maven import org.gradle.integtests.fixtures.AbstractHttpDependencyResolutionTest import org.gradle.integtests.fixtures.resolve.ResolveTestFixture import org.gradle.test.fixtures.maven.MavenModule -import spock.lang.Ignore +import spock.lang.Issue class MavenBomResolveIntegrationTest extends AbstractHttpDependencyResolutionTest { def resolve = new ResolveTestFixture(buildFile).expectDefaultConfiguration('runtime') @@ -137,8 +137,8 @@ class MavenBomResolveIntegrationTest extends AbstractHttpDependencyResolutionTes } } - @Ignore("This isn't true anymore: a POM is either a platform (BOM) or a library") - def "a bom can declare dependencies"() { + @Issue("gradle/gradle#8420") + def "can depend on both platform and library if a published POM represents both of them"() { given: mavenHttpRepo.module('group', 'moduleC', '1.0').allowAll().publish() bomDependency('moduleA') @@ -156,7 +156,8 @@ class MavenBomResolveIntegrationTest extends AbstractHttpDependencyResolutionTes buildFile << """ dependencies { - compile "group:bom:1.0" + compile platform("group:bom:1.0") // dependency on the platform + compile "group:bom:1.0" // dependency on library compile "group:moduleA" } """ @@ -168,7 +169,12 @@ class MavenBomResolveIntegrationTest extends AbstractHttpDependencyResolutionTes resolve.expectGraph { root(':', ':testproject:') { module("group:bom:1.0") { - module("group:moduleA:2.0") + variant("platform-runtime", ['org.gradle.component.category':'platform', 'org.gradle.status':'release', 'org.gradle.usage':'java-runtime']) + constraint("group:moduleA:2.0") + noArtifacts() + } + module("group:bom:1.0") { + variant("runtime", ['org.gradle.component.category':'library', 'org.gradle.status':'release', 'org.gradle.usage':'java-runtime']) module("group:moduleC:1.0") noArtifacts() } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java index 1e5a5692bcf0..0be6d7e32137 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/DefaultConfigurationMetadata.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.capabilities.CapabilitiesMetadata; +import org.gradle.api.capabilities.Capability; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.Factory; import org.gradle.internal.component.model.DependencyMetadata; @@ -86,6 +87,24 @@ private DefaultConfigurationMetadata(ModuleComponentIdentifier componentId, Stri this.dependencyFilter = dependencyFilter; } + private DefaultConfigurationMetadata(ModuleComponentIdentifier componentId, + String name, + boolean transitive, + boolean visible, + ImmutableSet hierarchy, + ImmutableList artifacts, + VariantMetadataRules componentMetadataRules, + ImmutableList excludes, + ImmutableAttributes attributes, + Factory> configDependenciesFactory, + DependencyFilter dependencyFilter, + List capabilities) { + super(componentId, name, transitive, visible, artifacts, hierarchy, excludes, attributes, configDependenciesFactory, ImmutableCapabilities.of(capabilities)); + this.componentMetadataRules = componentMetadataRules; + this.componentLevelAttributes = attributes; + this.dependencyFilter = dependencyFilter; + } + @Override public ImmutableAttributes getAttributes() { if (computedAttributes == null) { @@ -165,6 +184,10 @@ public DefaultConfigurationMetadata withForcedDependencies() { return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), componentLevelAttributes, lazyConfigDependencies(), dependencyFilter.forcing()); } + public DefaultConfigurationMetadata withCapabilities(List capabilities) { + return new DefaultConfigurationMetadata(getComponentId(), getName(), isTransitive(), isVisible(), getHierarchy(), getArtifacts(), componentMetadataRules, getExcludes(), super.getAttributes(), lazyConfigDependencies(), dependencyFilter, capabilities); + } + private ImmutableList force(ImmutableList configDependencies) { ImmutableList.Builder dependencies = new ImmutableList.Builder(); for (ModuleDependencyMetadata configDependency : configDependencies) { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java index e813c25c8135..9adc86f95c00 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/JavaEcosystemVariantDerivationStrategy.java @@ -16,12 +16,15 @@ package org.gradle.internal.component.external.model; import com.google.common.collect.ImmutableList; +import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.attributes.Usage; import org.gradle.api.internal.artifacts.repositories.metadata.MavenImmutableAttributesFactory; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.external.model.maven.DefaultMavenModuleResolveMetadata; import org.gradle.internal.component.model.ConfigurationMetadata; +import java.util.Collections; + public class JavaEcosystemVariantDerivationStrategy implements VariantDerivationStrategy { @Override public boolean derivesVariants() { @@ -37,12 +40,12 @@ public ImmutableList derive(ModuleComponentReso DefaultConfigurationMetadata compileConfiguration = (DefaultConfigurationMetadata) md.getConfiguration("compile"); DefaultConfigurationMetadata runtimeConfiguration = (DefaultConfigurationMetadata) md.getConfiguration("runtime"); return ImmutableList.of( - libraryWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API), - libraryWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME), - platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, false), - platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, false), - platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, true), - platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, true)); + libraryWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API), + libraryWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME), + platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, false), + platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, false), + platformWithUsageAttribute(compileConfiguration, attributes, attributesFactory, Usage.JAVA_API, true), + platformWithUsageAttribute(runtimeConfiguration, attributes, attributesFactory, Usage.JAVA_RUNTIME, true)); } return null; } @@ -54,9 +57,16 @@ private static ConfigurationMetadata libraryWithUsageAttribute(DefaultConfigurat private static ConfigurationMetadata platformWithUsageAttribute(DefaultConfigurationMetadata conf, ImmutableAttributes originAttributes, MavenImmutableAttributesFactory attributesFactory, String usage, boolean enforcedPlatform) { ImmutableAttributes attributes = attributesFactory.platformWithUsage(originAttributes, usage, enforcedPlatform); + ModuleComponentIdentifier componentId = conf.getComponentId(); String prefix = enforcedPlatform ? "enforced-platform-" : "platform-"; DefaultConfigurationMetadata metadata = conf.withAttributes(prefix + conf.getName(), attributes); - metadata = metadata.withConstraintsOnly(); + metadata = metadata + .withConstraintsOnly() + .withCapabilities(Collections.singletonList(new ImmutableCapability( + componentId.getGroup(), + componentId.getModule() + "-derived-platform", + componentId.getVersion() + ))); if (enforcedPlatform) { metadata = metadata.withForcedDependencies(); }