From efeecd680b3789217d92becf2ebcc7a390cfe129 Mon Sep 17 00:00:00 2001 From: Paul Merlin Date: Sat, 27 Apr 2019 12:26:34 +0200 Subject: [PATCH] Rework exclude rule merging As a follow-up to #9197, this commit properly fixes the exclude rule merging algorithm, by completely rewriting it. The new merging algorithm works by implementing the minimal set of algebra operations that make sense to minimize computation durations. In order to do this, this commit introduces a number of exclude specs (found in their own package) and factories to create actual implementation of those specs. Specs represent the different kind of excludes we can find: - excluding a group - excluding a module (no group defined) - excluding a group+module - excluding an artifact of a group+module - pattern-matching excludes - unions of excludes - intersections of excludes With all those minimal bricks, factories are responsible of generating consistent specs. The dumbest factory will just generate new instances for everything. This is the default factory. Minimally, this factory has to be backed by an optimizing factory, which will take care of handling special cases: - union or intersection of a single spec - union or intersection of 2 specs - when one of them is null - when both are equal Then we have a factory which performs the minimal algebra to minimize specs: - unions of unions - intersections of intersections - union of a union and individual specs - insection of an intersection and individual spec - ... This factory can be as smart as it can, but one must be careful that it's worth it: some previously implemented optimizations (like (A+B).A = A turned out to be costly to detect, and didn't make it the final cut. Last but not least, a caching factory is there to avoid recomputing the same intersections and unions of specs when we have already done the job. This is efficient if the underlying (delegate) specs are easily compared, which is the case thanks to the interning factory. All in all, the delegation chain allows us to make the algorithm fast and hopefully reliable, while making it easier to debug. --- .../gradlebuild/packaging/MinifyPlugin.kt | 1 + ...ndencyExcludeResolveIntegrationTest.groovy | 8 +- ...ependencyManagementBuildScopeServices.java | 4 +- .../ivyresolve/NoRepositoriesResolver.java | 4 +- .../RepositoryChainArtifactResolver.java | 4 +- .../ProjectDependencyResolver.java | 4 +- .../artifact/DefaultArtifactSet.java | 10 +- .../ResolvedArtifactsGraphVisitor.java | 4 +- .../excludes/AbstractCompositeExclusion.java | 102 --- .../excludes/AbstractModuleExclusion.java | 118 --- .../resolveengine/excludes/AllExclusion.java | 87 -- .../excludes/ArtifactExcludeSpec.java | 82 -- .../excludes/EitherExclusion.java | 107 --- .../excludes/GroupNameExcludeSpec.java | 58 -- .../excludes/ImmutableModuleExclusionSet.java | 187 ---- .../IvyPatternMatcherExcludeRuleSpec.java | 95 -- .../excludes/ModuleExclusion.java | 49 -- .../excludes/ModuleExclusions.java | 491 ++--------- .../excludes/ModuleIdExcludeSpec.java | 57 -- .../excludes/ModuleNameExcludeSpec.java | 57 -- .../excludes/PatternMatchers.java | 2 +- .../factories/CachingExcludeFactory.java | 149 ++++ .../factories/DelegatingExcludeFactory.java | 92 ++ .../factories/NormalizingExcludeFactory.java | 158 ++++ .../excludes/factories/Optimizations.java | 89 ++ .../factories/OptimizingExcludeFactory.java | 61 ++ .../excludes/factories/package-info.java | 20 + .../simple/DefaultCompositeExclude.java | 117 +++ .../excludes/simple/DefaultExcludeAllOf.java | 55 ++ .../excludes/simple/DefaultExcludeAnyOf.java | 54 ++ .../simple/DefaultExcludeEverything.java | 72 ++ .../simple/DefaultExcludeFactory.java | 88 ++ .../simple/DefaultExcludeNothing.java | 71 ++ .../excludes/simple/DefaultGroupExclude.java | 88 ++ ...faultIvyPatternMatcherExcludeRuleSpec.java | 118 +++ .../simple/DefaultModuleArtifactExclude.java | 85 ++ .../excludes/simple/DefaultModuleExclude.java | 88 ++ .../simple/DefaultModuleIdExclude.java | 88 ++ .../simple/DefaultModuleSetExclude.java | 83 ++ .../excludes/simple/package-info.java | 20 + .../ArtifactExclude.java} | 29 +- .../excludes/specs/CompositeExclude.java | 32 + .../excludes/specs/ExcludeAllOf.java | 19 + .../excludes/specs/ExcludeAnyOf.java | 19 + .../excludes/specs/ExcludeEverything.java | 19 + .../excludes/specs/ExcludeFactory.java | 48 + .../excludes/specs/ExcludeNothing.java | 19 + .../excludes/specs/ExcludeSpec.java | 43 + .../excludes/specs/GroupExclude.java | 20 + .../IvyPatternMatcherExcludeRuleSpec.java | 19 + .../excludes/specs/ModuleExclude.java | 20 + .../excludes/specs/ModuleIdExclude.java | 22 + .../ModuleSetExclude.java} | 32 +- .../excludes/specs/package-info.java | 20 + .../graph/DependencyGraphEdge.java | 4 +- .../graph/builder/EdgeState.java | 16 +- .../graph/builder/NodeState.java | 48 +- .../model/FixedComponentArtifacts.java | 4 +- .../MetadataSourcedComponentArtifacts.java | 4 +- .../component/model/ComponentArtifacts.java | 4 +- .../resolve/resolver/ArtifactSelector.java | 4 +- .../resolver/DefaultArtifactSelector.java | 10 +- .../resolver/OriginArtifactSelector.java | 4 +- ...RepositoryChainArtifactResolverTest.groovy | 6 +- .../DependencyGraphBuilderTest.groovy | 2 +- .../DefaultModuleExclusionTest.groovy | 818 ------------------ .../NormalizingExcludeFactoryTest.groovy | 137 +++ .../model/IvyDependencyDescriptorTest.groovy | 29 +- .../MavenDependencyDescriptorTest.groovy | 16 +- .../DefaultLocalComponentMetadataTest.groovy | 3 - ...ocalComponentDependencyMetadataTest.groovy | 9 +- .../LocalLibraryDependencyResolver.java | 4 +- ...mLocalLibraryDependencyResolverTest.groovy | 7 +- .../resolver/VcsDependencyResolver.java | 4 +- 74 files changed, 2219 insertions(+), 2402 deletions(-) delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractCompositeExclusion.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractModuleExclusion.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ArtifactExcludeSpec.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/GroupNameExcludeSpec.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ImmutableModuleExclusionSet.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IvyPatternMatcherExcludeRuleSpec.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusion.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleIdExcludeSpec.java delete mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleNameExcludeSpec.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/CachingExcludeFactory.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/DelegatingExcludeFactory.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactory.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/Optimizations.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/OptimizingExcludeFactory.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/package-info.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultCompositeExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAllOf.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAnyOf.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeEverything.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeFactory.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeNothing.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultGroupExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultIvyPatternMatcherExcludeRuleSpec.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleArtifactExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleIdExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleSetExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/package-info.java rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/{ExcludeNone.java => specs/ArtifactExclude.java} (62%) create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/CompositeExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAllOf.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAnyOf.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeEverything.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeFactory.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeNothing.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeSpec.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/GroupExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/IvyPatternMatcherExcludeRuleSpec.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleExclude.java create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleIdExclude.java rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/{ExcludeAllModulesSpec.java => specs/ModuleSetExclude.java} (53%) create mode 100644 subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/package-info.java delete mode 100644 subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/DefaultModuleExclusionTest.groovy create mode 100644 subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactoryTest.groovy diff --git a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt index 25136dcaba5f..412753e83031 100644 --- a/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt +++ b/buildSrc/subprojects/packaging/src/main/kotlin/org/gradle/gradlebuild/packaging/MinifyPlugin.kt @@ -38,6 +38,7 @@ open class MinifyPlugin : Plugin { val keepPatterns = mapOf( "fastutil" to setOf( "it.unimi.dsi.fastutil.ints.IntOpenHashSet", + "it.unimi.dsi.fastutil.ints.IntRBTreeSet", "it.unimi.dsi.fastutil.ints.IntSets" ) ) diff --git a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ModuleDependencyExcludeResolveIntegrationTest.groovy b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ModuleDependencyExcludeResolveIntegrationTest.groovy index 3ceb8f4c4ffe..5ee7c5f879dc 100644 --- a/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ModuleDependencyExcludeResolveIntegrationTest.groovy +++ b/subprojects/dependency-management/src/integTest/groovy/org/gradle/integtests/resolve/ModuleDependencyExcludeResolveIntegrationTest.groovy @@ -16,9 +16,11 @@ package org.gradle.integtests.resolve + import org.gradle.integtests.fixtures.executer.GradleContextualExecuter import spock.lang.IgnoreIf import spock.lang.Issue +import spock.lang.Unroll /** * Demonstrates the resolution of dependency excludes in published module metadata. @@ -109,7 +111,8 @@ task check(type: Sync) { * * Exclude is applied to dependency a->b */ - def "dependency exclude for group or module applies to child module of dependency"() { + @Unroll + def "dependency exclude for group or module applies to child module of dependency (#excluded)"() { given: def expectResolved = ['a', 'b', 'c', 'd', 'e'] - expectExcluded repository { @@ -202,7 +205,8 @@ task check(type: Sync) { * * Selective exclusions are applied to dependency a->b */ - def "can exclude transitive dependencies"() { + @Unroll + def "can exclude transitive dependencies (#condition)"() { repository { 'a:a:1.0' { dependsOn group: 'b', artifact: 'b', version: '1.0', exclusions: excludes diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementBuildScopeServices.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementBuildScopeServices.java index d6e133f8525e..9d5d2dce8097 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementBuildScopeServices.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/DependencyManagementBuildScopeServices.java @@ -169,8 +169,8 @@ BuildCommencedTimeProvider createBuildTimeProvider() { return new BuildCommencedTimeProvider(); } - ModuleExclusions createModuleExclusions(ImmutableModuleIdentifierFactory moduleIdentifierFactory) { - return new ModuleExclusions(moduleIdentifierFactory); + ModuleExclusions createModuleExclusions() { + return new ModuleExclusions(); } MavenMutableModuleMetadataFactory createMutableMavenMetadataFactory(ImmutableModuleIdentifierFactory moduleIdentifierFactory, diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java index bfd43681d9a1..7de16f585f18 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/NoRepositoriesResolver.java @@ -19,7 +19,7 @@ import org.gradle.api.artifacts.component.ComponentIdentifier; import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelector; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.component.ArtifactType; @@ -82,7 +82,7 @@ public boolean isFetchingMetadataCheap(ComponentIdentifier identifier) { @Nullable @Override - public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { throw new UnsupportedOperationException(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java index 9e044fb8a93a..152fe0fbbc1c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolver.java @@ -17,7 +17,7 @@ import org.gradle.api.attributes.Category; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.repositories.metadata.MavenImmutableAttributesFactory; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.AttributeValue; @@ -60,7 +60,7 @@ public void resolveArtifactsWithType(ComponentResolveMetadata component, Artifac @Nullable @Override - public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { if (component.getSource() == null) { // virtual components have no source return NO_ARTIFACTS; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java index bdb29c4ea06d..33b876d65a5b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/projectmodule/ProjectDependencyResolver.java @@ -26,7 +26,7 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.component.ArtifactType; @@ -131,7 +131,7 @@ public void resolveArtifactsWithType(ComponentResolveMetadata component, Artifac @Nullable @Override - public ArtifactSet resolveArtifacts(final ComponentResolveMetadata component, final ConfigurationMetadata configuration, final ArtifactTypeRegistry artifactTypeRegistry, final ModuleExclusion exclusions, final ImmutableAttributes overriddenAttributes) { + public ArtifactSet resolveArtifacts(final ComponentResolveMetadata component, final ConfigurationMetadata configuration, final ArtifactTypeRegistry artifactTypeRegistry, final ExcludeSpec exclusions, final ImmutableAttributes overriddenAttributes) { if (isProjectModule(component.getId())) { return DefaultArtifactSet.multipleVariants(component.getId(), component.getModuleVersionId(), component.getSource(), exclusions, configuration.getVariants(), component.getAttributesSchema(), self, allProjectArtifacts, artifactTypeRegistry, overriddenAttributes); } else { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/DefaultArtifactSet.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/DefaultArtifactSet.java index 852a6b5baf3f..e6b5b844aa64 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/DefaultArtifactSet.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/DefaultArtifactSet.java @@ -23,7 +23,7 @@ import org.gradle.api.artifacts.component.ComponentArtifactIdentifier; import org.gradle.api.artifacts.component.ComponentIdentifier; import org.gradle.api.internal.artifacts.DefaultResolvedArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.transform.VariantSelector; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.AttributesSchemaInternal; @@ -71,7 +71,7 @@ public ImmutableAttributes getOverriddenAttributes() { return selectionAttributes; } - public static ArtifactSet multipleVariants(ComponentIdentifier componentIdentifier, ModuleVersionIdentifier ownerId, ModuleSource moduleSource, ModuleExclusion exclusions, Set variants, AttributesSchemaInternal schema, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ImmutableAttributes selectionAttributes) { + public static ArtifactSet multipleVariants(ComponentIdentifier componentIdentifier, ModuleVersionIdentifier ownerId, ModuleSource moduleSource, ExcludeSpec exclusions, Set variants, AttributesSchemaInternal schema, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ImmutableAttributes selectionAttributes) { if (variants.size() == 1) { VariantResolveMetadata variantMetadata = variants.iterator().next(); ResolvedVariant resolvedVariant = toResolvedVariant(variantMetadata, ownerId, moduleSource, exclusions, artifactResolver, allResolvedArtifacts, artifactTypeRegistry); @@ -85,13 +85,13 @@ public static ArtifactSet multipleVariants(ComponentIdentifier componentIdentifi return new MultipleVariantArtifactSet(componentIdentifier, schema, result.build(), selectionAttributes); } - public static ArtifactSet singleVariant(ComponentIdentifier componentIdentifier, ModuleVersionIdentifier ownerId, DisplayName displayName, Collection artifacts, ModuleSource moduleSource, ModuleExclusion exclusions, AttributesSchemaInternal schema, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ImmutableAttributes selectionAttributes) { + public static ArtifactSet singleVariant(ComponentIdentifier componentIdentifier, ModuleVersionIdentifier ownerId, DisplayName displayName, Collection artifacts, ModuleSource moduleSource, ExcludeSpec exclusions, AttributesSchemaInternal schema, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ImmutableAttributes selectionAttributes) { VariantResolveMetadata variantMetadata = new DefaultVariantMetadata(displayName, ImmutableAttributes.EMPTY, ImmutableList.copyOf(artifacts), ImmutableCapabilities.EMPTY); ResolvedVariant resolvedVariant = toResolvedVariant(variantMetadata, ownerId, moduleSource, exclusions, artifactResolver, allResolvedArtifacts, artifactTypeRegistry); return new SingleVariantArtifactSet(componentIdentifier, schema, resolvedVariant, selectionAttributes); } - private static ResolvedVariant toResolvedVariant(VariantResolveMetadata variant, ModuleVersionIdentifier ownerId, ModuleSource moduleSource, ModuleExclusion exclusions, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry) { + private static ResolvedVariant toResolvedVariant(VariantResolveMetadata variant, ModuleVersionIdentifier ownerId, ModuleSource moduleSource, ExcludeSpec exclusions, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry) { List artifacts = variant.getArtifacts(); ImmutableSet.Builder resolvedArtifacts = ImmutableSet.builder(); @@ -100,7 +100,7 @@ private static ResolvedVariant toResolvedVariant(VariantResolveMetadata variant, for (ComponentArtifactMetadata artifact : artifacts) { IvyArtifactName artifactName = artifact.getName(); - if (exclusions.excludeArtifact(ownerId.getModule(), artifactName)) { + if (exclusions.excludesArtifact(ownerId.getModule(), artifactName)) { continue; } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/ResolvedArtifactsGraphVisitor.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/ResolvedArtifactsGraphVisitor.java index 96113fa4eb10..c0617d9d8af6 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/ResolvedArtifactsGraphVisitor.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/artifact/ResolvedArtifactsGraphVisitor.java @@ -17,7 +17,7 @@ package org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact; import com.google.common.collect.Maps; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphEdge; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphNode; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphSelector; @@ -96,7 +96,7 @@ private ArtifactsForNode getArtifacts(DependencyGraphEdge dependency, Dependency ArtifactsForNode configurationArtifactSet = artifactsByNodeId.get(toConfiguration.getNodeId()); if (configurationArtifactSet == null) { - ModuleExclusion exclusions = dependency.getExclusions(); + ExcludeSpec exclusions = dependency.getExclusions(); ArtifactSet nodeArtifacts = artifactSelector.resolveArtifacts(component, targetConfiguration, exclusions, overriddenAttributes); int id = nextId++; configurationArtifactSet = new ArtifactsForNode(id, nodeArtifacts); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractCompositeExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractCompositeExclusion.java deleted file mode 100644 index 830ccd8118e9..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractCompositeExclusion.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import com.google.common.collect.Sets; - -import java.util.Collection; -import java.util.Set; - -abstract class AbstractCompositeExclusion extends AbstractModuleExclusion { - private int hashCode = -1; - - abstract Collection getFilters(); - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("{"); - builder.append(getClass().getSimpleName()); - for (AbstractModuleExclusion spec : getFilters()) { - builder.append(' '); - builder.append(spec); - } - builder.append("}"); - return builder.toString(); - } - - @Override - protected boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - AbstractCompositeExclusion spec = (AbstractCompositeExclusion) other; - Collection thisFilters = getFilters(); - Collection otherFilters = spec.getFilters(); - - // To make the comparison faster, we compute the sets of specs that exist in this exclusion, but not in the other - // and the set of specs that exist in the other and not in this one. Then we only need to check if the missing - // from one set have an equivalent in the missing of the other set, which is much faster than checking all of them - Set miss1 = Sets.newHashSetWithExpectedSize(thisFilters.size()); - Set miss2 = Sets.newHashSetWithExpectedSize(otherFilters.size()); - for (AbstractModuleExclusion exclusion : thisFilters) { - if (!otherFilters.contains(exclusion)) { - miss1.add(exclusion); - } - } - for (AbstractModuleExclusion otherFilter : otherFilters) { - if (!thisFilters.contains(otherFilter)) { - miss2.add(otherFilter); - } - } - return (miss1.isEmpty() && miss2.isEmpty()) || (implies(miss1, miss2) && implies(miss2, miss1)); - } - - @Override - protected boolean doEquals(Object obj) { - AbstractCompositeExclusion other = (AbstractCompositeExclusion) obj; - return hashCode() == other.hashCode() && getFilters().equals(other.getFilters()); - } - - @Override - protected int doHashCode() { - if (hashCode != -1) { - return hashCode; - } - hashCode = getFilters().hashCode(); - return hashCode; - } - - /** - * Returns true if for every spec in this spec, there is a corresponding spec in the given spec that excludesSameModulesAs(). - */ - protected boolean implies(Set miss1, Set miss2) { - if (miss1.isEmpty() || miss2.isEmpty()) { - return false; - } - for (AbstractModuleExclusion thisSpec : miss1) { - boolean found = false; - for (AbstractModuleExclusion otherSpec : miss2) { - if (thisSpec.excludesSameModulesAs(otherSpec)) { - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractModuleExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractModuleExclusion.java deleted file mode 100644 index 1a1d54a24440..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AbstractModuleExclusion.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.component.model.IvyArtifactName; - -import java.util.Collection; - -abstract class AbstractModuleExclusion implements ModuleExclusion { - private int hashCode = -1; - private ModuleExclusion lastCheck; - private boolean lastCheckResult; - - protected static boolean isWildcard(String attribute) { - return PatternMatchers.ANY_EXPRESSION.equals(attribute); - } - - public boolean excludeArtifact(ModuleIdentifier module, IvyArtifactName artifact) { - return false; - } - - public boolean mayExcludeArtifacts() { - return false; - } - - public final boolean excludesSameModulesAs(ModuleExclusion filter) { - if (filter == this) { - return true; - } - AbstractModuleExclusion other = (AbstractModuleExclusion) filter; - boolean thisExcludesNothing = excludesNoModules(); - boolean otherExcludesNothing = other.excludesNoModules(); - if (thisExcludesNothing && otherExcludesNothing) { - return true; - } - if (thisExcludesNothing || otherExcludesNothing) { - return false; - } - if (!other.getClass().equals(getClass())) { - return false; - } - synchronized (this) { - // This is an optimization, based on the fact that in a large amount of times - // a specific exclusion is checked against the same filter the next time so - // we don't need to recompute the result: we can cache the last query - if (filter == lastCheck) { - return lastCheckResult; - } - lastCheck = other; - lastCheckResult = doExcludesSameModulesAs(other); - return lastCheckResult; - } - } - - /** - * Only called when this and the other spec have the same class. - */ - protected boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - return false; - } - - protected boolean excludesNoModules() { - return false; - } - - /** - * Possibly unpack a composite spec into it's constituent parts, if those parts are applied as an intersection. - * @param specs - */ - protected void unpackEither(Collection specs) { - specs.add(this); - } - - /** - * Possibly unpack a composite spec into it's constituent parts, if those parts are applied as a union. - */ - protected void unpackAll(Collection specs) { - specs.add(this); - } - - @Override - public final boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj == null || obj.getClass() != getClass()) { - return false; - } - return doEquals(obj); - } - - protected abstract boolean doEquals(Object obj); - - @Override - public final int hashCode() { - if (hashCode != -1) { - return hashCode; - } - hashCode = doHashCode(); - return hashCode; - } - - protected abstract int doHashCode(); -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java deleted file mode 100644 index 9dfc35884906..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.component.model.IvyArtifactName; - -import java.util.Collection; -import java.util.List; - -/** - * A filter that only excludes artifacts and modules that are excluded by _all_ of the supplied exclude rules. - * As such, this is a union of the separate exclude rule filters. - */ -class AllExclusion extends AbstractCompositeExclusion { - private final List filters; - - public AllExclusion(List filters) { - this.filters = filters; - } - - Collection getFilters() { - return filters; - } - - /** - * Can unpack into constituents when creating a larger union. - */ - @Override - protected void unpackAll(Collection specs) { - specs.addAll(this.filters); - } - - @Override - protected boolean excludesNoModules() { - for (AbstractModuleExclusion excludeSpec : filters) { - if (excludeSpec.excludesNoModules()) { - return true; - } - } - return false; - } - - public boolean excludeModule(ModuleIdentifier element) { - for (AbstractModuleExclusion spec : filters) { - if (!spec.excludeModule(element)) { - return false; - } - } - - return true; - } - - public boolean excludeArtifact(ModuleIdentifier module, IvyArtifactName artifact) { - for (AbstractModuleExclusion spec : filters) { - if (!spec.excludeArtifact(module, artifact)) { - return false; - } - } - - return true; - } - - public boolean mayExcludeArtifacts() { - for (AbstractModuleExclusion spec : filters) { - if (!spec.mayExcludeArtifacts()) { - return false; - } - } - - return true; - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ArtifactExcludeSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ArtifactExcludeSpec.java deleted file mode 100644 index c10b61cb1495..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ArtifactExcludeSpec.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.component.model.IvyArtifactName; - -/** - * A ModuleResolutionFilter that excludes any artifact that matches supplied module and artifact details. - * Does not exclude any modules - */ -class ArtifactExcludeSpec extends AbstractModuleExclusion { - private final ModuleIdentifier moduleId; - private final IvyArtifactName ivyArtifactName; - - ArtifactExcludeSpec(ModuleIdentifier moduleId, IvyArtifactName artifact) { - this.moduleId = moduleId; - this.ivyArtifactName = artifact; - } - - @Override - public String toString() { - return "{artifact " + moduleId + ":" + ivyArtifactName + "}"; - } - - @Override - protected boolean doEquals(Object o) { - ArtifactExcludeSpec other = (ArtifactExcludeSpec) o; - return moduleId.equals(other.moduleId) && ivyArtifactName.equals(other.ivyArtifactName); - } - - @Override - protected int doHashCode() { - return moduleId.hashCode() ^ ivyArtifactName.hashCode(); - } - - @Override - protected boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - return true; - } - - @Override - protected boolean excludesNoModules() { - return true; - } - - @Override - public boolean excludeModule(ModuleIdentifier module) { - return false; - } - - @Override - public boolean excludeArtifact(ModuleIdentifier module, IvyArtifactName artifact) { - return matches(moduleId.getGroup(), module.getGroup()) - && matches(moduleId.getName(), module.getName()) - && matches(ivyArtifactName.getName(), artifact.getName()) - && matches(ivyArtifactName.getExtension(), artifact.getExtension()) - && matches(ivyArtifactName.getType(), artifact.getType()); - } - - public boolean mayExcludeArtifacts() { - return true; - } - - private boolean matches(String expression, String input) { - return isWildcard(expression) || expression.equals(input); - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java deleted file mode 100644 index f8f39dedae10..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.component.model.IvyArtifactName; - -import java.util.Collection; - -/** - * A spec that excludes modules or artifacts that are excluded by _any_ of the supplied exclusions. - * As such, this is an intersection of the separate exclude rule filters. - */ -class EitherExclusion extends AbstractCompositeExclusion { - private final ImmutableModuleExclusionSet excludeSpecs; - private final boolean mergeable; - - private Boolean excludesNoModules; - - public EitherExclusion(ImmutableModuleExclusionSet specs) { - this.excludeSpecs = specs; - boolean canMerge = true; - for (AbstractModuleExclusion spec : specs) { - if (!canMerge(spec)) { - canMerge = false; - break; - } - } - mergeable = canMerge; - } - - boolean canMerge() { - return mergeable; - } - - ImmutableModuleExclusionSet getFilters() { - return excludeSpecs; - } - - @Override - protected boolean excludesNoModules() { - if (excludesNoModules == null) { - // cache the result as we may be asked several times - excludesNoModules = doExcludeNoModules(); - } - return excludesNoModules; - } - - private boolean doExcludeNoModules() { - for (AbstractModuleExclusion excludeSpec : excludeSpecs) { - if (!excludeSpec.excludesNoModules()) { - return false; - } - } - return true; - } - - public boolean excludeModule(ModuleIdentifier element) { - return excludeSpecs.excludesModule(element); - } - - public boolean excludeArtifact(ModuleIdentifier module, IvyArtifactName artifact) { - return excludeSpecs.excludesArtifact(module, artifact); - } - - public boolean mayExcludeArtifacts() { - for (AbstractModuleExclusion spec : excludeSpecs) { - if (spec.mayExcludeArtifacts()) { - return true; - } - } - - return false; - } - - /** - * Can unpack into constituents when creating a larger intersection (since elements are applied as an intersection). - * @param specs - */ - @Override - protected void unpackEither(Collection specs) { - specs.addAll(excludeSpecs); - } - - private static boolean canMerge(AbstractModuleExclusion excludeSpec) { - return excludeSpec instanceof ExcludeAllModulesSpec - || excludeSpec instanceof ArtifactExcludeSpec - || excludeSpec instanceof GroupNameExcludeSpec - || excludeSpec instanceof ModuleNameExcludeSpec - || excludeSpec instanceof ModuleIdExcludeSpec; - } - -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/GroupNameExcludeSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/GroupNameExcludeSpec.java deleted file mode 100644 index 30f35daadbf8..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/GroupNameExcludeSpec.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; - -/** - * A ModuleResolutionFilter that excludes any module with a matching group. - * Does not exclude any artifacts. - */ -class GroupNameExcludeSpec extends AbstractModuleExclusion { - final String group; - - GroupNameExcludeSpec(String group) { - this.group = group; - } - - @Override - public String toString() { - return "{group " + group + "}"; - } - - @Override - protected boolean doEquals(Object o) { - GroupNameExcludeSpec other = (GroupNameExcludeSpec) o; - return group.equals(other.group); - } - - @Override - protected int doHashCode() { - return group.hashCode(); - } - - @Override - public boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - GroupNameExcludeSpec groupNameExcludeSpec = (GroupNameExcludeSpec) other; - return group.equals(groupNameExcludeSpec.group); - } - - @Override - public boolean excludeModule(ModuleIdentifier module) { - return module.getGroup().equals(group); - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ImmutableModuleExclusionSet.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ImmutableModuleExclusionSet.java deleted file mode 100644 index eee88c589dfa..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ImmutableModuleExclusionSet.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterators; -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.Cast; -import org.gradle.internal.component.model.IvyArtifactName; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Set; - -final class ImmutableModuleExclusionSet implements Set { - private final Set delegate; - - final AbstractModuleExclusion[] elements; - private final int hashCode; - - // the following fields are used as optimizations, to avoid iterating on the whole set of exclusions - private ImmutableSet excludedModules; - private ImmutableList moduleExcludes; - private ImmutableList artifactExcludes; - - ImmutableModuleExclusionSet(ImmutableSet delegate) { - this.delegate = delegate; - this.elements = delegate.toArray(new AbstractModuleExclusion[0]); - this.hashCode = delegate.hashCode(); - } - - private synchronized void precomputeCaches() { - if (excludedModules != null) { - return; - } - ImmutableSet.Builder moduleIds = ImmutableSet.builder(); - ImmutableList.Builder modules = ImmutableList.builder(); - ImmutableList.Builder artifacts = ImmutableList.builder(); - for (AbstractModuleExclusion exclusion : delegate) { - if (exclusion instanceof ModuleIdExcludeSpec) { - moduleIds.add(((ModuleIdExcludeSpec) exclusion).moduleId); - } else { - if (!exclusion.excludesNoModules()) { - modules.add(exclusion); - } - if (exclusion.mayExcludeArtifacts()) { - artifacts.add(exclusion); - } - } - } - excludedModules = moduleIds.build(); - moduleExcludes = modules.build(); - artifactExcludes = artifacts.build(); - } - - @Override - public int size() { - return delegate.size(); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return delegate.contains(o); - } - - @Override - public Iterator iterator() { - return Iterators.forArray(elements); - } - - /** - * This method optimizes module exclusion lookup, based on empirical data showing that the set can be very large, but would contain mostly direct module exclusion nodes. So instead of always - * iterating over all excluded modules, we can perform a fast lookup using a set of excluded modules first, then only iterate on the remaining exclusions. - * - * @param id the module to check - * @return true if it's excluded - */ - boolean excludesModule(ModuleIdentifier id) { - precomputeCaches(); - if (excludedModules.contains(id)) { - return true; - } - for (AbstractModuleExclusion excludeSpec : moduleExcludes) { - if (excludeSpec.excludeModule(id)) { - return true; - } - } - return false; - } - - boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifact) { - precomputeCaches(); - for (AbstractModuleExclusion excludeSpec : artifactExcludes) { - if (excludeSpec.excludeArtifact(module, artifact)) { - return true; - } - } - return false; - } - - @Override - public Object[] toArray() { - return elements; - } - - @Override - public T[] toArray(T[] a) { - return Cast.uncheckedCast(elements); - } - - @Override - public boolean add(AbstractModuleExclusion abstractModuleExclusion) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean containsAll(Collection c) { - return delegate.containsAll(c); - } - - @Override - public boolean addAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean retainAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeAll(Collection c) { - throw new UnsupportedOperationException(); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - ImmutableModuleExclusionSet that = (ImmutableModuleExclusionSet) o; - - if (hashCode != that.hashCode) { - return false; - } - - return delegate.equals(that.delegate); - } - - @Override - public int hashCode() { - return hashCode; - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IvyPatternMatcherExcludeRuleSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IvyPatternMatcherExcludeRuleSpec.java deleted file mode 100644 index 7e8ff90ddd3c..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IvyPatternMatcherExcludeRuleSpec.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import com.google.common.base.Objects; -import org.apache.ivy.plugins.matcher.PatternMatcher; -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.component.model.ExcludeMetadata; -import org.gradle.internal.component.model.IvyArtifactName; - -/** - * A ModuleResolutionFilter that excludes any module/artifact that matches the exclude rule, using an Ivy pattern matcher. - */ -class IvyPatternMatcherExcludeRuleSpec extends AbstractModuleExclusion { - private final ModuleIdentifier moduleId; - private final IvyArtifactName ivyArtifactName; - private final PatternMatcher matcher; - private final boolean isArtifactExclude; - - IvyPatternMatcherExcludeRuleSpec(ExcludeMetadata rule) { - this.moduleId = rule.getModuleId(); - this.ivyArtifactName = rule.getArtifact(); - this.matcher = PatternMatchers.getInstance().getMatcher(rule.getMatcher()); - isArtifactExclude = ivyArtifactName != null; - } - - @Override - public String toString() { - return "{exclude-rule " + moduleId + ":" + ivyArtifactName + " with matcher " + matcher.getName() + "}"; - } - - @Override - protected boolean doEquals(Object o) { - IvyPatternMatcherExcludeRuleSpec other = (IvyPatternMatcherExcludeRuleSpec) o; - return doExcludesSameModulesAs(other); - } - - @Override - protected int doHashCode() { - return Objects.hashCode(moduleId, ivyArtifactName); - } - - @Override - protected boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - IvyPatternMatcherExcludeRuleSpec otherSpec = (IvyPatternMatcherExcludeRuleSpec) other; - return moduleId.equals(otherSpec.moduleId) - && Objects.equal(ivyArtifactName, otherSpec.ivyArtifactName) - && matcher.getName().equals(otherSpec.matcher.getName()); - } - - @Override - protected boolean excludesNoModules() { - return isArtifactExclude; - } - - public boolean excludeModule(ModuleIdentifier module) { - if (isArtifactExclude) { - return false; - } - return matches(moduleId.getGroup(), module.getGroup()) && matches(moduleId.getName(), module.getName()); - } - - public boolean excludeArtifact(ModuleIdentifier module, IvyArtifactName artifact) { - if (!isArtifactExclude) { - return false; - } - return matches(moduleId.getGroup(), module.getGroup()) - && matches(moduleId.getName(), module.getName()) - && matches(ivyArtifactName.getName(), artifact.getName()) - && matches(ivyArtifactName.getExtension(), artifact.getExtension()) - && matches(ivyArtifactName.getType(), artifact.getType()); - } - - public boolean mayExcludeArtifacts() { - return isArtifactExclude; - } - - private boolean matches(String expression, String input) { - return matcher.getMatcher(expression).matches(input); - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusion.java deleted file mode 100644 index b7f54482de38..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusion.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.internal.component.model.IvyArtifactName; - -/** - * Manages sets of exclude rules, allowing union and intersection operations on the rules. - */ -public interface ModuleExclusion { - /** - * Should this module be excluded from the resolution result? - */ - boolean excludeModule(ModuleIdentifier module); - - /** - * Should this artifact be excluded from the resolution result? - */ - boolean excludeArtifact(ModuleIdentifier module, IvyArtifactName artifact); - - /** - * Could any artifacts be excluded by this filter? - * - * @return false if this filter could return false for {@link #excludeArtifact} for every provided artifact. - */ - boolean mayExcludeArtifacts(); - - /** - * Determines if this filter excludes the same set of modules as the other. - * - * @return true if the filters excludes the same set of modules. Returns false if they may not, or if it is unknown. - */ - boolean excludesSameModulesAs(ModuleExclusion other); -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusions.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusions.java index fa10c3d46959..538674d8cdf8 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusions.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleExclusions.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,453 +13,88 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.gradle.api.artifacts.ModuleIdentifier; -import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.DependencyGraphBuilder; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories.CachingExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories.NormalizingExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories.OptimizingExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple.DefaultExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.internal.component.model.ExcludeMetadata; import org.gradle.internal.component.model.IvyArtifactName; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; -import java.util.Set; - -import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.AbstractModuleExclusion.isWildcard; +import java.util.stream.Collectors; -/** - * Manages sets of exclude rules, allowing union and intersection operations on the rules. - * - *

This class attempts to reduce execution time, by flattening union and intersection specs, at the cost of more analysis at construction time. This is taken advantage of by {@link - * DependencyGraphBuilder}, on the assumption that there are many more edges in the dependency graph than there are exclude rules (ie - * we evaluate the rules much more often that we construct them).

- * - *

Also, this class attempts to be quite accurate in determining if 2 specs will exclude exactly the same set of modules. {@link DependencyGraphBuilder} - * uses this to avoid traversing the dependency graph of a particular version that has already been traversed when a new incoming edge is added (eg a newly discovered dependency) and when an incoming - * edge is removed (eg a conflict evicts a version that depends on the given version).

- * - *
  • When a module dependency has multiple exclusions, then the resulting exclusion is the _intersection_ of those exclusions (module is excluded if excluded by _any_).
  • When a module - * is depended on via a transitive path, then the resulting exclusion is the _intersection_ of the exclusions on each leg of the path (module is excluded if excluded by _any_).
  • When a module - * is depended on via multiple paths in the graph, then the resulting exclusion is the _union_ of the exclusions on each of those paths (module is excluded if excluded by _all_).
- */ public class ModuleExclusions { - private static final ExcludeNone EXCLUDE_NONE = new ExcludeNone(); - private static final ExcludeAllModulesSpec EXCLUDE_ALL_MODULES_SPEC = new ExcludeAllModulesSpec(); - - private final ImmutableModuleIdentifierFactory moduleIdentifierFactory; - - private final Map mergeCache = Maps.newConcurrentMap(); - private final Map, AbstractModuleExclusion> excludeAnyCache = Maps.newConcurrentMap(); - private final Map, EitherExclusion> eitherCache = Maps.newConcurrentMap(); - private final Map> mergeOperationCache = Maps.newIdentityHashMap(); - private final Map moduleIdSpecs = Maps.newConcurrentMap(); - private final Map moduleNameSpecs = Maps.newConcurrentMap(); - private final Map groupNameSpecs = Maps.newConcurrentMap(); - - private final Object mergeOperationLock = new Object(); - - public ModuleExclusions(ImmutableModuleIdentifierFactory moduleIdentifierFactory) { - this.moduleIdentifierFactory = moduleIdentifierFactory; - } - - /** - * Returns a spec that excludes nothing. - */ - public static ModuleExclusion excludeNone() { - return EXCLUDE_NONE; - } - - /** - * Returns a spec that excludes those modules and artifacts that are excluded by _any_ of the given exclude rules. - */ - public ModuleExclusion excludeAny(ExcludeMetadata... excludes) { - if (excludes.length == 0) { - return EXCLUDE_NONE; - } - return excludeAny(ImmutableList.copyOf(excludes)); - } - - /** - * Returns a spec that excludes those modules and artifacts that are excluded by _any_ of the given exclude rules. - */ - public ModuleExclusion excludeAny(ImmutableList excludes) { - if (excludes.isEmpty()) { - return EXCLUDE_NONE; - } - AbstractModuleExclusion exclusion = excludeAnyCache.get(excludes); - if (exclusion != null) { - return exclusion; - } - ImmutableSet.Builder exclusions = ImmutableSet.builder(); - for (ExcludeMetadata exclude : excludes) { - exclusions.add(forExclude(exclude)); - } - exclusion = asEither(exclusions.build()); - excludeAnyCache.put(excludes, exclusion); - return exclusion; - } - - private AbstractModuleExclusion forExclude(ExcludeMetadata rule) { - // For custom ivy pattern matchers, don't inspect the rule any more deeply: this prevents us from doing smart merging later - if (!PatternMatchers.isExactMatcher(rule.getMatcher())) { - return new IvyPatternMatcherExcludeRuleSpec(rule); - } - - ModuleIdentifier moduleId = rule.getModuleId(); - IvyArtifactName artifact = rule.getArtifact(); - boolean anyOrganisation = isWildcard(moduleId.getGroup()); - boolean anyModule = isWildcard(moduleId.getName()); - - // Build a strongly typed (mergeable) exclude spec for each supplied rule - if (artifact == null) { - if (!anyOrganisation && !anyModule) { - return moduleIdExcludeSpec(moduleId); - } else if (!anyModule) { - return moduleNameExcludeSpec(moduleId.getName()); - } else if (!anyOrganisation) { - return groupNameExcludeSpec(moduleId.getGroup()); - } else { - return EXCLUDE_ALL_MODULES_SPEC; - } - } else { - return new ArtifactExcludeSpec(moduleId, artifact); - } - } - - private ModuleIdExcludeSpec moduleIdExcludeSpec(ModuleIdentifier id) { - ModuleIdExcludeSpec spec = moduleIdSpecs.get(id); - if (spec == null) { - spec = new ModuleIdExcludeSpec(id); - moduleIdSpecs.put(id, spec); - } - return spec; - } - - private ModuleNameExcludeSpec moduleNameExcludeSpec(String id) { - ModuleNameExcludeSpec spec = moduleNameSpecs.get(id); - if (spec == null) { - spec = new ModuleNameExcludeSpec(id); - moduleNameSpecs.put(id, spec); - } - return spec; - } - - private GroupNameExcludeSpec groupNameExcludeSpec(String id) { - GroupNameExcludeSpec spec = groupNameSpecs.get(id); - if (spec == null) { - spec = new GroupNameExcludeSpec(id); - groupNameSpecs.put(id, spec); - } - return spec; - } - - /** - * Returns a spec that excludes those modules and artifacts that are excluded by _either_ of the given exclude rules. - */ - public ModuleExclusion either(ModuleExclusion one, ModuleExclusion two) { - if (one == two) { - return one; - } - if (one == EXCLUDE_NONE) { - return two; - } - if (two == EXCLUDE_NONE) { - return one; - } - if (one.equals(two)) { - return one; - } - - if (one instanceof EitherExclusion && ((EitherExclusion) one).getFilters().contains(two)) { - return one; - } else if (two instanceof EitherExclusion && ((EitherExclusion) two).getFilters().contains(one)) { - return two; - } - - AbstractModuleExclusion aOne = (AbstractModuleExclusion) one; - AbstractModuleExclusion aTwo = (AbstractModuleExclusion) two; - - List builder = Lists.newArrayListWithExpectedSize(estimateSize(aOne) + estimateSize(aTwo)); - - aOne.unpackEither(builder); - aTwo.unpackEither(builder); - - return asEither(ImmutableSet.copyOf(builder)); - } - - private static int estimateSize(AbstractModuleExclusion ex) { - if (ex instanceof AbstractCompositeExclusion) { - return ((AbstractCompositeExclusion) ex).getFilters().size(); - } - return 1; - } - - /** - * Returns a spec that excludes only those modules and artifacts that are excluded by _both_ of the supplied exclude rules. - */ - public ModuleExclusion both(ModuleExclusion one, ModuleExclusion two) { - if (one == two) { - return one; - } - if (one == EXCLUDE_NONE || two == EXCLUDE_NONE) { - return EXCLUDE_NONE; - } - if (one.equals(two)) { - return one; - } - - List specs = new ArrayList(); - ((AbstractModuleExclusion) one).unpackAll(specs); - ((AbstractModuleExclusion) two).unpackAll(specs); - for (int i = 0; i < specs.size();) { - AbstractModuleExclusion spec = specs.get(i); - AbstractModuleExclusion merged = null; - // See if we can merge any of the following specs into one - for (int j = i + 1; j < specs.size(); j++) { - AbstractModuleExclusion other = specs.get(j); - merged = maybeMergeIntoAll(spec, other); - if (merged != null) { - specs.remove(j); - break; + // please keep the formatting below as it helps enabling or disabling stages + private final ExcludeFactory factory = new OptimizingExcludeFactory(// optimizes for nulls, 2-params, ... mandatory + new CachingExcludeFactory(// caches the result of operations + new NormalizingExcludeFactory(// performs algebra + new DefaultExcludeFactory()// the end of the chain, mandatory + ) + ) + ); + private final Map metadataToExcludeCache = Maps.newConcurrentMap(); + private final ExcludeSpec nothing; + + public ModuleExclusions() { + nothing = factory.nothing(); + } + + public ExcludeSpec excludeAny(ImmutableList excludes) { + return factory.anyOf(excludes.stream() + .map(this::forExclude) + .collect(Collectors.toList())); + } + + public ExcludeSpec nothing() { + return nothing; + } + + private ExcludeSpec forExclude(ExcludeMetadata r) { + return metadataToExcludeCache.computeIfAbsent(r, rule -> { + // For custom ivy pattern matchers, don't inspect the rule any more deeply: this prevents us from doing smart merging later + if (!PatternMatchers.isExactMatcher(rule.getMatcher())) { + return factory.ivyPatternExclude(rule.getModuleId(), rule.getArtifact(), rule.getMatcher()); + } + + ModuleIdentifier moduleId = rule.getModuleId(); + IvyArtifactName artifact = rule.getArtifact(); + boolean anyOrganisation = isWildcard(moduleId.getGroup()); + boolean anyModule = isWildcard(moduleId.getName()); + + // Build a strongly typed (mergeable) exclude spec for each supplied rule + if (artifact == null) { + if (!anyOrganisation && !anyModule) { + return factory.moduleId(moduleId); + } else if (!anyModule) { + return factory.module(moduleId.getName()); + } else if (!anyOrganisation) { + return factory.group(moduleId.getGroup()); + } else { + return factory.everything(); } - } - if (merged != null) { - specs.set(i, merged); } else { - i++; - } - } - if (specs.size() == 1) { - return specs.get(0); - } - return new AllExclusion(specs); - } - - /** - * Attempt to merge 2 exclusions into a single filter that is the union of both. - * Currently this is only implemented when both exclusions are `IntersectionExclusion`s. - */ - private AbstractModuleExclusion maybeMergeIntoAll(AbstractModuleExclusion one, AbstractModuleExclusion two) { - if (one.equals(two)) { - return one; - } - if (one instanceof EitherExclusion && two instanceof EitherExclusion) { - return maybeMergeIntoAll((EitherExclusion) one, (EitherExclusion) two); - } - return null; - } - - private AbstractModuleExclusion maybeMergeIntoAll(EitherExclusion one, EitherExclusion other) { - if (one.equals(other)) { - return one; - } - if (one.canMerge() && other.canMerge()) { - AbstractModuleExclusion[] oneFilters = one.getFilters().elements; - AbstractModuleExclusion[] otherFilters = other.getFilters().elements; - if (Arrays.equals(oneFilters, otherFilters)) { - return one; - } - - MergeOperation merge = mergeOperation(oneFilters, otherFilters); - AbstractModuleExclusion exclusion = mergeCache.get(merge); - if (exclusion != null) { - return exclusion; - } - return mergeAndCacheResult(merge, oneFilters, otherFilters); - } - return null; - } - - private MergeOperation mergeOperation(AbstractModuleExclusion[] one, AbstractModuleExclusion[] two) { - synchronized (mergeOperationLock) { - Map oneMap = mergeOperationCache.get(one); - if (oneMap == null) { - oneMap = Maps.newIdentityHashMap(); - mergeOperationCache.put(one, oneMap); - - } - MergeOperation mergeOperation = oneMap.get(two); - if (mergeOperation != null) { - return mergeOperation; - } - mergeOperation = new MergeOperation(one, two); - oneMap.put(two, mergeOperation); - return mergeOperation; - } - } - - private AbstractModuleExclusion mergeAndCacheResult(MergeOperation merge, AbstractModuleExclusion[] oneFilters, AbstractModuleExclusion[] otherFilters) { - AbstractModuleExclusion exclusion; // Merge the exclude rules from both specs into a single union spec. - final BitSet remaining = new BitSet(otherFilters.length); - remaining.set(0, otherFilters.length, true); - MergeSet merged = new MergeSet(remaining, oneFilters.length + otherFilters.length); - for (AbstractModuleExclusion thisSpec : oneFilters) { - if (!remaining.isEmpty()) { - for (int i = remaining.nextSetBit(0); i >= 0; i = remaining.nextSetBit(i+1)) { - AbstractModuleExclusion otherSpec = otherFilters[i]; - merged.current = otherSpec; - merged.idx = i; - mergeExcludeRules(thisSpec, otherSpec, merged); - } - } - } - if (merged.isEmpty()) { - exclusion = ModuleExclusions.EXCLUDE_NONE; - } else { - exclusion = asEither(ImmutableSet.copyOf(merged)); - } - mergeCache.put(merge, exclusion); - return exclusion; - } - - private EitherExclusion asEither(ImmutableSet excludes) { - EitherExclusion cached = eitherCache.get(excludes); - if (cached == null) { - cached = new EitherExclusion(new ImmutableModuleExclusionSet(excludes)); - eitherCache.put(excludes, cached); - } - return cached; - } - - // Add exclusions to the list that will exclude modules/artifacts that are excluded by _both_ of the candidate rules. - private void mergeExcludeRules(AbstractModuleExclusion spec1, AbstractModuleExclusion spec2, Set merged) { - if (spec1 == spec2) { - merged.add(spec1); - } else if (spec1 instanceof ExcludeAllModulesSpec) { - // spec1 excludes everything: use spec2 excludes - merged.add(spec2); - } else if (spec2 instanceof ExcludeAllModulesSpec) { - // spec2 excludes everything: use spec1 excludes - merged.add(spec1); - } else if (spec1 instanceof ArtifactExcludeSpec) { - // Excludes _no_ modules, may exclude some artifacts. - // This isn't right: We are losing the artifacts excluded by spec2 - // (2 artifact excludes should cancel out unless equal) - merged.add(spec1); - } else if (spec2 instanceof ArtifactExcludeSpec) { - // Excludes _no_ modules, may exclude some artifacts. - // This isn't right: We are losing the artifacts excluded by spec2 - merged.add(spec2); - } else if (spec1 instanceof GroupNameExcludeSpec) { - // Merge into a single exclusion for Group + Module - mergeExcludeRules((GroupNameExcludeSpec) spec1, spec2, merged); - } else if (spec2 instanceof GroupNameExcludeSpec) { - // Merge into a single exclusion for Group + Module - mergeExcludeRules((GroupNameExcludeSpec) spec2, spec1, merged); - } else if (spec1 instanceof ModuleNameExcludeSpec) { - // Merge into a single exclusion for Group + Module - mergeExcludeRules((ModuleNameExcludeSpec) spec1, spec2, merged); - } else if (spec2 instanceof ModuleNameExcludeSpec) { - // Merge into a single exclusion for Group + Module - mergeExcludeRules((ModuleNameExcludeSpec) spec2, spec1, merged); - } else if ((spec1 instanceof ModuleIdExcludeSpec) && (spec2 instanceof ModuleIdExcludeSpec)) { - // Excludes nothing if the excluded module ids don't match: in that case this rule contributes nothing to the union - ModuleIdExcludeSpec moduleSpec1 = (ModuleIdExcludeSpec) spec1; - ModuleIdExcludeSpec moduleSpec2 = (ModuleIdExcludeSpec) spec2; - if (moduleSpec1.moduleId.equals(moduleSpec2.moduleId)) { - merged.add(moduleSpec1); + return factory.ivyPatternExclude(moduleId, artifact, rule.getMatcher()); } - } else { - throw new UnsupportedOperationException(String.format("Cannot calculate intersection of exclude rules: %s, %s", spec1, spec2)); - } + }); } - private void mergeExcludeRules(GroupNameExcludeSpec spec1, AbstractModuleExclusion spec2, Set merged) { - if (spec2 instanceof GroupNameExcludeSpec) { - // Intersection of 2 group excludes does nothing unless excluded groups match - GroupNameExcludeSpec groupNameExcludeSpec = (GroupNameExcludeSpec) spec2; - if (spec1.group.equals(groupNameExcludeSpec.group)) { - merged.add(spec1); - } - } else if (spec2 instanceof ModuleNameExcludeSpec) { - // Intersection of group & module name exclude only excludes module with matching group + name - ModuleNameExcludeSpec moduleNameExcludeSpec = (ModuleNameExcludeSpec) spec2; - merged.add(moduleIdExcludeSpec(moduleIdentifierFactory.module(spec1.group, moduleNameExcludeSpec.module))); - } else if (spec2 instanceof ModuleIdExcludeSpec) { - // Intersection of group + module id exclude only excludes the module id if the excluded groups match - ModuleIdExcludeSpec moduleIdExcludeSpec = (ModuleIdExcludeSpec) spec2; - if (moduleIdExcludeSpec.moduleId.getGroup().equals(spec1.group)) { - merged.add(spec2); - } - } else { - throw new UnsupportedOperationException(String.format("Cannot calculate intersection of exclude rules: %s, %s", spec1, spec2)); - } + private static boolean isWildcard(String attribute) { + return PatternMatchers.ANY_EXPRESSION.equals(attribute); } - private static void mergeExcludeRules(ModuleNameExcludeSpec spec1, AbstractModuleExclusion spec2, Set merged) { - if (spec2 instanceof ModuleNameExcludeSpec) { - // Intersection of 2 module name excludes does nothing unless excluded module names match - ModuleNameExcludeSpec moduleNameExcludeSpec = (ModuleNameExcludeSpec) spec2; - if (spec1.module.equals(moduleNameExcludeSpec.module)) { - merged.add(spec1); - } - } else if (spec2 instanceof ModuleIdExcludeSpec) { - // Intersection of module name & module id exclude only excludes module if the excluded module names match - ModuleIdExcludeSpec moduleIdExcludeSpec = (ModuleIdExcludeSpec) spec2; - if (moduleIdExcludeSpec.moduleId.getName().equals(spec1.module)) { - merged.add(spec2); - } - } else { - throw new UnsupportedOperationException(String.format("Cannot calculate intersection of exclude rules: %s, %s", spec1, spec2)); - } + public ExcludeSpec excludeAny(ExcludeSpec one, ExcludeSpec two) { + return factory.anyOf(one, two); } - private static final class MergeOperation { - private final AbstractModuleExclusion[] one; - private final AbstractModuleExclusion[] two; - private final int hashCode; - - - private MergeOperation(AbstractModuleExclusion[] one, AbstractModuleExclusion[] two) { - this.one = one; - this.two = two; - this.hashCode = 31 * Arrays.hashCode(one) + Arrays.hashCode(two); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - MergeOperation that = (MergeOperation) o; - return Arrays.equals(one, that.one) && Arrays.equals(two, that.two); - } - - @Override - public int hashCode() { - return hashCode; - } + public ExcludeSpec excludeAll(ExcludeSpec one, ExcludeSpec two) { + return factory.allOf(one, two); } - private static final class MergeSet extends LinkedHashSet { - private final BitSet remaining; - private int idx; - private AbstractModuleExclusion current; - - private MergeSet(BitSet remaining, int size) { - super(size); - this.remaining = remaining; - } - - @Override - public boolean add(AbstractModuleExclusion abstractModuleExclusion) { - if (current == abstractModuleExclusion) { - remaining.clear(idx); - } - return super.add(abstractModuleExclusion); - } - } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleIdExcludeSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleIdExcludeSpec.java deleted file mode 100644 index 62dc730fa5b6..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleIdExcludeSpec.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; - -/** - * Excludes any module that has a module id matching the one specified. - * Does not exclude artifacts. - */ -class ModuleIdExcludeSpec extends AbstractModuleExclusion { - final ModuleIdentifier moduleId; - - public ModuleIdExcludeSpec(ModuleIdentifier id) { - this.moduleId = id; - } - - @Override - public String toString() { - return "{module-id " + moduleId + "}"; - } - - @Override - protected boolean doEquals(Object o) { - ModuleIdExcludeSpec other = (ModuleIdExcludeSpec) o; - return moduleId.equals(other.moduleId); - } - - @Override - protected int doHashCode() { - return moduleId.hashCode(); - } - - @Override - protected boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - ModuleIdExcludeSpec moduleIdExcludeSpec = (ModuleIdExcludeSpec) other; - return moduleId.equals(moduleIdExcludeSpec.moduleId); - } - - public boolean excludeModule(ModuleIdentifier module) { - return module.equals(moduleId); - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleNameExcludeSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleNameExcludeSpec.java deleted file mode 100644 index 0a8effc3c4c9..000000000000 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ModuleNameExcludeSpec.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; - -import org.gradle.api.artifacts.ModuleIdentifier; - -/** - * Excludes any module that has a module name matching the one specified. - * Does not exclude artifacts. - */ -class ModuleNameExcludeSpec extends AbstractModuleExclusion { - final String module; - - ModuleNameExcludeSpec(String module) { - this.module = module; - } - - @Override - public String toString() { - return "{module " + module + "}"; - } - - @Override - protected boolean doEquals(Object o) { - ModuleNameExcludeSpec other = (ModuleNameExcludeSpec) o; - return module.equals(other.module); - } - - @Override - protected int doHashCode() { - return module.hashCode(); - } - - @Override - public boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - ModuleNameExcludeSpec moduleNameExcludeSpec = (ModuleNameExcludeSpec) other; - return module.equals(moduleNameExcludeSpec.module); - } - - public boolean excludeModule(ModuleIdentifier element) { - return element.getName().equals(module); - } -} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/PatternMatchers.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/PatternMatchers.java index 62f80b6410f1..be93559e78ba 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/PatternMatchers.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/PatternMatchers.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/CachingExcludeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/CachingExcludeFactory.java new file mode 100644 index 000000000000..6d4936102d77 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/CachingExcludeFactory.java @@ -0,0 +1,149 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories; + +import com.google.common.collect.Maps; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; + +import java.util.List; +import java.util.Map; + +/** + * This factory is responsible for caching merging queries. It delegates computations + * to another factory, so if the delegate returns the same instances for the same + * queries, caching will be faster. + */ +public class CachingExcludeFactory extends DelegatingExcludeFactory { + private final Map allOfPairCache = Maps.newConcurrentMap(); + private final Map anyOfPairCache = Maps.newConcurrentMap(); + private final Map allOfListCache = Maps.newConcurrentMap(); + private final Map anyOfListCache = Maps.newConcurrentMap(); + + public CachingExcludeFactory(ExcludeFactory delegate) { + super(delegate); + } + + @Override + public ExcludeSpec anyOf(ExcludeSpec one, ExcludeSpec two) { + return cachedAnyPair(one, two); + } + + private ExcludeSpec cachedAnyPair(ExcludeSpec left, ExcludeSpec right) { + return anyOfPairCache.computeIfAbsent(new ExcludePair(left, right), key -> delegate.anyOf(key.left, key.right)); + } + + @Override + public ExcludeSpec allOf(ExcludeSpec one, ExcludeSpec two) { + return cachedAllPair(one, two); + } + + private ExcludeSpec cachedAllPair(ExcludeSpec left, ExcludeSpec right) { + return allOfPairCache.computeIfAbsent(new ExcludePair(left, right), key -> delegate.allOf(key.left, key.right)); + } + + @Override + public ExcludeSpec anyOf(List specs) { + return anyOfListCache.computeIfAbsent(new ExcludeList(specs), key -> delegate.anyOf(key.specs)); + } + + @Override + public ExcludeSpec allOf(List specs) { + return allOfListCache.computeIfAbsent(new ExcludeList(specs), key -> delegate.allOf(key.specs)); + } + + /** + * A special key which recognizes the fact union and intersection + * are commutative. + */ + private final static class ExcludePair { + private final ExcludeSpec left; + private final ExcludeSpec right; + private final int hashCode; + + private ExcludePair(ExcludeSpec left, ExcludeSpec right) { + this.left = left; + this.right = right; + this.hashCode = left.hashCode() ^ right.hashCode(); // must be symmetrical + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ExcludePair that = (ExcludePair) o; + + return (left.equals(that.left) && right.equals(that.right)) + // symmetry + || (left.equals(that.right) && right.equals(that.left)); + } + + @Override + public int hashCode() { + return hashCode; + } + } + + /** + * A special exclude spec list key which recognizes + * that union and intersection are commutative. + */ + private static class ExcludeList { + private final List specs; + private final int size; + private final int hashCode; + + private ExcludeList(List specs) { + this.specs = specs; + this.size = specs.size(); + this.hashCode = computeHashCode(); + } + + private int computeHashCode() { + int hash = 0; + for (ExcludeSpec spec : specs) { + hash += spec.hashCode(); + } + return hash; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ExcludeList that = (ExcludeList) o; + if (size != that.size) { + return false; + } + return specs.containsAll(that.specs); + } + + @Override + public int hashCode() { + return hashCode; + } + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/DelegatingExcludeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/DelegatingExcludeFactory.java new file mode 100644 index 000000000000..3c5f35f0b7e6 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/DelegatingExcludeFactory.java @@ -0,0 +1,92 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +import java.util.List; +import java.util.Set; + +public abstract class DelegatingExcludeFactory implements ExcludeFactory { + protected final ExcludeFactory delegate; + + public DelegatingExcludeFactory(ExcludeFactory delegate) { + this.delegate = delegate; + } + + @Override + public ExcludeSpec nothing() { + return delegate.nothing(); + } + + @Override + public ExcludeSpec everything() { + return delegate.everything(); + } + + @Override + public ExcludeSpec group(String group) { + return delegate.group(group); + } + + @Override + public ExcludeSpec module(String module) { + return delegate.module(module); + } + + @Override + public ExcludeSpec moduleId(ModuleIdentifier id) { + return delegate.moduleId(id); + } + + @Override + public ExcludeSpec artifact(ModuleIdentifier id, IvyArtifactName artifact) { + return delegate.artifact(id, artifact); + } + + @Override + public ExcludeSpec anyOf(ExcludeSpec one, ExcludeSpec two) { + return delegate.anyOf(one, two); + } + + @Override + public ExcludeSpec allOf(ExcludeSpec one, ExcludeSpec two) { + return delegate.allOf(one, two); + } + + @Override + public ExcludeSpec anyOf(List specs) { + return delegate.anyOf(specs); + } + + @Override + public ExcludeSpec allOf(List specs) { + return delegate.allOf(specs); + } + + @Override + public ExcludeSpec ivyPatternExclude(ModuleIdentifier moduleId, IvyArtifactName artifact, String matcher) { + return delegate.ivyPatternExclude(moduleId, artifact, matcher); + } + + @Override + public ExcludeSpec moduleSet(Set modules) { + return delegate.moduleSet(modules); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactory.java new file mode 100644 index 000000000000..f3b4720c8fad --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactory.java @@ -0,0 +1,158 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.CompositeExclude; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeAllOf; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeAnyOf; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeEverything; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeNothing; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ModuleIdExclude; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ModuleSetExclude; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * This factory performs normalization of exclude rules. This is the smartest + * of all factories and is responsible for doing some basic algebra computations. + * It shouldn't be too slow, or the whole chain will pay the price. + */ +public class NormalizingExcludeFactory extends DelegatingExcludeFactory { + public NormalizingExcludeFactory(ExcludeFactory delegate) { + super(delegate); + } + + @Override + public ExcludeSpec anyOf(ExcludeSpec one, ExcludeSpec two) { + return doUnion(ImmutableList.of(one, two)); + } + + @Override + public ExcludeSpec allOf(ExcludeSpec one, ExcludeSpec two) { + return doIntersect(ImmutableList.of(one, two)); + } + + @Override + public ExcludeSpec anyOf(List specs) { + return doUnion(specs); + } + + @Override + public ExcludeSpec allOf(List specs) { + return doIntersect(specs); + } + + private ExcludeSpec doUnion(List specs) { + Set simpleExcludes = null; + List moduleSets = null; + Set flattened = flatten(ExcludeAnyOf.class, specs, ExcludeEverything.class::isInstance, ExcludeNothing.class::isInstance); + if (flattened == null) { + return everything(); + } + for (Iterator it = flattened.iterator(); it.hasNext(); ) { + ExcludeSpec spec = it.next(); + if (spec instanceof ModuleIdExclude) { + if (simpleExcludes == null) { + simpleExcludes = Sets.newHashSetWithExpectedSize(specs.size()); + } + simpleExcludes.add((ModuleIdExclude) spec); + it.remove(); + } + // will allow merging module sets into a single one + if (spec instanceof ModuleSetExclude) { + if (moduleSets == null) { + moduleSets = Lists.newArrayList(); + } + moduleSets.add((ModuleSetExclude) spec); + it.remove(); + + } + } + // merge all single module id into an id set + if (simpleExcludes != null) { + if (simpleExcludes.size() > 1 || moduleSets != null) { + ModuleSetExclude e = (ModuleSetExclude) delegate.moduleSet(simpleExcludes.stream().map(ModuleIdExclude::getModuleId).collect(Collectors.toSet())); + if (moduleSets != null) { + moduleSets.add(e); + } else { + flattened.add(e); + } + } else { + flattened.add(simpleExcludes.iterator().next()); + } + } + if (moduleSets != null) { + if (moduleSets.size() == 1) { + flattened.add(moduleSets.get(0)); + } else { + // merge all module sets + flattened.add(delegate.moduleSet(moduleSets.stream().flatMap(e -> e.getModuleIds().stream()).collect(Collectors.toSet()))); + } + } + if (flattened.isEmpty()) { + return nothing(); + } + return Optimizations.optimizeList(this, ImmutableList.copyOf(flattened), delegate::anyOf); + } + + /** + * Flattens a collection of elements that are going to be joined or intersected. There + * are 3 possible outcomes: + * - null means that the fast exit condition was reached, meaning that the caller knows it's not worth computing more + * - empty list meaning that an easy simplification was reached and we directly know the result + * - flattened unions/intersections + */ + private Set flatten(Class flattenType, List specs, Predicate fastExit, Predicate filter) { + Set out = null; + for (ExcludeSpec spec : specs) { + if (fastExit.test(spec)) { + return null; + } + if (!filter.test(spec)) { + if (out == null) { + out = Sets.newHashSetWithExpectedSize(4 * specs.size()); + } + if (flattenType.isInstance(spec)) { + out.addAll(((CompositeExclude) spec).getComponents()); + } else { + out.add(spec); + } + } + } + return out == null ? Collections.emptySet() : out; + } + + private ExcludeSpec doIntersect(List specs) { + Set relevant = flatten(ExcludeAllOf.class, specs, ExcludeNothing.class::isInstance, ExcludeEverything.class::isInstance); + if (relevant == null) { + return nothing(); + } + if (relevant.isEmpty()) { + return everything(); + } + return Optimizations.optimizeList(this, ImmutableList.copyOf(relevant), delegate::allOf); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/Optimizations.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/Optimizations.java new file mode 100644 index 000000000000..cf68477477ff --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/Optimizations.java @@ -0,0 +1,89 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories; + +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeEverything; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeNothing; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +public abstract class Optimizations { + public static ExcludeSpec optimizeAnyOf(ExcludeSpec one, ExcludeSpec two, BiFunction onMiss) { + // fast path for two + if (one == null) { + return two; + } + if (two == null) { + return one; + } + if (one.equals(two)) { + return one; + } + if (one instanceof ExcludeEverything) { + return one; + } + if (one instanceof ExcludeNothing) { + return two; + } + if (two instanceof ExcludeEverything) { + return two; + } + if (two instanceof ExcludeNothing) { + return one; + } + return onMiss.apply(one, two); + } + + public static ExcludeSpec optimizeAllOf(ExcludeFactory factory, ExcludeSpec one, ExcludeSpec two, BiFunction onMiss) { + // fast path for two + if (one == null) { + return two; + } + if (two == null) { + return one; + } + if (one.equals(two)) { + return one; + } + if (one instanceof ExcludeEverything) { + return two; + } + if (one instanceof ExcludeNothing) { + return factory.nothing(); + } + if (two instanceof ExcludeEverything) { + return one; + } + if (two instanceof ExcludeNothing) { + return factory.nothing(); + } + return onMiss.apply(one, two); + } + + public static ExcludeSpec optimizeList(ExcludeFactory factory, List specs, Function, ExcludeSpec> onMiss) { + if (specs.isEmpty()) { + return factory.nothing(); + } + if (specs.size() == 1) { + return specs.get(0); + } + return onMiss.apply(specs); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/OptimizingExcludeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/OptimizingExcludeFactory.java new file mode 100644 index 000000000000..d1b277af5da7 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/OptimizingExcludeFactory.java @@ -0,0 +1,61 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories; + +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; + +import java.util.List; + +/** + * This factory is responsible for optimizing in special cases: null parameters, + * list with 2 elements, ... and should be at the top of the delegation chain. + */ +public class OptimizingExcludeFactory extends DelegatingExcludeFactory { + public OptimizingExcludeFactory(ExcludeFactory delegate) { + super(delegate); + } + + @Override + public ExcludeSpec anyOf(ExcludeSpec one, ExcludeSpec two) { + return Optimizations.optimizeAnyOf(one, two, super::anyOf); + } + + @Override + public ExcludeSpec allOf(ExcludeSpec one, ExcludeSpec two) { + return Optimizations.optimizeAllOf(this, one, two, super::allOf); + } + + @Override + public ExcludeSpec anyOf(List specs) { + return Optimizations.optimizeList(this, specs, list -> { + if (list.size() == 2) { + return delegate.anyOf(list.get(0), list.get(1)); + } + return delegate.anyOf(list); + }); + } + + @Override + public ExcludeSpec allOf(List specs) { + return Optimizations.optimizeList(this, specs, list -> { + if (list.size() == 2) { + return delegate.allOf(list.get(0), list.get(1)); + } + return delegate.allOf(list); + }); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/package-info.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/package-info.java new file mode 100644 index 000000000000..5b3deca545d0 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This package contains different accessory factories for excludes. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultCompositeExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultCompositeExclude.java new file mode 100644 index 000000000000..fc694803d425 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultCompositeExclude.java @@ -0,0 +1,117 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableSet; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.CompositeExclude; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; + +import java.util.Iterator; +import java.util.stream.Stream; + +abstract class DefaultCompositeExclude implements CompositeExclude { + private final ImmutableSet components; + private final int hashCode; + + DefaultCompositeExclude(ImmutableSet components) { + this.components = components; + this.hashCode = components.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DefaultCompositeExclude that = (DefaultCompositeExclude) o; + return hashCode == that.hashCode && Objects.equal(components, that.components); + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DefaultCompositeExclude that = (DefaultCompositeExclude) o; + return equalsIgnoreArtifact(components, that.components); + } + + private boolean equalsIgnoreArtifact(ImmutableSet components, ImmutableSet other) { + if (components == other) { + return true; + } + if (components.size() != other.size()) { + return false; + } + return compareExcludingArtifacts(components, other); + } + + private boolean compareExcludingArtifacts(ImmutableSet components, ImmutableSet other) { + // The fast check iterator is there assuming that we have 2 collections with identical contents + // in which case we can perform a faster check for sets, as if they were lists + Iterator fastCheckIterator = other.iterator(); + for (ExcludeSpec component : components) { + boolean found = false; + if (fastCheckIterator != null && fastCheckIterator.next().equalsIgnoreArtifact(component)) { + break; + } + // we're unlucky, sets are either different, or in a different order + fastCheckIterator = null; + for (ExcludeSpec o : other) { + if (component.equalsIgnoreArtifact(o)) { + found = true; + break; + } + } + if (!found) { + // fast exit, when sets are actually different + return false; + } + } + return true; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public final Stream components() { + return components.stream(); + } + + @Override + public ImmutableSet getComponents() { + return components; + } + + @Override + public String toString() { + return "{" + getDisplayName() + + " " + components + + '}'; + } + + protected abstract String getDisplayName(); +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAllOf.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAllOf.java new file mode 100644 index 000000000000..3f027c46b8cf --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAllOf.java @@ -0,0 +1,55 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import com.google.common.collect.ImmutableSet; +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeAllOf; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +import java.util.List; + +final class DefaultExcludeAllOf extends DefaultCompositeExclude implements ExcludeAllOf { + public static ExcludeSpec of(List components) { + return new DefaultExcludeAllOf(ImmutableSet.copyOf(components)); + } + + private DefaultExcludeAllOf(ImmutableSet components) { + super(components); + } + + @Override + protected String getDisplayName() { + return "all of"; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return components().allMatch(e -> e.excludes(module)); + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return components().allMatch(e -> e.excludesArtifact(module, artifactName)); + } + + @Override + public boolean mayExcludeArtifacts() { + return components().allMatch(ExcludeSpec::mayExcludeArtifacts); + } + +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAnyOf.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAnyOf.java new file mode 100644 index 000000000000..ab64e51b10aa --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeAnyOf.java @@ -0,0 +1,54 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import com.google.common.collect.ImmutableSet; +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeAnyOf; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +import java.util.List; + +final class DefaultExcludeAnyOf extends DefaultCompositeExclude implements ExcludeAnyOf { + public static ExcludeSpec of(List components) { + return new DefaultExcludeAnyOf(ImmutableSet.copyOf(components)); + } + + private DefaultExcludeAnyOf(ImmutableSet components) { + super(components); + } + + @Override + protected String getDisplayName() { + return "any of"; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return components().anyMatch(e -> e.excludes(module)); + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return components().anyMatch(e -> e.excludesArtifact(module, artifactName)); + } + + @Override + public boolean mayExcludeArtifacts() { + return components().anyMatch(ExcludeSpec::mayExcludeArtifacts); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeEverything.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeEverything.java new file mode 100644 index 000000000000..d0fa7eab8725 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeEverything.java @@ -0,0 +1,72 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeEverything; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +final class DefaultExcludeEverything implements ExcludeEverything { + private static final ExcludeEverything INSTANCE = new DefaultExcludeEverything(); + + public static ExcludeSpec get() { + return INSTANCE; + } + + private DefaultExcludeEverything() { + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return true; + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + // everything excluded **only** applies to modules, not artifacts! + return false; + } + + @Override + public boolean mayExcludeArtifacts() { + return false; // an exclude all is for modules, not artifacts + } + + @Override + public String toString() { + return "{excludes everything}"; + } + + @Override + public int hashCode() { + return 1; + } + + @Override + public boolean equals(Object obj) { + return this == obj; + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec o) { + return this == o; + } + + private int size() { + return 1; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeFactory.java new file mode 100644 index 000000000000..6ac063956f9f --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeFactory.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import com.google.common.collect.ImmutableList; +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories.Optimizations; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +import java.util.List; +import java.util.Set; + +public class DefaultExcludeFactory implements ExcludeFactory { + @Override + public ExcludeSpec nothing() { + return DefaultExcludeNothing.get(); + } + + @Override + public ExcludeSpec everything() { + return DefaultExcludeEverything.get(); + } + + @Override + public ExcludeSpec group(String group) { + return DefaultGroupExclude.of(group); + } + + @Override + public ExcludeSpec module(String module) { + return DefaultModuleExclude.of(module); + } + + @Override + public ExcludeSpec moduleId(ModuleIdentifier id) { + return DefaultModuleIdExclude.of(id); + } + + @Override + public ExcludeSpec artifact(ModuleIdentifier id, IvyArtifactName artifact) { + return DefaultModuleArtifactExclude.of(id, artifact); + } + + @Override + public ExcludeSpec anyOf(ExcludeSpec one, ExcludeSpec two) { + return Optimizations.optimizeAnyOf(one, two, (a, b) -> DefaultExcludeAnyOf.of(ImmutableList.of(a, b))); + } + + @Override + public ExcludeSpec allOf(ExcludeSpec one, ExcludeSpec two) { + return Optimizations.optimizeAllOf(this, one, two, (a, b) -> DefaultExcludeAllOf.of(ImmutableList.of(a, b))); + } + + @Override + public ExcludeSpec anyOf(List specs) { + return DefaultExcludeAnyOf.of(specs); + } + + @Override + public ExcludeSpec allOf(List specs) { + return DefaultExcludeAllOf.of(specs); + } + + @Override + public ExcludeSpec ivyPatternExclude(ModuleIdentifier moduleId, IvyArtifactName artifact, String matcher) { + return DefaultIvyPatternMatcherExcludeRuleSpec.of(moduleId, artifact, matcher); + } + + @Override + public ExcludeSpec moduleSet(Set modules) { + return DefaultModuleSetExclude.of(modules); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeNothing.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeNothing.java new file mode 100644 index 000000000000..d86cc95a5e53 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultExcludeNothing.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeNothing; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +class DefaultExcludeNothing implements ExcludeNothing { + private static final ExcludeNothing INSTANCE = new DefaultExcludeNothing(); + + public static ExcludeSpec get() { + return INSTANCE; + } + + private DefaultExcludeNothing() { + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return false; + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return false; + } + + @Override + public boolean mayExcludeArtifacts() { + return false; + } + + @Override + public String toString() { + return "{excludes none}"; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public boolean equals(Object obj) { + return this == obj; + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec o) { + return this == o; + } + + private int size() { + return 1; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultGroupExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultGroupExclude.java new file mode 100644 index 000000000000..9265f9d9f841 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultGroupExclude.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.GroupExclude; +import org.gradle.internal.component.model.IvyArtifactName; + +final class DefaultGroupExclude implements GroupExclude { + private final String group; + private final int hashCode; + + private DefaultGroupExclude(String group) { + this.group = group; + this.hashCode = group.hashCode(); + } + + static ExcludeSpec of(String group) { + return new DefaultGroupExclude(group); + } + + @Override + public String getGroup() { + return group; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return group.equals(module.getGroup()); + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return false; + } + + @Override + public boolean mayExcludeArtifacts() { + return false; + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultGroupExclude that = (DefaultGroupExclude) o; + + if (hashCode != that.hashCode) { + return false; + } + return group.equals(that.group); + + } + + @Override + public int hashCode() { + return group.hashCode(); + } + + @Override + public String toString() { + return "{exclude group = '" + group + "'}"; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultIvyPatternMatcherExcludeRuleSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultIvyPatternMatcherExcludeRuleSpec.java new file mode 100644 index 000000000000..c8245cb56735 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultIvyPatternMatcherExcludeRuleSpec.java @@ -0,0 +1,118 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import com.google.common.base.Objects; +import org.apache.ivy.plugins.matcher.PatternMatcher; +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.PatternMatchers; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.IvyPatternMatcherExcludeRuleSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +final class DefaultIvyPatternMatcherExcludeRuleSpec implements IvyPatternMatcherExcludeRuleSpec { + private final ModuleIdentifier moduleId; + private final IvyArtifactName ivyArtifactName; + private final PatternMatcher matcher; + private final boolean isArtifactExclude; + private final int hashCode; + + public static ExcludeSpec of(ModuleIdentifier moduleId, IvyArtifactName artifact, String matcher) { + return new DefaultIvyPatternMatcherExcludeRuleSpec(moduleId, artifact, matcher); + } + + private DefaultIvyPatternMatcherExcludeRuleSpec(ModuleIdentifier moduleId, IvyArtifactName artifact, String matcher) { + this.moduleId = moduleId; + this.ivyArtifactName = artifact; + this.matcher = PatternMatchers.getInstance().getMatcher(matcher); + isArtifactExclude = ivyArtifactName != null; + hashCode = Objects.hashCode(moduleId, ivyArtifactName, matcher, isArtifactExclude); + } + + @Override + public String toString() { + return "{exclude-rule " + moduleId + ":" + ivyArtifactName + " with matcher " + matcher.getName() + "}"; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + if (isArtifactExclude) { + return false; + } + return matches(moduleId.getGroup(), module.getGroup()) && matches(moduleId.getName(), module.getName()); + } + + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifact) { + if (!isArtifactExclude) { + return false; + } + return matches(moduleId.getGroup(), module.getGroup()) + && matches(moduleId.getName(), module.getName()) + && matches(ivyArtifactName.getName(), artifact.getName()) + && matches(ivyArtifactName.getExtension(), artifact.getExtension()) + && matches(ivyArtifactName.getType(), artifact.getType()); + } + + public boolean mayExcludeArtifacts() { + return isArtifactExclude; + } + + private boolean matches(String expression, String input) { + return matcher.getMatcher(expression).matches(input); + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DefaultIvyPatternMatcherExcludeRuleSpec that = (DefaultIvyPatternMatcherExcludeRuleSpec) o; + return isArtifactExclude == that.isArtifactExclude && + Objects.equal(moduleId, that.moduleId) && + Objects.equal(matcher, that.matcher); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DefaultIvyPatternMatcherExcludeRuleSpec that = (DefaultIvyPatternMatcherExcludeRuleSpec) o; + return hashCode == that.hashCode && + isArtifactExclude == that.isArtifactExclude && + Objects.equal(moduleId, that.moduleId) && + Objects.equal(ivyArtifactName, that.ivyArtifactName) && + Objects.equal(matcher, that.matcher); + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public IvyArtifactName getArtifact() { + return ivyArtifactName; + } + +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleArtifactExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleArtifactExclude.java new file mode 100644 index 000000000000..69af6ce4af41 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleArtifactExclude.java @@ -0,0 +1,85 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ArtifactExclude; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.internal.component.model.IvyArtifactName; + +final class DefaultModuleArtifactExclude implements ArtifactExclude { + private final ModuleIdentifier moduleId; + private final IvyArtifactName artifactName; + private final int hashCode; + + static ArtifactExclude of(ModuleIdentifier id, IvyArtifactName artifact) { + return new DefaultModuleArtifactExclude(id, artifact); + } + + private DefaultModuleArtifactExclude(ModuleIdentifier moduleId, IvyArtifactName artifactName) { + this.moduleId = moduleId; + this.artifactName = artifactName; + this.hashCode = 31 * moduleId.hashCode() + artifactName.hashCode(); + } + + @Override + public IvyArtifactName getArtifact() { + return artifactName; + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return moduleId.equals(module) && this.artifactName.equals(artifactName); + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + DefaultModuleArtifactExclude exc = (DefaultModuleArtifactExclude) other; + return moduleId.equals(exc.moduleId); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultModuleArtifactExclude that = (DefaultModuleArtifactExclude) o; + + if (hashCode != that.hashCode) { + return false; + } + if (!moduleId.equals(that.moduleId)) { + return false; + } + return artifactName.equals(that.artifactName); + + } + + @Override + public int hashCode() { + return hashCode; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleExclude.java new file mode 100644 index 000000000000..dab2af2adc97 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleExclude.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ModuleExclude; +import org.gradle.internal.component.model.IvyArtifactName; + +final class DefaultModuleExclude implements ModuleExclude { + private final String module; + private final int hashCode; + + public static ExcludeSpec of(String module) { + return new DefaultModuleExclude(module); + } + + private DefaultModuleExclude(String module) { + this.module = module; + this.hashCode = module.hashCode(); + } + + @Override + public String getModule() { + return module; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return this.module.equals(module.getName()); + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return false; + } + + @Override + public boolean mayExcludeArtifacts() { + return false; + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultModuleExclude that = (DefaultModuleExclude) o; + + if (hashCode != that.hashCode) { + return false; + } + return module.equals(that.module); + + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public String toString() { + return "{exclude module = '" + module + "'}"; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleIdExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleIdExclude.java new file mode 100644 index 000000000000..fa33f5b7e90f --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleIdExclude.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ModuleIdExclude; +import org.gradle.internal.component.model.IvyArtifactName; + +final class DefaultModuleIdExclude implements ModuleIdExclude { + private final ModuleIdentifier moduleId; + private final int hashCode; + + static ModuleIdExclude of(ModuleIdentifier id) { + return new DefaultModuleIdExclude(id); + } + + private DefaultModuleIdExclude(ModuleIdentifier moduleId) { + this.moduleId = moduleId; + this.hashCode = moduleId.hashCode(); + } + + @Override + public ModuleIdentifier getModuleId() { + return moduleId; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return moduleId.equals(module); + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return false; + } + + @Override + public boolean mayExcludeArtifacts() { + return false; + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultModuleIdExclude that = (DefaultModuleIdExclude) o; + + if (hashCode != that.hashCode) { + return false; + } + return moduleId.equals(that.moduleId); + + } + + @Override + public int hashCode() { + return moduleId.hashCode(); + } + + @Override + public String toString() { + return "{exclude module id = '" + moduleId + "'}"; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleSetExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleSetExclude.java new file mode 100644 index 000000000000..f4bf9f1c3407 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/DefaultModuleSetExclude.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; + +import com.google.common.collect.ImmutableSet; +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ModuleSetExclude; +import org.gradle.internal.component.model.IvyArtifactName; + +import java.util.Set; + +final class DefaultModuleSetExclude implements ModuleSetExclude { + private final Set moduleIds; + private final int hashCode; + + static ModuleSetExclude of(Set ids) { + return new DefaultModuleSetExclude(ImmutableSet.copyOf(ids)); + } + + private DefaultModuleSetExclude(ImmutableSet moduleIds) { + this.moduleIds = moduleIds; + this.hashCode = moduleIds.hashCode(); + } + + @Override + public Set getModuleIds() { + return moduleIds; + } + + @Override + public boolean excludes(ModuleIdentifier module) { + return moduleIds.contains(module); + } + + @Override + public boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName) { + return false; + } + + @Override + public boolean mayExcludeArtifacts() { + return false; + } + + @Override + public boolean equalsIgnoreArtifact(ExcludeSpec other) { + return equals(other); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultModuleSetExclude that = (DefaultModuleSetExclude) o; + + return moduleIds.equals(that.moduleIds); + + } + + @Override + public int hashCode() { + return hashCode; + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/package-info.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/package-info.java new file mode 100644 index 000000000000..b6a89d979304 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/simple/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This package contains the leaf exclude type implementations. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ExcludeNone.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ArtifactExclude.java similarity index 62% rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ExcludeNone.java rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ArtifactExclude.java index 05295501a01b..c7ef4c4758ed 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ExcludeNone.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ArtifactExclude.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,34 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.internal.component.model.IvyArtifactName; -class ExcludeNone extends AbstractModuleExclusion { - @Override - public String toString() { - return "{exclude-none}"; - } - - @Override - protected boolean doEquals(Object o) { - return true; - } - - @Override - protected int doHashCode() { - return 0; - } - +public interface ArtifactExclude extends ExcludeSpec { @Override - public boolean excludeModule(ModuleIdentifier module) { + default boolean excludes(ModuleIdentifier module) { return false; } @Override - protected boolean excludesNoModules() { + default boolean mayExcludeArtifacts() { return true; } + + IvyArtifactName getArtifact(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/CompositeExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/CompositeExclude.java new file mode 100644 index 000000000000..85c0bc324e43 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/CompositeExclude.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +import java.util.Collection; +import java.util.stream.Stream; + +public interface CompositeExclude extends ExcludeSpec { + @Override + boolean equals(Object o); + + Stream components(); + + Collection getComponents(); + + default boolean contains(ExcludeSpec spec) { + return components().anyMatch(spec::equals); + } +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAllOf.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAllOf.java new file mode 100644 index 000000000000..6109f3c099ea --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAllOf.java @@ -0,0 +1,19 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface ExcludeAllOf extends CompositeExclude { +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAnyOf.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAnyOf.java new file mode 100644 index 000000000000..5fa17734c077 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeAnyOf.java @@ -0,0 +1,19 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface ExcludeAnyOf extends CompositeExclude { +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeEverything.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeEverything.java new file mode 100644 index 000000000000..f2c94d3b7da0 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeEverything.java @@ -0,0 +1,19 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface ExcludeEverything extends ExcludeSpec { +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeFactory.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeFactory.java new file mode 100644 index 000000000000..b7e35a51351f --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeFactory.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.internal.component.model.IvyArtifactName; + +import java.util.List; +import java.util.Set; + +public interface ExcludeFactory { + ExcludeSpec nothing(); + + ExcludeSpec everything(); + + ExcludeSpec group(String group); + + ExcludeSpec module(String module); + + ExcludeSpec moduleId(ModuleIdentifier id); + + ExcludeSpec artifact(ModuleIdentifier id, IvyArtifactName artifact); + + ExcludeSpec anyOf(ExcludeSpec one, ExcludeSpec two); + + ExcludeSpec allOf(ExcludeSpec one, ExcludeSpec two); + + ExcludeSpec anyOf(List specs); + + ExcludeSpec allOf(List specs); + + ExcludeSpec ivyPatternExclude(ModuleIdentifier moduleId, IvyArtifactName artifact, String matcher); + + ExcludeSpec moduleSet(Set modules); +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeNothing.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeNothing.java new file mode 100644 index 000000000000..ca1d6c1d423a --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeNothing.java @@ -0,0 +1,19 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface ExcludeNothing extends ExcludeSpec { +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeSpec.java new file mode 100644 index 000000000000..7cd89f75354d --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ExcludeSpec.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +import org.gradle.api.artifacts.ModuleIdentifier; +import org.gradle.internal.component.model.IvyArtifactName; + +public interface ExcludeSpec { + /** + * Determines if this exclude rule excludes the supplied module. + */ + boolean excludes(ModuleIdentifier module); + + /** + * Determines if this exclude rule excludes the supplied artifact, for the specified module. + */ + boolean excludesArtifact(ModuleIdentifier module, IvyArtifactName artifactName); + + /** + * Tells if this rule may exclude some artifacts. This is used to optimize artifact resolution. + */ + boolean mayExcludeArtifacts(); + + /** + * This method is used to determine if 2 excludes are equivalent, only differing by the artifact they exclude. + * This is used by the resolution engine to figure out if it should invalidate a previous visit or not. + */ + boolean equalsIgnoreArtifact(ExcludeSpec other); + +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/GroupExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/GroupExclude.java new file mode 100644 index 000000000000..3ecd5e978341 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/GroupExclude.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface GroupExclude extends ExcludeSpec { + String getGroup(); +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/IvyPatternMatcherExcludeRuleSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/IvyPatternMatcherExcludeRuleSpec.java new file mode 100644 index 000000000000..56f467fa59b9 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/IvyPatternMatcherExcludeRuleSpec.java @@ -0,0 +1,19 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface IvyPatternMatcherExcludeRuleSpec extends ArtifactExclude { +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleExclude.java new file mode 100644 index 000000000000..1862bd502089 --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleExclude.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +public interface ModuleExclude extends ExcludeSpec { + String getModule(); +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleIdExclude.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleIdExclude.java new file mode 100644 index 000000000000..4ce47c8f368d --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleIdExclude.java @@ -0,0 +1,22 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; + +import org.gradle.api.artifacts.ModuleIdentifier; + +public interface ModuleIdExclude extends ExcludeSpec { + ModuleIdentifier getModuleId(); +} diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ExcludeAllModulesSpec.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleSetExclude.java similarity index 53% rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ExcludeAllModulesSpec.java rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleSetExclude.java index 633e8e65000f..de8742d30477 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/ExcludeAllModulesSpec.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/ModuleSetExclude.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,34 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes; +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; import org.gradle.api.artifacts.ModuleIdentifier; -class ExcludeAllModulesSpec extends AbstractModuleExclusion { - @Override - public String toString() { - return "{exclude-all}"; - } - - @Override - protected boolean doEquals(Object o) { - return true; - } - - @Override - protected int doHashCode() { - return 0; - } - - @Override - public boolean doExcludesSameModulesAs(AbstractModuleExclusion other) { - return true; - } +import java.util.Set; - @Override - public boolean excludeModule(ModuleIdentifier module) { - return true; - } +public interface ModuleSetExclude extends ExcludeSpec { + Set getModuleIds(); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/package-info.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/package-info.java new file mode 100644 index 000000000000..1d7c9a15a78d --- /dev/null +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/specs/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This package contains the base interfaces for module exclusion specs. + */ +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/DependencyGraphEdge.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/DependencyGraphEdge.java index c6303c9c8dce..f36e84efaf00 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/DependencyGraphEdge.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/DependencyGraphEdge.java @@ -17,7 +17,7 @@ package org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph; import org.gradle.api.artifacts.Dependency; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.model.ComponentArtifactMetadata; import org.gradle.internal.component.model.ConfigurationMetadata; @@ -34,7 +34,7 @@ public interface DependencyGraphEdge extends ResolvedGraphDependency { DependencyGraphSelector getSelector(); - ModuleExclusion getExclusions(); + ExcludeSpec getExclusions(); boolean contributesArtifacts(); diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/EdgeState.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/EdgeState.java index 930eff01866f..49b04b209984 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/EdgeState.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/EdgeState.java @@ -24,7 +24,8 @@ import org.gradle.api.artifacts.component.ComponentSelector; import org.gradle.api.artifacts.result.ComponentSelectionReason; import org.gradle.api.attributes.Attribute; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphEdge; import org.gradle.api.internal.attributes.AttributeMergingException; import org.gradle.api.internal.attributes.ImmutableAttributes; @@ -54,7 +55,7 @@ class EdgeState implements DependencyGraphEdge { private final NodeState from; private final SelectorState selector; private final ResolveState resolveState; - private final ModuleExclusion transitiveExclusions; + private final ExcludeSpec transitiveExclusions; private final List targetNodes = Lists.newLinkedList(); private final boolean isTransitive; private final boolean isConstraint; @@ -62,7 +63,7 @@ class EdgeState implements DependencyGraphEdge { private ModuleVersionResolveException targetNodeSelectionFailure; private ImmutableAttributes cachedAttributes; - EdgeState(NodeState from, DependencyState dependencyState, ModuleExclusion transitiveExclusions, ResolveState resolveState) { + EdgeState(NodeState from, DependencyState dependencyState, ExcludeSpec transitiveExclusions, ResolveState resolveState) { this.from = from; this.dependencyState = dependencyState; this.dependencyMetadata = dependencyState.getDependency(); @@ -243,16 +244,17 @@ private boolean isVirtualDependency() { } @Override - public ModuleExclusion getExclusions() { + public ExcludeSpec getExclusions() { List excludes = dependencyMetadata.getExcludes(); if (excludes.isEmpty()) { return transitiveExclusions; } - ModuleExclusion edgeExclusions = resolveState.getModuleExclusions().excludeAny(ImmutableList.copyOf(excludes)); - return resolveState.getModuleExclusions().either(edgeExclusions, transitiveExclusions); + ModuleExclusions moduleExclusions = resolveState.getModuleExclusions(); + ExcludeSpec edgeExclusions = moduleExclusions.excludeAny(ImmutableList.copyOf(excludes)); + return moduleExclusions.excludeAny(edgeExclusions, transitiveExclusions); } - public ModuleExclusion getEdgeExclusions() { + ExcludeSpec getEdgeExclusions() { List excludes = dependencyMetadata.getExcludes(); if (excludes.isEmpty()) { return null; diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/NodeState.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/NodeState.java index 5198e9a4b4bf..a4f32568876c 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/NodeState.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/NodeState.java @@ -28,8 +28,7 @@ import org.gradle.api.internal.artifacts.DependencySubstitutionInternal; import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier; import org.gradle.api.internal.artifacts.ivyservice.dependencysubstitution.DependencySubstitutionApplicator; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphNode; import org.gradle.api.internal.attributes.ImmutableAttributesFactory; import org.gradle.api.specs.Spec; @@ -76,7 +75,8 @@ public boolean isSatisfiedBy(EdgeState edge) { private final boolean isTransitive; private final boolean selectedByVariantAwareResolution; - ModuleExclusion previousTraversalExclusions; + ExcludeSpec previousTraversalExclusions; + // In opposite to outgoing edges, virtual edges are for now pretty rare, so they are created lazily private List virtualEdges; private boolean queued; @@ -222,7 +222,7 @@ public void visitOutgoingDependencies(Collection discoveredEdges) { } // Determine the net exclusion for this node, by inspecting all transitive incoming edges - ModuleExclusion resolutionFilter = getModuleResolutionFilter(incomingEdges); + ExcludeSpec resolutionFilter = getModuleResolutionFilter(incomingEdges); // Virtual platforms require their constraints to be recomputed each time as each module addition can cause a shift in versions if (!isVirtualPlatformNeedsRefresh()) { @@ -304,7 +304,7 @@ private void handleNonTransitiveNode(Collection discoveredEdges) { * Iterate over the dependencies originating in this node, adding them either as a 'pending' dependency * or adding them to the `discoveredEdges` collection (and `this.outgoingEdges`) */ - private void visitDependencies(ModuleExclusion resolutionFilter, Collection discoveredEdges) { + private void visitDependencies(ExcludeSpec resolutionFilter, Collection discoveredEdges) { PendingDependenciesVisitor pendingDepsVisitor = resolveState.newPendingDependenciesVisitor(); try { for (DependencyMetadata dependency : metaData.getDependencies()) { @@ -327,7 +327,7 @@ private void visitDependencies(ModuleExclusion resolutionFilter, Collection discoveredEdges, ModuleExclusion resolutionFilter, boolean deferSelection) { + private void createAndLinkEdgeState(DependencyState dependencyState, Collection discoveredEdges, ExcludeSpec resolutionFilter, boolean deferSelection) { EdgeState dependencyEdge = new EdgeState(this, dependencyState, resolutionFilter, resolveState); outgoingEdges.add(dependencyEdge); discoveredEdges.add(dependencyEdge); @@ -438,17 +438,17 @@ private List getTransitiveIncomingEdges() { return incomingEdges; } - private boolean isExcluded(ModuleExclusion selector, DependencyState dependencyState) { + private boolean isExcluded(ExcludeSpec selector, DependencyState dependencyState) { DependencyMetadata dependency = dependencyState.getDependency(); if (!resolveState.getEdgeFilter().isSatisfiedBy(dependency)) { LOGGER.debug("{} is filtered.", dependency); return true; } - if (selector == ModuleExclusions.excludeNone()) { + if (selector == resolveState.getModuleExclusions().nothing()) { return false; } ModuleIdentifier targetModuleId = dependencyState.getModuleIdentifier(); - if (selector.excludeModule(targetModuleId)) { + if (selector.excludes(targetModuleId)) { LOGGER.debug("{} is excluded from {}.", targetModuleId, this); return true; } @@ -479,14 +479,14 @@ public boolean shouldIncludedInGraphResult() { return isSelected() && !component.getModule().isVirtualPlatform(); } - private ModuleExclusion getModuleResolutionFilter(List incomingEdges) { - ModuleExclusions moduleExclusions = resolveState.getModuleExclusions(); - ModuleExclusion nodeExclusions = moduleExclusions.excludeAny(metaData.getExcludes()); + private ExcludeSpec getModuleResolutionFilter(List incomingEdges) { + org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions moduleExclusions = resolveState.getModuleExclusions(); + ExcludeSpec nodeExclusions = moduleExclusions.excludeAny(metaData.getExcludes()); if (incomingEdges.isEmpty()) { return nodeExclusions; } - ModuleExclusion edgeExclusions = null; + ExcludeSpec edgeExclusions = null; for (EdgeState dependencyEdge : incomingEdges) { if (dependencyEdge.isTransitive()) { @@ -494,31 +494,19 @@ private ModuleExclusion getModuleResolutionFilter(List incomingEdges) edgeExclusions = excludedByBoth(edgeExclusions, dependencyEdge.getExclusions()); } else if (dependencyEdge.getDependencyMetadata().isConstraint()) { // Constraint: only consider explicit exclusions declared for this constraint - ModuleExclusion constraintExclusions = dependencyEdge.getEdgeExclusions(); + ExcludeSpec constraintExclusions = dependencyEdge.getEdgeExclusions(); nodeExclusions = excludedByEither(nodeExclusions, constraintExclusions); } } return excludedByEither(edgeExclusions, nodeExclusions); } - private ModuleExclusion excludedByBoth(ModuleExclusion one, ModuleExclusion two) { - if (one == null) { - return two; - } - if (two == null) { - return one; - } - return resolveState.getModuleExclusions().both(one, two); + private ExcludeSpec excludedByBoth(ExcludeSpec one, ExcludeSpec two) { + return resolveState.getModuleExclusions().excludeAll(one, two); } - private ModuleExclusion excludedByEither(ModuleExclusion one, ModuleExclusion two) { - if (one == null) { - return two; - } - if (two == null) { - return one; - } - return resolveState.getModuleExclusions().either(one, two); + private ExcludeSpec excludedByEither(ExcludeSpec one, ExcludeSpec two) { + return resolveState.getModuleExclusions().excludeAny(one, two); } private void removeOutgoingEdges() { diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/FixedComponentArtifacts.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/FixedComponentArtifacts.java index d7b4e1b8f4b5..f19f3d939d7f 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/FixedComponentArtifacts.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/FixedComponentArtifacts.java @@ -21,7 +21,7 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.model.ComponentArtifactMetadata; @@ -48,7 +48,7 @@ public List getArtifacts() { } @Override - public ArtifactSet getArtifactsFor(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet getArtifactsFor(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { return DefaultArtifactSet.singleVariant(component.getId(), component.getModuleVersionId(), configuration.asDescribable(), artifacts, component.getSource(), exclusions, component.getAttributesSchema(), artifactResolver, allResolvedArtifacts, artifactTypeRegistry, overriddenAttributes); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/MetadataSourcedComponentArtifacts.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/MetadataSourcedComponentArtifacts.java index 65ad6c4c5beb..dc3e8171b1d6 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/MetadataSourcedComponentArtifacts.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/external/model/MetadataSourcedComponentArtifacts.java @@ -20,7 +20,7 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.model.ComponentArtifacts; @@ -35,7 +35,7 @@ */ public class MetadataSourcedComponentArtifacts implements ComponentArtifacts { @Override - public ArtifactSet getArtifactsFor(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet getArtifactsFor(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { return DefaultArtifactSet.multipleVariants(component.getId(), component.getModuleVersionId(), component.getSource(), exclusions, configuration.getVariants(), component.getAttributesSchema(), artifactResolver, allResolvedArtifacts, artifactTypeRegistry, overriddenAttributes); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/ComponentArtifacts.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/ComponentArtifacts.java index bbe40f6a04c2..d472253621dd 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/ComponentArtifacts.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/component/model/ComponentArtifacts.java @@ -19,7 +19,7 @@ import org.gradle.api.artifacts.component.ComponentArtifactIdentifier; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.resolve.resolver.ArtifactResolver; @@ -33,5 +33,5 @@ public interface ComponentArtifacts { /** * Returns the variants for the given configuration. The values that are returned are retained for the life of the current build, so should reference as little state as possible. Should also be thread safe. */ - ArtifactSet getArtifactsFor(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes); + ArtifactSet getArtifactsFor(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactResolver artifactResolver, Map allResolvedArtifacts, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/ArtifactSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/ArtifactSelector.java index 0cfde84a1e6c..8315ea214182 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/ArtifactSelector.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/ArtifactSelector.java @@ -17,7 +17,7 @@ package org.gradle.internal.resolve.resolver; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.local.model.LocalFileDependencyMetadata; import org.gradle.internal.component.model.ComponentArtifactMetadata; @@ -30,7 +30,7 @@ public interface ArtifactSelector { /** * Creates a set that will resolve the artifacts of the given configuration, minus those artifacts that are excluded. */ - ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes); + ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes); /** * Creates a set that will resolve the given artifacts of the given component. diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/DefaultArtifactSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/DefaultArtifactSelector.java index 4b014722c534..b2c6cdf564d6 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/DefaultArtifactSelector.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/DefaultArtifactSelector.java @@ -22,8 +22,8 @@ import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.FileDependencyArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple.DefaultExcludeFactory; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.Describables; @@ -37,6 +37,8 @@ import java.util.Map; public class DefaultArtifactSelector implements ArtifactSelector { + private static final ExcludeSpec EXCLUDE_NONE = new DefaultExcludeFactory().nothing(); + private final Map allResolvedArtifacts = Maps.newHashMap(); private final List selectors; private final ArtifactTypeRegistry artifactTypeRegistry; @@ -54,7 +56,7 @@ public ArtifactSet resolveArtifacts(LocalFileDependencyMetadata fileDependencyMe } @Override - public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { ArtifactSet artifacts = null; for (OriginArtifactSelector selector : selectors) { artifacts = selector.resolveArtifacts(component, configuration, artifactTypeRegistry, exclusions, overriddenAttributes); @@ -70,6 +72,6 @@ public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, Configur @Override public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, Collection artifacts, ImmutableAttributes overriddenAttributes) { - return DefaultArtifactSet.singleVariant(component.getId(), component.getModuleVersionId(), Describables.of(component.getId()), artifacts, component.getSource(), ModuleExclusions.excludeNone(), component.getAttributesSchema(), artifactResolver, allResolvedArtifacts, artifactTypeRegistry, overriddenAttributes); + return DefaultArtifactSet.singleVariant(component.getId(), component.getModuleVersionId(), Describables.of(component.getId()), artifacts, component.getSource(), EXCLUDE_NONE, component.getAttributesSchema(), artifactResolver, allResolvedArtifacts, artifactTypeRegistry, overriddenAttributes); } } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/OriginArtifactSelector.java b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/OriginArtifactSelector.java index 417f76df206b..e295d624140b 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/OriginArtifactSelector.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/internal/resolve/resolver/OriginArtifactSelector.java @@ -17,7 +17,7 @@ package org.gradle.internal.resolve.resolver; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.internal.component.model.ComponentResolveMetadata; @@ -30,5 +30,5 @@ public interface OriginArtifactSelector { * Creates a set that will resolve the artifacts of the given configuration, minus those artifacts that are excluded. */ @Nullable - ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes); + ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes); } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolverTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolverTest.groovy index 4c38b10d4b08..1c7bf8d8ae1b 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolverTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/ivyresolve/RepositoryChainArtifactResolverTest.groovy @@ -17,7 +17,7 @@ package org.gradle.api.internal.artifacts.ivyservice.ivyresolve import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry import org.gradle.api.internal.attributes.ImmutableAttributes import org.gradle.internal.component.model.ComponentArtifactMetadata @@ -57,7 +57,7 @@ class RepositoryChainArtifactResolverTest extends Specification { def artifacts = Mock(ComponentArtifacts) def configuration = Stub(ConfigurationMetadata) def artifactTypeRegistry = Stub(ArtifactTypeRegistry) - def exclusion = Stub(ModuleExclusion) + def exclusion = Stub(ExcludeSpec) def artifactSet = Stub(ArtifactSet) when: @@ -82,7 +82,7 @@ class RepositoryChainArtifactResolverTest extends Specification { def artifacts = Mock(ComponentArtifacts) def configuration = Stub(ConfigurationMetadata) def artifactTypeRegistry = Stub(ArtifactTypeRegistry) - def exclusion = Stub(ModuleExclusion) + def exclusion = Stub(ExcludeSpec) def artifactSet = Stub(ArtifactSet) when: diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy index e21f95488187..aa8b52afebb9 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/DependencyGraphBuilderTest.groovy @@ -92,7 +92,7 @@ class DependencyGraphBuilderTest extends Specification { DefaultModuleIdentifier.newId(*args) } } - def moduleExclusions = new ModuleExclusions(moduleIdentifierFactory) + def moduleExclusions = new ModuleExclusions() def buildOperationProcessor = Mock(BuildOperationExecutor) { def queue = Mock(BuildOperationQueue) { add(_) >> { args -> diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/DefaultModuleExclusionTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/DefaultModuleExclusionTest.groovy deleted file mode 100644 index 01beda4ce5f0..000000000000 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/DefaultModuleExclusionTest.groovy +++ /dev/null @@ -1,818 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes - -import groovy.transform.NotYetImplemented -import org.gradle.api.internal.artifacts.DefaultModuleIdentifier -import org.gradle.api.internal.artifacts.ImmutableModuleIdentifierFactory -import org.gradle.internal.component.external.descriptor.DefaultExclude -import org.gradle.internal.component.model.DefaultIvyArtifactName -import org.gradle.internal.component.model.Exclude -import org.gradle.internal.component.model.IvyArtifactName -import spock.lang.Specification -import spock.lang.Unroll - -import static org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions.excludeNone - -class DefaultModuleExclusionTest extends Specification { - def moduleExclusions = new ModuleExclusions(Mock(ImmutableModuleIdentifierFactory) { - module(_, _) >> { args -> - DefaultModuleIdentifier.newId(*args) - } - }) - - def "accepts all modules default"() { - def spec = excludeAny() - - expect: - !spec.excludeModule(moduleId("org", "module")) - } - - def "accepts all artifacts by default"() { - def spec = excludeAny() - - expect: - !spec.excludeArtifact(moduleId("org", "module"), artifactName("test", "jar", "jar")) - !spec.mayExcludeArtifacts() - } - - def "spec with no rules excludes nothing"() { - expect: - excludeAny().is(excludeNone()) - } - - def "default specs accept the same modules as each other"() { - expect: - excludeAny().excludesSameModulesAs(excludeAny()) - excludeNone().excludesSameModulesAs(excludeNone()) - } - - def "specs are equal when they contain the same rules"() { - def rule1 = excludeRule("*", "*") - def rule2 = excludeRule("org", "*") - def rule3 = excludeRule("org", "module") - - expect: - excludeAny(rule1) == excludeAny(rule1) - excludeAny(rule1) != excludeAny(rule2) - excludeAny(rule1) != excludeAny(rule1, rule2) - - excludeAny(rule2, rule1) == excludeAny(rule1, rule2) - excludeAny(rule2, rule1) != excludeAny(rule1, rule3) - excludeAny(rule2, rule1) != excludeAny(rule1, rule2, rule3) - } - - @Unroll - def "does not accept module that matches single module exclude rule (#rule)"() { - when: - def spec = excludeAny(rule) - - then: - spec.excludeModule(moduleId('org', 'module')) - - where: - rule << [excludeRule('*', '*'), - excludeRule('org', 'module'), - excludeRule('org', '*'), - excludeRule('*', 'module'), - regexpExcludeRule('*', '*'), - regexpExcludeRule('or.*', 'module'), - regexpExcludeRule('org', 'mod.*'), - regexpExcludeRule('or.*', '*'), - regexpExcludeRule('*', 'mod.*')] - } - - @Unroll - def "accepts module that doesn't match single module exclude rule (#rule)"() { - when: - def spec = excludeAny(rule) - - then: - !spec.excludeModule(moduleId('org', 'module')) - - where: - rule << [excludeRule('org2', 'module2'), - excludeRule('*', 'module2'), - excludeRule('org2', '*'), - regexpExcludeRule('or.*2', "module"), - regexpExcludeRule('org', "mod.*2"), - regexpExcludeRule('or.*2', "*"), - regexpExcludeRule('*', "mod.*2")] - } - - @Unroll - def "module exclude rule selects the same modules as itself (#rule)"() { - when: - def spec = excludeAny(rule) - def same = excludeAny(rule) - def all = excludeAny() - def otherRule = excludeAny(excludeRule('*', 'other')) - def artifactRule = excludeAny(excludeRule('*', 'other', 'thing', '*', '*')) - - then: - spec.excludesSameModulesAs(spec) - spec.excludesSameModulesAs(same) - !spec.excludesSameModulesAs(all) - !spec.excludesSameModulesAs(otherRule) - !spec.excludesSameModulesAs(artifactRule) - - where: - rule << [excludeRule('*', '*'), - excludeRule('*', 'module'), - excludeRule('org', '*'), - excludeRule('org', 'module'), - regexpExcludeRule('or.*', "module"), - regexpExcludeRule('org', "mod.*")] - } - - @Unroll - def "accepts module for every artifact exclude rule (#rule)"() { - when: - def spec = excludeAny(rule) - - then: - !spec.excludeModule(moduleId('org', 'module')) - spec.mayExcludeArtifacts() - - where: - rule << [excludeRule('*', '*', 'artifact'), - excludeRule('org', '*', 'artifact'), - excludeRule('org', 'module', 'artifact'), - regexpExcludeRule('.*', "m.*", 'artifact')] - } - - @Unroll - def "accepts artifact for every module exclude rule (#rule)"() { - when: - def spec = excludeAny(rule) - - then: - !spec.excludeArtifact(moduleId('org', 'module'), artifactName('name', 'jar', 'jar')) - !spec.mayExcludeArtifacts() - - where: - rule << [excludeRule('*', '*'), - excludeRule('org', 'module'), - excludeRule('org', '*'), - excludeRule('*', 'module'), - regexpExcludeRule('*', '*'), - regexpExcludeRule('or.*', 'module'), - regexpExcludeRule('org', 'mod.*'), - regexpExcludeRule('or.*', '*'), - regexpExcludeRule('*', 'mod.*')] - } - - @Unroll - def "does not accept artifact that matches single artifact exclude rule (#rule)"() { - when: - def spec = excludeAny(rule) - - then: - spec.excludeArtifact(moduleId('org', 'module'), artifactName('mylib', 'jar', 'jar')) - spec.mayExcludeArtifacts() - - where: - rule << [excludeRule('org', 'module', 'mylib', 'jar', 'jar'), - excludeRule('org', 'module', '*', 'jar', 'jar'), - excludeRule('org', 'module', 'mylib', '*', 'jar'), - excludeRule('org', 'module', 'mylib', 'jar', '*'), - regexpExcludeRule('org', 'module', 'my.*', 'jar', 'jar'), - regexpExcludeRule('org', 'module', 'my.*', '*', '*'), - regexpExcludeRule('org', 'module', 'mylib', 'j.*', 'jar'), - regexpExcludeRule('org', 'module', '*', 'j.*', 'jar'), - regexpExcludeRule('org', 'module', 'mylib', 'jar', 'j.*'), - regexpExcludeRule('org', 'module', 'mylib', '*', 'j.*')] - } - - @Unroll - def "accepts artifact that doesn't match single artifact exclude rule (#rule)"() { - when: - def spec = excludeAny(rule) - - then: - !spec.excludeArtifact(moduleId('org', 'module'), artifactName('mylib', 'jar', 'jar')) - - where: - rule << [excludeRule('*', 'module'), - excludeRule('org', '*'), - excludeRule('org', 'module'), - excludeRule('*', 'module2'), - excludeRule('org2', '*'), - excludeRule('org2', 'module2'), - excludeRule('org', 'module', 'mylib', 'sources', 'jar'), - excludeRule('org', 'module', 'mylib', 'jar', 'war'), - excludeRule('org', 'module', 'otherlib', 'jar', 'jar'), - excludeRule('org', 'module', 'otherlib', '*', '*'), - excludeRule('org', 'module', 'otherlib', '*', 'jar'), - excludeRule('org', 'module', 'otherlib', 'jar', '*'), - excludeRule('org', 'module', '*', 'sources', 'jar'), - excludeRule('org', 'module', '*', 'sources', '*'), - excludeArtifactRule('mylib', 'sources', 'jar'), - excludeArtifactRule('mylib', 'jar', 'war'), - excludeArtifactRule('otherlib', 'jar', 'jar'), - excludeArtifactRule('otherlib', '*', '*'), - excludeArtifactRule('*', 'sources', 'jar'), - excludeArtifactRule('otherlib', '*', 'jar'), - excludeArtifactRule('otherlib', 'jar', '*'), - regexpExcludeRule('or.*2', 'module'), - regexpExcludeRule('org', 'mod.*2'), - regexpExcludeRule('org', 'module', 'my.*2', '*', '*'), - regexpExcludeRule('org', 'module', 'mylib', 'j.*2', '*'), - regexpExcludeRule('org', 'module', 'mylib', 'jar', 'j.*2'), - regexpExcludeArtifactRule('my.*2', '*', '*'), - regexpExcludeArtifactRule('mylib', 'j.*2', '*'), - regexpExcludeArtifactRule('mylib', 'jar', 'j.*2')] - } - - @Unroll - def "artifact exclude rule accepts the same modules as other rules that accept all modules (#rule)"() { - when: - def spec = excludeAny(rule) - def sameRule = excludeAny(rule) - def otherRule = excludeAny(excludeRule('*', '*', 'thing', '*', '*')) - def all = excludeNone() - def moduleRule = excludeAny(excludeRule('*', 'module')) - - then: - spec.excludesSameModulesAs(spec) - spec.excludesSameModulesAs(sameRule) - spec.excludesSameModulesAs(otherRule) - spec.excludesSameModulesAs(all) - all.excludesSameModulesAs(spec) - - !spec.excludesSameModulesAs(moduleRule) - !moduleRule.excludesSameModulesAs(spec) - - spec.excludesSameModulesAs(both(spec, otherRule)) - spec.excludesSameModulesAs(both(spec, moduleRule)) - spec.excludesSameModulesAs(either(spec, both(otherRule, sameRule))) - - where: - rule << [excludeRule('*', '*', '*', 'jar', 'jar'), - excludeRule('org', 'module', 'mylib', 'jar', 'jar'), - excludeRule('org', 'module', '*', 'jar', 'jar'), - excludeRule('org', 'module', 'mylib', '*', 'jar'), - excludeRule('org', 'module', 'mylib', 'jar', '*'), - regexpExcludeRule('org', "module", 'my.*', 'jar', 'jar'), - regexpExcludeRule('org', "module", 'mylib', 'j.*', 'jar'), - regexpExcludeRule('org', "module", 'mylib', 'jar', 'j.*')] - } - - def "does not accept module version that matches any exclude rule"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def rule3 = excludeRule("org2", "*") - def rule4 = excludeRule("*", "module4") - def rule5 = regexpExcludeRule("regexp-\\d+", "module\\d+") - def spec = excludeAny(rule1, rule2, rule3, rule4, rule5) - - expect: - spec.excludeModule(moduleId("org", "module")) - spec.excludeModule(moduleId("org", "module2")) - spec.excludeModule(moduleId("org2", "anything")) - spec.excludeModule(moduleId("other", "module4")) - spec.excludeModule(moduleId("regexp-72", "module12")) - !spec.excludeModule(moduleId("org", "other")) - !spec.excludeModule(moduleId("regexp-72", "other")) - !spec.excludeModule(moduleId("regexp", "module2")) - } - - def "specs with the same set of exclude rules accept the same modules as each other"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def rule3 = excludeRule("org2", "*") - def rule4 = excludeRule("*", "module4") - def rule5 = regexpExcludeRule("pattern1", "pattern2") - def exactMatchSpec = excludeAny(rule1) - def moduleWildcard = excludeAny(rule3) - def groupWildcard = excludeAny(rule4) - def regexp = excludeAny(rule5) - def manyRules = excludeAny(rule1, rule2, rule3, rule4, rule5) - - expect: - exactMatchSpec.excludesSameModulesAs(exactMatchSpec) - exactMatchSpec.excludesSameModulesAs(excludeAny(rule1)) - - !exactMatchSpec.excludesSameModulesAs(excludeAny(rule2)) - !exactMatchSpec.excludesSameModulesAs(excludeAny()) - !exactMatchSpec.excludesSameModulesAs(excludeAny(rule1, rule2)) - - moduleWildcard.excludesSameModulesAs(moduleWildcard) - moduleWildcard.excludesSameModulesAs(excludeAny(rule3)) - - !moduleWildcard.excludesSameModulesAs(excludeAny(rule1)) - !moduleWildcard.excludesSameModulesAs(excludeAny(rule1, rule3)) - !moduleWildcard.excludesSameModulesAs(excludeAny()) - !moduleWildcard.excludesSameModulesAs(excludeAny(excludeRule("org3", "*"))) - - groupWildcard.excludesSameModulesAs(groupWildcard) - groupWildcard.excludesSameModulesAs(excludeAny(rule4)) - - !groupWildcard.excludesSameModulesAs(excludeAny(rule1)) - !groupWildcard.excludesSameModulesAs(excludeAny(rule1, rule4)) - !groupWildcard.excludesSameModulesAs(excludeAny()) - !groupWildcard.excludesSameModulesAs(excludeAny(excludeRule("*", "module5"))) - - regexp.excludesSameModulesAs(regexp) - regexp.excludesSameModulesAs(excludeAny(rule5)) - - !regexp.excludesSameModulesAs(excludeAny(rule1)) - !regexp.excludesSameModulesAs(excludeAny(rule1, rule5)) - !regexp.excludesSameModulesAs(excludeAny()) - !regexp.excludesSameModulesAs(excludeAny(regexpExcludeRule("pattern", "other"))) - - manyRules.excludesSameModulesAs(manyRules) - manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, rule3, rule4, rule5)) - - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule3, rule4, rule5)) - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, rule4, rule5)) - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, rule3, rule5)) - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, rule3, rule4)) - - !manyRules.excludesSameModulesAs(excludeAny(rule1, excludeRule("org", "module3"), rule3, rule4, rule5)) - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, excludeRule("org3", "*"), rule4, rule5)) - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, rule3, excludeRule("*", "module5"), rule5)) - !manyRules.excludesSameModulesAs(excludeAny(rule1, rule2, rule3, rule4, regexpExcludeRule("other", "other"))) - } - - def "union with empty spec is empty spec"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeArtifactRule("b", "jar", "jar") - def spec = excludeAny(rule1, rule2) - def spec2 = excludeNone() - - expect: - both(spec, spec2).is(spec2) - both(spec2, spec).is(spec2) - } - - def "union of a spec with itself returns the original spec"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def rule3 = excludeArtifactRule("a", "jar", "jar") - def spec = excludeAny(rule1, rule2, rule3) - - expect: - both(spec, spec).is(spec) - } - - def "union of two specs with the same exclude rule instances returns one of the original specs"() { - def rule1 = excludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = excludeRule("org2", "*") - def rule4 = excludeRule("*", "module3") - def spec = excludeAny(rule1, rule2, rule3, rule4) - def spec2 = excludeAny(rule2, rule3, rule1, rule4) - - expect: - both(spec, spec2).is(spec) - } - - @NotYetImplemented - def "union of two specs where one spec contains a superset of rules returns the spec with the subset of rules"() { - def rule1 = excludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = excludeRule("org2", "*") - def rule4 = excludeRule("*", "module3") - def spec = excludeAny(rule1, rule2, rule3, rule4) - def spec2 = excludeAny(rule2, rule1, rule4) - - expect: - both(spec, spec2).is(spec2) - both(spec2, spec).is(spec2) - } - - def "union of two specs with exact matching exclude rules uses the either of the exclude rules"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def rule3 = excludeRule("org", "module3") - def spec = excludeAny(rule1, rule2) - def spec2 = excludeAny(rule1, rule3) - - expect: - def union = both(spec, spec2) - union == excludeAny(rule1) - } - - def "union of spec with module wildcard uses the most specific matching exclude rules"() { - def rule1 = excludeRule("org", "*") - def rule2 = excludeRule("org", "module") - def rule3 = excludeRule("org", "module2") - def rule4 = excludeRule("other", "module") - def rule5 = excludeRule("*", "module3") - def rule6 = excludeRule("org2", "*") - def spec = excludeAny(rule1) - - expect: - def union1 = both(spec, excludeAny(rule2, rule3, rule4)) - union1 == excludeAny(rule2, rule3) - - def union2 = both(spec, excludeAny(rule5)) - union2 == excludeAny(excludeRule("org", "module3")) - - def union3 = both(spec, excludeAny(rule6, rule2)) - union3 == excludeAny(rule2) - } - - def "union of spec with group wildcard uses the most specific matching exclude rules"() { - def rule1 = excludeRule("*", "module") - def rule2 = excludeRule("org", "module") - def rule3 = excludeRule("org", "module2") - def rule4 = excludeRule("other", "module") - def rule5 = excludeRule("org", "*") - def rule6 = excludeRule("*", "module2") - def spec = excludeAny(rule1) - - expect: - def union1 = both(spec, excludeAny(rule2, rule3, rule4)) - union1 == excludeAny(rule2, rule4) - - def union2 = both(spec, excludeAny(rule5)) - union2 == excludeAny(excludeRule("org", "module")) - - def union3 = both(spec, excludeAny(rule6)) - union3 == excludeNone() - } - - def "union of two specs with disjoint exact matching exclude rules excludes no modules"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def spec = excludeAny(rule1) - def spec2 = excludeAny(rule2) - - expect: - def union = both(spec, spec2) - union == excludeNone() - } - - def "union of a spec with exclude-all spec returns the original spec"() { - def rule1 = excludeRule("*", "*") - def rule2 = excludeRule("org", "module2") - def spec1 = excludeAny(rule1) - def spec2 = excludeAny(rule2) - - expect: - both(spec1, spec2) == spec2 - both(spec2, spec1) == spec2 - } - - def "union of module spec and artifact spec uses the artifact spec"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("*", "module-2") - def rule3 = excludeRule("org", "*-2") - def artifactRule1 = excludeRule("org", "module", "art", "*", "*") - def artifactRule2 = excludeRule("*", "*", "*", "jar", "*") - def artifactSpec1 = excludeAny(artifactRule1) - def artifactSpec2 = excludeAny(artifactRule1, artifactRule2) - - expect: - def union1 = both(artifactSpec1, excludeAny(rule1)) - union1 == artifactSpec1 - - def union2 = both(artifactSpec1, excludeAny(rule1, rule2, rule3)) - union2 == artifactSpec1 - - def union3 = both(artifactSpec2, excludeAny(rule1, rule2, rule3)) - union3 == artifactSpec2 - } - - def "union of two specs with non-exact matching exclude rules is a union spec"() { - def rule1 = excludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def spec = excludeAny(rule1) - def spec2 = excludeAny(rule2) - - expect: - def union = both(spec, spec2) - def specs = [] - union.unpackAll(specs) - specs.size() == 2 - specs[0] == spec - specs[1] == spec2 - } - - def "union of union specs is the union of the original specs"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def rule3 = regexpExcludeRule("org", "module2") - def spec = excludeAny(rule1) - def spec2 = excludeAny(rule1, rule2) - def spec3 = excludeAny(rule3) - - expect: - def union = both(both(spec, spec3), spec2) - - union instanceof AllExclusion - union.filters.size() == 2 - union.filters.any { - it instanceof EitherExclusion && it.excludeSpecs == spec.excludeSpecs - } - union.filters.contains(spec3) - } - - // Regression test for GRADLE-3275, also exercises GRADLE-3434 - def "either propagates through child union rules"() { - def rule1 = excludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = regexpExcludeRule("org", "module3") - def spec = excludeAny(rule1) - def spec2 = excludeAny(rule1, rule2) - def spec3 = excludeAny(rule3) - - def excludeBacked1 = either(spec, spec2); // module + module2 - def union1 = both(spec2, spec3); // module, module2, module3 - def excludeBacked2 = either(spec2, union1); // module, module2 - def finalUnion = both(spec3, excludeBacked2); // module - - expect: - // Sanity checks. - excludeBacked1 == spec2 - def specs = [] - union1.unpackAll(specs) - specs == [spec2, spec3]; - - // Verify test is exercising the function it's supposed to. - excludeBacked1 instanceof EitherExclusion - excludeBacked2 instanceof EitherExclusion - - union1 instanceof AllExclusion - finalUnion instanceof AllExclusion - - !spec2.excludeModule(moduleId("org", "module4")) - - // Verify that this function passes the either operation through to union2's rules. - !finalUnion.excludeModule(moduleId("org", "module")) - !finalUnion.excludeModule(moduleId("org", "module2")) - !finalUnion.excludeModule(moduleId("org", "module3")) - } - - def "union accept module that is accepted by any merged exclude rule"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def spec = excludeAny(rule1, rule2) - def spec2 = excludeAny(rule1) - - expect: - def union1 = both(spec, spec2) - - spec.excludeModule(moduleId("org", "module")) - union1.excludeModule(moduleId("org", "module")) - - spec.excludeModule(moduleId("org", "module2")) - !union1.excludeModule(moduleId("org", "module2")) - } - - def "union accepts artifact that is accepted by any merged exclude rule"() { - def moduleId = moduleId("org", "module") - def excludeA = excludeRule("org", "module", "a") - def excludeB = excludeRule("org", "module", "b") - def spec = excludeAny(excludeA) - def spec2 = excludeAny(excludeB) - - when: - def union1 = both(spec, spec2) - - then: - union1.excludeArtifact(moduleId, artifactName("a", "zip", "zip")) - !union1.excludeArtifact(moduleId, artifactName("b", "zip", "zip")) - !union1.excludeArtifact(moduleId, artifactName("c", "zip", "zip")) - - union1.mayExcludeArtifacts() - } - - def "unions accepts same modules when original specs accept same modules"() { - def rule1 = regexpExcludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = regexpExcludeRule("org", "module3") - def spec1 = excludeAny(rule1) - def spec2 = excludeAny(rule2) - def spec3 = excludeAny(rule3) - - expect: - both(spec1, spec2).excludesSameModulesAs(both(spec2, spec1)) - - !both(spec1, spec2).excludesSameModulesAs(spec2) - !both(spec1, spec2).excludesSameModulesAs(spec1) - !both(spec1, spec2).excludesSameModulesAs(both(spec1, spec3)) - } - - def "either with empty spec is original spec"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeArtifactRule("b", "jar", "jar") - def spec = excludeAny(rule1, rule2) - def spec2 = excludeNone() - - expect: - either(spec, spec2).is(spec) - either(spec2, spec).is(spec) - } - - def "either of a spec with itself returns the original spec"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def rule3 = excludeArtifactRule("b", "jar", "jar") - def spec = excludeAny(rule1, rule2, rule3) - - expect: - either(spec, spec).is(spec) - } - - def "either of two specs with the same exclude rule instances returns one of the original specs"() { - def rule1 = excludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = excludeRule("org2", "*") - def rule4 = excludeRule("*", "module3") - def spec = excludeAny(rule1, rule2, rule3, rule4) - def spec2 = excludeAny(rule2, rule3, rule1, rule4) - - expect: - either(spec, spec2).is(spec) - } - - def "either of two specs where one spec contains a superset of the rules of the other returns the spec containing the superset"() { - def rule1 = excludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = excludeRule("org2", "*") - def rule4 = excludeRule("*", "module3") - def spec = excludeAny(rule1, rule2, rule3, rule4) - def spec2 = excludeAny(rule2, rule1, rule4) - - expect: - either(spec, spec2).is(spec) - either(spec2, spec).is(spec) - } - - def "either does not accept module that is not accepted by any merged exclude rules"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def spec = excludeAny(rule1, rule2) - def spec2 = excludeAny(rule1) - - expect: - def either = either(spec, spec2) - - spec.excludeModule(moduleId("org", "module")) - either.excludeModule(moduleId("org", "module")) - - spec.excludeModule(moduleId("org", "module2")) - either.excludeModule(moduleId("org", "module2")) - - !spec.excludeModule(moduleId("org", "module3")) - !spec2.excludeModule(moduleId("org", "module3")) - !either.excludeModule(moduleId("org", "module3")) - } - - def "either accepts artifact that is accepted by every merged exclude rule"() { - def moduleId = moduleId("org", "module") - def excludeA = excludeRule("org", "module", "a") - def excludeB = excludeRule("org", "module", "b") - def spec = excludeAny(excludeA, excludeB) - def spec2 = excludeAny(excludeA) - - expect: - def either = either(spec, spec2) - - either.excludeArtifact(moduleId, artifactName("a", "zip", "zip")) - either.excludeArtifact(moduleId, artifactName("b", "zip", "zip")) - !either.excludeArtifact(moduleId, artifactName("c", "zip", "zip")) - - either.mayExcludeArtifacts() - } - - def "either of two specs with exclude rules is the union of the exclude rules"() { - def rule1 = excludeRule("org", "module") - def rule2 = excludeRule("org", "module2") - def spec = excludeAny(rule1, rule2) - def spec2 = excludeAny(rule1) - - expect: - def either = either(spec, spec2) - either == excludeAny(rule1, rule2) - } - - def "eithers accepts same modules when original specs accept same modules"() { - def rule1 = regexpExcludeRule("org", "module") - def rule2 = regexpExcludeRule("org", "module2") - def rule3 = regexpExcludeRule("org", "module3") - def spec1 = both(excludeAny(rule1), excludeAny(rule2)) - def spec2 = both(excludeAny(rule2), excludeAny(rule1)) - def spec3 = excludeAny(rule3) - assert spec1.excludesSameModulesAs(spec2) - - expect: - either(spec1, spec2).excludesSameModulesAs(either(spec2, spec1)) - - !either(spec1, spec2).excludesSameModulesAs(spec1) - !either(spec1, spec2).excludesSameModulesAs(spec2) - !either(spec1, spec2).excludesSameModulesAs(either(spec1, spec3)) - } - - def "does not accept artifact that matches specific exclude rule"() { - def rule1 = excludeArtifactRule("a", "jar", "jar") - def rule2 = excludeArtifactRule("b", "jar", "jar") - def rule3 = excludeArtifactRule("c", "*", "*") - def rule4 = excludeArtifactRule("d", "*", "jar") - def rule5 = excludeArtifactRule("e", "sources", "jar") - def rule6 = excludeArtifactRule("f", "sources", "*") - def rule7 = excludeArtifactRule("g", "jar", "war") - def rule8 = regexpExcludeArtifactRule("regexp-\\d+", "jar", "jar") - def spec = excludeAny(rule1, rule2, rule3, rule4, rule5, rule6, rule7, rule8) - - expect: - spec.excludeArtifact(moduleId("org", "module"), artifactName("a", "jar", "jar")) - spec.excludeArtifact(moduleId("org", "module2"), artifactName("b", "jar", "jar")) - spec.excludeArtifact(moduleId("org2", "anything"), artifactName("c", "jar", "jar")) - spec.excludeArtifact(moduleId("other", "module4"), artifactName("d", "jar", "jar")) - spec.excludeArtifact(moduleId("some", "app"), artifactName("e", "sources", "jar")) - spec.excludeArtifact(moduleId("foo", "bar"), artifactName("f", "sources", "jar")) - spec.excludeArtifact(moduleId("well", "known"), artifactName("g", "jar", "war")) - spec.excludeArtifact(moduleId("other", "sample"), artifactName("regexp-99", "jar", "jar")) - !spec.excludeArtifact(moduleId("some", "app"), artifactName("e", "jar", "jar")) - !spec.excludeArtifact(moduleId("some", "app"), artifactName("e", "javadoc", "jar")) - !spec.excludeArtifact(moduleId("foo", "bar"), artifactName("f", "jar", "jar")) - !spec.excludeArtifact(moduleId("well", "known"), artifactName("g", "jar", "jar")) - !spec.excludeArtifact(moduleId("well", "known"), artifactName("g", "jar", "zip")) - !spec.excludeArtifact(moduleId("other", "sample"), artifactName("regexp", "jar", "jar")) - } - - def "can merge excludes with default and non-default ivy pattern matchers"() { - def simpleExclude = excludeAny(excludeModuleRule("module-exclude")) - def regexpExclude = excludeAny(regexpExcludeRule("regexp-match", "*")) - def unmergedUnion = both(simpleExclude, regexpExclude) - def either = either(unmergedUnion, simpleExclude) - - expect: - both(either, simpleExclude) - } - - ModuleExclusion both(ModuleExclusion spec, ModuleExclusion otherRule) { - moduleExclusions.both(spec, otherRule) - } - - ModuleExclusion either(ModuleExclusion spec, ModuleExclusion otherRule) { - moduleExclusions.either(spec, otherRule) - } - - ModuleExclusion excludeAny(Exclude... excludes) { - moduleExclusions.excludeAny(excludes) - } - - static specForRule(def spec, Exclude rule) { - return spec.moduleId.group == rule.moduleId.group && spec.moduleId.name == rule.moduleId.name - } - - def moduleId(String group, String name) { - return DefaultModuleIdentifier.newId(group, name); - } - - def artifactName(String name, String type, String ext) { - return new DefaultIvyArtifactName(name, type, ext) - } - - def excludeRule(String org, String module) { - new DefaultExclude(DefaultModuleIdentifier.newId(org, module), null, new String[0], PatternMatchers.EXACT) - } - - def excludeRule(String org, String module, String name, String type = "*", String ext = "*") { - IvyArtifactName artifactName = new DefaultIvyArtifactName(name, type, ext) - new DefaultExclude(DefaultModuleIdentifier.newId(org, module), artifactName, new String[0], PatternMatchers.EXACT) - } - - def excludeModuleRule(String module) { - new DefaultExclude(DefaultModuleIdentifier.newId("*", module)) - } - - def excludeGroupRule(String group) { - new DefaultExclude(DefaultModuleIdentifier.newId(group, "*")) - } - - def excludeArtifactRule(String name, String type, String ext) { - excludeRule("*", "*", name, type, ext) - } - - def regexpExcludeRule(String org, String module) { - new DefaultExclude(DefaultModuleIdentifier.newId(org, module), null, new String[0], "regexp") - } - - def regexpExcludeRule(String org, String module, String name, String type = "*", String ext = "*") { - IvyArtifactName ivyArtifactName = new DefaultIvyArtifactName(name, type, ext) - new DefaultExclude(DefaultModuleIdentifier.newId(org, module), ivyArtifactName, new String[0], "regexp") - } - - def regexpExcludeArtifactRule(String name, String type, String ext) { - regexpExcludeRule("*", "*", name, type, ext) - } -} diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactoryTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactoryTest.groovy new file mode 100644 index 000000000000..57acacc8d6d7 --- /dev/null +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/factories/NormalizingExcludeFactoryTest.groovy @@ -0,0 +1,137 @@ +/* + * Copyright 2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.factories + +import com.google.common.collect.ImmutableList +import org.gradle.api.internal.artifacts.DefaultModuleIdentifier +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.simple.DefaultExcludeFactory +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeFactory +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec +import org.gradle.internal.component.model.DefaultIvyArtifactName +import org.gradle.internal.component.model.IvyArtifactName +import spock.lang.Shared +import spock.lang.Specification +import spock.lang.Subject +import spock.lang.Unroll + +class NormalizingExcludeFactoryTest extends Specification { + + @Shared + private ExcludeFactory delegate = new DefaultExcludeFactory() + + @Subject + private NormalizingExcludeFactory factory = new NormalizingExcludeFactory(delegate) + + @Shared + private DefaultIvyArtifactName artifactName = new DefaultIvyArtifactName("a", "b", "c") + + @Unroll("#left ∪ #right = #expected") + def "union of two elements"() { + expect: + factory.anyOf(left, right) == expected + + and: "union is commutative" + factory.anyOf(right, left) == expected + + where: + left | right | expected +/* everything() | nothing() | everything() + everything() | everything() | everything() + nothing() | nothing() | nothing() + everything() | group("foo") | everything() + nothing() | group("foo") | group("foo") + group("foo") | group("bar") | anyOf(group("foo"), group("bar")) + group("foo") | module("bar") | anyOf(group("foo"), module("bar"))*/ + anyOf(group("foo"), group("bar")) | group("foo") | anyOf(group("foo"), group("bar")) + anyOf(group("foo"), module("bar")) | module("bar") | anyOf(module("bar"), group("foo")) + } + + @Unroll("#one ∪ #two ∪ #three = #expected") + def "union of three elements"() { + expect: + [one, two, three].combinations().each { list -> + assert factory.anyOf(list) == expected + } + + where: + one | two | three | expected + everything() | nothing() | nothing() | everything() + everything() | everything() | everything() | everything() + nothing() | nothing() | nothing() | nothing() + everything() | group("foo") | everything() | everything() + group("foo") | group("bar") | group("baz") | anyOf(group("foo"), group("bar"), group("baz")) + } + + @Unroll("#left ∩ #right = #expected") + def "intersection of two elements"() { + expect: + factory.allOf(left, right) == expected + + and: "intersection is commutative" + factory.allOf(right, left) == expected + + where: + left | right | expected + everything() | nothing() | nothing() + everything() | everything() | everything() + nothing() | nothing() | nothing() + everything() | group("foo") | group("foo") + nothing() | group("foo") | nothing() + group("foo") | group("foo") | group("foo") + allOf(group("foo"), group("foo2")) | module("bar") | allOf(group("foo2"), group("foo"), module("bar")) + } + + private ExcludeSpec nothing() { + delegate.nothing() + } + + private ExcludeSpec everything() { + delegate.everything() + } + + private ExcludeSpec group(String group) { + delegate.group(group) + } + + private ExcludeSpec module(String module) { + delegate.module(module) + } + + private ExcludeSpec module(String group, String name) { + delegate.moduleId(DefaultModuleIdentifier.newId(group, name)) + } + + private ExcludeSpec anyOf(ExcludeSpec... specs) { + delegate.anyOf(ImmutableList.copyOf(specs)) + } + + private ExcludeSpec allOf(ExcludeSpec... specs) { + delegate.allOf(ImmutableList.copyOf(specs)) + } + + private ExcludeSpec ivy(String group, String module, IvyArtifactName artifact, String matcher) { + delegate.ivyPatternExclude( + DefaultModuleIdentifier.newId(group, module), + artifact, + matcher + ) + } + + private static IvyArtifactName artifact(String name) { + new DefaultIvyArtifactName(name, "jar", "jar") + } +} diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/IvyDependencyDescriptorTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/IvyDependencyDescriptorTest.groovy index 6fa3d7ce1f47..312f2a5a149f 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/IvyDependencyDescriptorTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/IvyDependencyDescriptorTest.groovy @@ -16,15 +16,16 @@ package org.gradle.internal.component.external.model +import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableListMultimap import com.google.common.collect.ImmutableSet import com.google.common.collect.LinkedHashMultimap import org.gradle.api.artifacts.component.ComponentIdentifier import org.gradle.api.artifacts.component.ModuleComponentSelector -import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.DefaultModuleIdentifier -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.PatternMatchers +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec import org.gradle.internal.component.external.descriptor.Artifact import org.gradle.internal.component.external.descriptor.DefaultExclude import org.gradle.internal.component.external.model.ivy.IvyDependencyDescriptor @@ -38,6 +39,8 @@ import static com.google.common.collect.ImmutableList.copyOf class IvyDependencyDescriptorTest extends ExternalDependencyDescriptorTest { + private final static ExcludeSpec NOTHING = new ModuleExclusions().nothing() + @Override ExternalDependencyDescriptor create(ModuleComponentSelector selector) { return new IvyDependencyDescriptor(selector, ImmutableListMultimap.of()) @@ -101,40 +104,40 @@ class IvyDependencyDescriptorTest extends ExternalDependencyDescriptorTest { def "excludes nothing when no exclude rules provided"() { def dep = createWithExcludes(requested, []) - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() expect: - moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration("from").hierarchy))) == ModuleExclusions.excludeNone() - moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration("anything").hierarchy))) == ModuleExclusions.excludeNone() + moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration("from").hierarchy))) == NOTHING + moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration("anything").hierarchy))) == NOTHING } def "excludes nothing when traversing a different configuration"() { def exclude = new DefaultExclude(DefaultModuleIdentifier.newId("group", "*"), ["from"] as String[], PatternMatchers.EXACT) def dep = createWithExcludes(requested, [exclude]) - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() expect: - moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration("anything").hierarchy))) == ModuleExclusions.excludeNone() + moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration("anything").hierarchy))) == NOTHING } def "applies exclude rules when traversing a configuration"() { def exclude = new DefaultExclude(DefaultModuleIdentifier.newId("group", "*"), ["from"] as String[], PatternMatchers.EXACT) def dep = createWithExcludes(requested, [exclude]) def configuration = configuration("from") - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() expect: - moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration.hierarchy))) == moduleExclusions.excludeAny(exclude) + moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration.hierarchy))) == moduleExclusions.excludeAny(ImmutableList.of(exclude)) } def "applies rules when traversing a child of specified configuration"() { def exclude = new DefaultExclude(DefaultModuleIdentifier.newId("group", "*"), ["from"] as String[], PatternMatchers.EXACT) def dep = createWithExcludes(requested, [exclude]) def configuration = configuration("child", "from") - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() expect: - moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration.hierarchy))) == moduleExclusions.excludeAny(exclude) + moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration.hierarchy))) == moduleExclusions.excludeAny(ImmutableList.of(exclude)) } def "applies matching exclude rules"() { @@ -143,10 +146,10 @@ class IvyDependencyDescriptorTest extends ExternalDependencyDescriptorTest { def exclude3 = new DefaultExclude(DefaultModuleIdentifier.newId("group3", "*"), ["other"] as String[], PatternMatchers.EXACT) def dep = createWithExcludes(requested, [exclude1, exclude2, exclude3]) def configuration = configuration("from") - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() expect: - moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration.hierarchy))) == moduleExclusions.excludeAny(exclude1, exclude2) + moduleExclusions.excludeAny(copyOf(dep.getConfigurationExcludes(configuration.hierarchy))) == moduleExclusions.excludeAny(ImmutableList.of(exclude1, exclude2)) } def "selects no configurations when no configuration mappings provided"() { diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/MavenDependencyDescriptorTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/MavenDependencyDescriptorTest.groovy index 364c0797750f..98975bbe60bc 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/MavenDependencyDescriptorTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/external/model/MavenDependencyDescriptorTest.groovy @@ -31,13 +31,14 @@ */ package org.gradle.internal.component.external.model +import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSet import org.gradle.api.artifacts.component.ComponentIdentifier import org.gradle.api.artifacts.component.ModuleComponentSelector -import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.DefaultModuleIdentifier -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.PatternMatchers +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec import org.gradle.internal.component.external.descriptor.DefaultExclude import org.gradle.internal.component.external.descriptor.MavenScope import org.gradle.internal.component.external.model.maven.MavenDependencyDescriptor @@ -47,11 +48,12 @@ import org.gradle.internal.component.model.ComponentResolveMetadata import org.gradle.internal.component.model.ConfigurationMetadata import org.gradle.internal.component.model.ConfigurationNotFoundException import org.gradle.internal.component.model.Exclude -import org.gradle.internal.component.model.ExcludeMetadata +import org.gradle.internal.component.model.ExcludeMetadata class MavenDependencyDescriptorTest extends ExternalDependencyDescriptorTest { - final ModuleExclusions moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) - + final ModuleExclusions moduleExclusions = new ModuleExclusions() + final ExcludeSpec nothing = moduleExclusions.nothing() + @Override ExternalDependencyDescriptor create(ModuleComponentSelector selector) { return mavenDependencyMetadata(MavenScope.Compile, selector, []) @@ -66,7 +68,7 @@ class MavenDependencyDescriptorTest extends ExternalDependencyDescriptorTest { expect: def exclusions = moduleExclusions.excludeAny(dep.allExcludes) - exclusions == ModuleExclusions.excludeNone() + exclusions == nothing exclusions.is(moduleExclusions.excludeAny(dep.allExcludes)) } @@ -77,7 +79,7 @@ class MavenDependencyDescriptorTest extends ExternalDependencyDescriptorTest { expect: def exclusions = moduleExclusions.excludeAny(dep.allExcludes) - exclusions == moduleExclusions.excludeAny(exclude1, exclude2) + exclusions == moduleExclusions.excludeAny(ImmutableList.of(exclude1, exclude2)) exclusions.is(moduleExclusions.excludeAny(dep.allExcludes)) } diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/local/model/DefaultLocalComponentMetadataTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/local/model/DefaultLocalComponentMetadataTest.groovy index 3e74a451defc..06ec41b3aef5 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/local/model/DefaultLocalComponentMetadataTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/local/model/DefaultLocalComponentMetadataTest.groovy @@ -18,12 +18,10 @@ package org.gradle.internal.component.local.model import com.google.common.collect.ImmutableSet import org.gradle.api.artifacts.PublishArtifact -import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.DefaultModuleIdentifier import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier import org.gradle.api.internal.artifacts.DefaultPublishArtifactSet import org.gradle.api.internal.artifacts.configurations.OutgoingVariant -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact import org.gradle.api.internal.attributes.AttributeContainerInternal import org.gradle.api.internal.attributes.AttributesSchemaInternal @@ -66,7 +64,6 @@ class DefaultLocalComponentMetadataTest extends Specification { } def "configuration has no dependencies or artifacts when none have been added"() { - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) when: metadata.addConfiguration("super", "description", [] as Set, ImmutableSet.of("super"), false, false, ImmutableAttributes.EMPTY, true, true, ImmutableCapabilities.EMPTY) metadata.addConfiguration("conf", "description", ["super"] as Set, ImmutableSet.of("super", "conf"), true, true, ImmutableAttributes.EMPTY, true, true, ImmutableCapabilities.EMPTY) diff --git a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/LocalComponentDependencyMetadataTest.groovy b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/LocalComponentDependencyMetadataTest.groovy index adf654269986..f66bb71c10f5 100644 --- a/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/LocalComponentDependencyMetadataTest.groovy +++ b/subprojects/dependency-management/src/test/groovy/org/gradle/internal/component/model/LocalComponentDependencyMetadataTest.groovy @@ -26,7 +26,6 @@ import org.gradle.api.artifacts.component.ProjectComponentSelector import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.AttributeCompatibilityRule import org.gradle.api.attributes.CompatibilityCheckDetails -import org.gradle.api.internal.artifacts.DefaultImmutableModuleIdentifierFactory import org.gradle.api.internal.artifacts.DefaultModuleIdentifier import org.gradle.api.internal.artifacts.dependencies.DefaultMutableVersionConstraint import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions @@ -351,24 +350,24 @@ Configuration 'bar': } def "excludes nothing when no exclude rules provided"() { - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() def dep = new LocalComponentDependencyMetadata(componentId, Stub(ComponentSelector), "from", null, ImmutableAttributes.EMPTY, "to", [] as List, [], false, false, true, false, null) expect: def exclusions = moduleExclusions.excludeAny(copyOf(dep.excludes)) - exclusions == ModuleExclusions.excludeNone() + exclusions == moduleExclusions.nothing() exclusions.is(moduleExclusions.excludeAny(copyOf(dep.excludes))) } def "applies exclude rules when traversing the from configuration"() { def exclude1 = new DefaultExclude(DefaultModuleIdentifier.newId("group1", "*")) def exclude2 = new DefaultExclude(DefaultModuleIdentifier.newId("group2", "*")) - def moduleExclusions = new ModuleExclusions(new DefaultImmutableModuleIdentifierFactory()) + def moduleExclusions = new ModuleExclusions() def dep = new LocalComponentDependencyMetadata(componentId, Stub(ComponentSelector), "from", null, ImmutableAttributes.EMPTY, "to", [] as List, [exclude1, exclude2], false, false, true, false, null) expect: def exclusions = moduleExclusions.excludeAny(copyOf(dep.excludes)) - exclusions == moduleExclusions.excludeAny(exclude1, exclude2) + exclusions == moduleExclusions.excludeAny(ImmutableList.of(exclude1, exclude2)) exclusions.is(moduleExclusions.excludeAny(copyOf(dep.excludes))) } diff --git a/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java b/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java index 001af7d81153..3783fa6cde97 100644 --- a/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java +++ b/subprojects/platform-base/src/main/java/org/gradle/api/internal/resolve/LocalLibraryDependencyResolver.java @@ -26,7 +26,7 @@ import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelector; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ResolvableArtifact; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.component.ArtifactType; @@ -206,7 +206,7 @@ private boolean isLibrary(ComponentIdentifier identifier) { @Nullable @Override - public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { ComponentIdentifier componentId = component.getId(); if (isLibrary(componentId)) { return new MetadataSourcedComponentArtifacts().getArtifactsFor(component, configuration, this, new ConcurrentHashMap(), artifactTypeRegistry, exclusions, overriddenAttributes); diff --git a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/internal/resolve/JvmLocalLibraryDependencyResolverTest.groovy b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/internal/resolve/JvmLocalLibraryDependencyResolverTest.groovy index af3bf172c1c8..c022ff26b397 100644 --- a/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/internal/resolve/JvmLocalLibraryDependencyResolverTest.groovy +++ b/subprojects/platform-jvm/src/test/groovy/org/gradle/jvm/internal/resolve/JvmLocalLibraryDependencyResolverTest.groovy @@ -22,6 +22,7 @@ import org.gradle.api.artifacts.component.LibraryBinaryIdentifier import org.gradle.api.artifacts.component.LibraryComponentSelector import org.gradle.api.artifacts.component.ModuleComponentIdentifier import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusions +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry import org.gradle.api.internal.attributes.ImmutableAttributes import org.gradle.api.internal.component.ArtifactType @@ -68,6 +69,8 @@ import static org.gradle.util.WrapUtil.toDomainObjectSet class JvmLocalLibraryDependencyResolverTest extends Specification { + public static final ExcludeSpec NOTHING = new ModuleExclusions().nothing() + Map projects ProjectRegistry projectRegistry ProjectModelResolver projectModelResolver @@ -210,7 +213,7 @@ class JvmLocalLibraryDependencyResolverTest extends Specification { result.hasResult() when: - def artifacts = resolver.resolveArtifacts(component, configuration, Stub(ArtifactTypeRegistry), ModuleExclusions.excludeNone(), ImmutableAttributes.EMPTY) + def artifacts = resolver.resolveArtifacts(component, configuration, Stub(ArtifactTypeRegistry), NOTHING, ImmutableAttributes.EMPTY) then: artifacts != null @@ -230,7 +233,7 @@ class JvmLocalLibraryDependencyResolverTest extends Specification { !result.hasResult() when: - def artifacts = resolver.resolveArtifacts(component, configuration, Stub(ArtifactTypeRegistry), ModuleExclusions.excludeNone(), ImmutableAttributes.EMPTY) + def artifacts = resolver.resolveArtifacts(component, configuration, Stub(ArtifactTypeRegistry), NOTHING, ImmutableAttributes.EMPTY) then: artifacts == null diff --git a/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java b/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java index b1c8f446b86e..ac0e6979e78f 100644 --- a/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java +++ b/subprojects/version-control/src/main/java/org/gradle/vcs/internal/resolver/VcsDependencyResolver.java @@ -25,7 +25,7 @@ import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionSelector; import org.gradle.api.internal.artifacts.ivyservice.projectmodule.LocalComponentRegistry; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; -import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.ModuleExclusion; +import org.gradle.api.internal.artifacts.ivyservice.resolveengine.excludes.specs.ExcludeSpec; import org.gradle.api.internal.artifacts.type.ArtifactTypeRegistry; import org.gradle.api.internal.attributes.ImmutableAttributes; import org.gradle.api.internal.component.ArtifactType; @@ -159,7 +159,7 @@ public OriginArtifactSelector getArtifactSelector() { @Nullable @Override - public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ModuleExclusion exclusions, ImmutableAttributes overriddenAttributes) { + public ArtifactSet resolveArtifacts(ComponentResolveMetadata component, ConfigurationMetadata configuration, ArtifactTypeRegistry artifactTypeRegistry, ExcludeSpec exclusions, ImmutableAttributes overriddenAttributes) { return null; }