From 88dbb29ee0818314209338cea50d9e745fc94e9c Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Tue, 23 Apr 2019 19:44:07 +0200 Subject: [PATCH 1/2] Use consistent ordering for module exclusions This commit updates the `MergeSet` implementation to extend from linked hashset instead of hashset, so that the order of elements is consistent. In theory, it shouldn't matter, but practice has shown that there must be a bug somewhere else that is at least partially mitigated by using consistent ordering here. In practice what it means is that it is possible to get inconsistent classpath ordering in multi-project builds depending on the order of resolution of projects, when those projects have lots of common exclusions in transitive dependencies. The considtion to reach this bug are unclear despite our efforts to find out, so this commit is really just a workaround at this point. --- .../ivyservice/resolveengine/excludes/ModuleExclusions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 98dfc5251850..a249d30bf7c9 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 @@ -29,7 +29,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -444,7 +444,7 @@ public int hashCode() { } } - private static final class MergeSet extends HashSet { + private static final class MergeSet extends LinkedHashSet { private final BitSet remaining; private int idx; private AbstractModuleExclusion current; From f2093f25776ca6d37a3f7faa93e95c83591e5f78 Mon Sep 17 00:00:00 2001 From: Cedric Champeau Date: Wed, 24 Apr 2019 09:27:58 +0200 Subject: [PATCH 2/2] Clarifying renames The exclude rule merging algorithms are pretty hard to understand due to the mental shift required by weird definitions of "union" and "intersection" which are the exact opposite of what they should be. --- .../excludes/AbstractModuleExclusion.java | 4 +- ...{UnionExclusion.java => AllExclusion.java} | 6 +- ...ionExclusion.java => EitherExclusion.java} | 6 +- .../excludes/ModuleExclusions.java | 44 ++--- .../graph/builder/EdgeState.java | 2 +- .../graph/builder/NodeState.java | 4 +- .../DefaultModuleExclusionTest.groovy | 166 +++++++++--------- 7 files changed, 116 insertions(+), 116 deletions(-) rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/{UnionExclusion.java => AllExclusion.java} (92%) rename subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/{IntersectionExclusion.java => EitherExclusion.java} (93%) 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 index 0339c5a1212f..1a1d54a24440 100644 --- 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 @@ -81,14 +81,14 @@ protected boolean excludesNoModules() { * Possibly unpack a composite spec into it's constituent parts, if those parts are applied as an intersection. * @param specs */ - protected void unpackIntersection(Collection 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 unpackUnion(Collection specs) { + protected void unpackAll(Collection specs) { specs.add(this); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/UnionExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java similarity index 92% rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/UnionExclusion.java rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java index df88c0d07530..9dfc35884906 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/UnionExclusion.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/AllExclusion.java @@ -26,10 +26,10 @@ * 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 UnionExclusion extends AbstractCompositeExclusion { +class AllExclusion extends AbstractCompositeExclusion { private final List filters; - public UnionExclusion(List filters) { + public AllExclusion(List filters) { this.filters = filters; } @@ -41,7 +41,7 @@ Collection getFilters() { * Can unpack into constituents when creating a larger union. */ @Override - protected void unpackUnion(Collection specs) { + protected void unpackAll(Collection specs) { specs.addAll(this.filters); } diff --git a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IntersectionExclusion.java b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java similarity index 93% rename from subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IntersectionExclusion.java rename to subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java index e2ef11886dc3..f8f39dedae10 100644 --- a/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/IntersectionExclusion.java +++ b/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/excludes/EitherExclusion.java @@ -25,13 +25,13 @@ * 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 IntersectionExclusion extends AbstractCompositeExclusion { +class EitherExclusion extends AbstractCompositeExclusion { private final ImmutableModuleExclusionSet excludeSpecs; private final boolean mergeable; private Boolean excludesNoModules; - public IntersectionExclusion(ImmutableModuleExclusionSet specs) { + public EitherExclusion(ImmutableModuleExclusionSet specs) { this.excludeSpecs = specs; boolean canMerge = true; for (AbstractModuleExclusion spec : specs) { @@ -92,7 +92,7 @@ public boolean mayExcludeArtifacts() { * @param specs */ @Override - protected void unpackIntersection(Collection specs) { + protected void unpackEither(Collection specs) { specs.addAll(excludeSpecs); } 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 a249d30bf7c9..fa10c3d46959 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 @@ -59,7 +59,7 @@ public class ModuleExclusions { private final Map mergeCache = Maps.newConcurrentMap(); private final Map, AbstractModuleExclusion> excludeAnyCache = Maps.newConcurrentMap(); - private final Map, IntersectionExclusion> intersectionCache = 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(); @@ -103,7 +103,7 @@ public ModuleExclusion excludeAny(ImmutableList excludes) { for (ExcludeMetadata exclude : excludes) { exclusions.add(forExclude(exclude)); } - exclusion = asIntersection(exclusions.build()); + exclusion = asEither(exclusions.build()); excludeAnyCache.put(excludes, exclusion); return exclusion; } @@ -165,7 +165,7 @@ private GroupNameExcludeSpec groupNameExcludeSpec(String id) { /** * Returns a spec that excludes those modules and artifacts that are excluded by _either_ of the given exclude rules. */ - public ModuleExclusion intersect(ModuleExclusion one, ModuleExclusion two) { + public ModuleExclusion either(ModuleExclusion one, ModuleExclusion two) { if (one == two) { return one; } @@ -179,9 +179,9 @@ public ModuleExclusion intersect(ModuleExclusion one, ModuleExclusion two) { return one; } - if (one instanceof IntersectionExclusion && ((IntersectionExclusion) one).getFilters().contains(two)) { + if (one instanceof EitherExclusion && ((EitherExclusion) one).getFilters().contains(two)) { return one; - } else if (two instanceof IntersectionExclusion && ((IntersectionExclusion) two).getFilters().contains(one)) { + } else if (two instanceof EitherExclusion && ((EitherExclusion) two).getFilters().contains(one)) { return two; } @@ -190,10 +190,10 @@ public ModuleExclusion intersect(ModuleExclusion one, ModuleExclusion two) { List builder = Lists.newArrayListWithExpectedSize(estimateSize(aOne) + estimateSize(aTwo)); - aOne.unpackIntersection(builder); - aTwo.unpackIntersection(builder); + aOne.unpackEither(builder); + aTwo.unpackEither(builder); - return asIntersection(ImmutableSet.copyOf(builder)); + return asEither(ImmutableSet.copyOf(builder)); } private static int estimateSize(AbstractModuleExclusion ex) { @@ -206,7 +206,7 @@ private static int estimateSize(AbstractModuleExclusion ex) { /** * Returns a spec that excludes only those modules and artifacts that are excluded by _both_ of the supplied exclude rules. */ - public ModuleExclusion union(ModuleExclusion one, ModuleExclusion two) { + public ModuleExclusion both(ModuleExclusion one, ModuleExclusion two) { if (one == two) { return one; } @@ -218,15 +218,15 @@ public ModuleExclusion union(ModuleExclusion one, ModuleExclusion two) { } List specs = new ArrayList(); - ((AbstractModuleExclusion) one).unpackUnion(specs); - ((AbstractModuleExclusion) two).unpackUnion(specs); + ((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 = maybeMergeIntoUnion(spec, other); + merged = maybeMergeIntoAll(spec, other); if (merged != null) { specs.remove(j); break; @@ -241,24 +241,24 @@ public ModuleExclusion union(ModuleExclusion one, ModuleExclusion two) { if (specs.size() == 1) { return specs.get(0); } - return new UnionExclusion(specs); + 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 maybeMergeIntoUnion(AbstractModuleExclusion one, AbstractModuleExclusion two) { + private AbstractModuleExclusion maybeMergeIntoAll(AbstractModuleExclusion one, AbstractModuleExclusion two) { if (one.equals(two)) { return one; } - if (one instanceof IntersectionExclusion && two instanceof IntersectionExclusion) { - return maybeMergeIntoUnion((IntersectionExclusion) one, (IntersectionExclusion) two); + if (one instanceof EitherExclusion && two instanceof EitherExclusion) { + return maybeMergeIntoAll((EitherExclusion) one, (EitherExclusion) two); } return null; } - private AbstractModuleExclusion maybeMergeIntoUnion(IntersectionExclusion one, IntersectionExclusion other) { + private AbstractModuleExclusion maybeMergeIntoAll(EitherExclusion one, EitherExclusion other) { if (one.equals(other)) { return one; } @@ -315,17 +315,17 @@ private AbstractModuleExclusion mergeAndCacheResult(MergeOperation merge, Abstra if (merged.isEmpty()) { exclusion = ModuleExclusions.EXCLUDE_NONE; } else { - exclusion = asIntersection(ImmutableSet.copyOf(merged)); + exclusion = asEither(ImmutableSet.copyOf(merged)); } mergeCache.put(merge, exclusion); return exclusion; } - private IntersectionExclusion asIntersection(ImmutableSet excludes) { - IntersectionExclusion cached = intersectionCache.get(excludes); + private EitherExclusion asEither(ImmutableSet excludes) { + EitherExclusion cached = eitherCache.get(excludes); if (cached == null) { - cached = new IntersectionExclusion(new ImmutableModuleExclusionSet(excludes)); - intersectionCache.put(excludes, cached); + cached = new EitherExclusion(new ImmutableModuleExclusionSet(excludes)); + eitherCache.put(excludes, cached); } return cached; } 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 0f55a4a2a9b8..881961218178 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 @@ -232,7 +232,7 @@ public ModuleExclusion getExclusions() { return transitiveExclusions; } ModuleExclusion edgeExclusions = resolveState.getModuleExclusions().excludeAny(ImmutableList.copyOf(excludes)); - return resolveState.getModuleExclusions().intersect(edgeExclusions, transitiveExclusions); + return resolveState.getModuleExclusions().either(edgeExclusions, transitiveExclusions); } public ModuleExclusion getEdgeExclusions() { 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 40b83b37cd8e..b087206e3d6c 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 @@ -469,7 +469,7 @@ private ModuleExclusion excludedByBoth(ModuleExclusion one, ModuleExclusion two) if (two == null) { return one; } - return resolveState.getModuleExclusions().union(one, two); + return resolveState.getModuleExclusions().both(one, two); } private ModuleExclusion excludedByEither(ModuleExclusion one, ModuleExclusion two) { @@ -479,7 +479,7 @@ private ModuleExclusion excludedByEither(ModuleExclusion one, ModuleExclusion tw if (two == null) { return one; } - return resolveState.getModuleExclusions().intersect(one, two); + return resolveState.getModuleExclusions().either(one, two); } private void removeOutgoingEdges() { 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 index ccbf86ce9457..01beda4ce5f0 100644 --- 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 @@ -256,9 +256,9 @@ class DefaultModuleExclusionTest extends Specification { !spec.excludesSameModulesAs(moduleRule) !moduleRule.excludesSameModulesAs(spec) - spec.excludesSameModulesAs(union(spec, otherRule)) - spec.excludesSameModulesAs(union(spec, moduleRule)) - spec.excludesSameModulesAs(intersect(spec, union(otherRule, sameRule))) + spec.excludesSameModulesAs(both(spec, otherRule)) + spec.excludesSameModulesAs(both(spec, moduleRule)) + spec.excludesSameModulesAs(either(spec, both(otherRule, sameRule))) where: rule << [excludeRule('*', '*', '*', 'jar', 'jar'), @@ -355,8 +355,8 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeNone() expect: - union(spec, spec2).is(spec2) - union(spec2, spec).is(spec2) + both(spec, spec2).is(spec2) + both(spec2, spec).is(spec2) } def "union of a spec with itself returns the original spec"() { @@ -366,7 +366,7 @@ class DefaultModuleExclusionTest extends Specification { def spec = excludeAny(rule1, rule2, rule3) expect: - union(spec, spec).is(spec) + both(spec, spec).is(spec) } def "union of two specs with the same exclude rule instances returns one of the original specs"() { @@ -378,7 +378,7 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2, rule3, rule1, rule4) expect: - union(spec, spec2).is(spec) + both(spec, spec2).is(spec) } @NotYetImplemented @@ -391,11 +391,11 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2, rule1, rule4) expect: - union(spec, spec2).is(spec2) - union(spec2, spec).is(spec2) + both(spec, spec2).is(spec2) + both(spec2, spec).is(spec2) } - def "union of two specs with exact matching exclude rules uses the intersection of the exclude rules"() { + 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") @@ -403,7 +403,7 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule1, rule3) expect: - def union = union(spec, spec2) + def union = both(spec, spec2) union == excludeAny(rule1) } @@ -417,13 +417,13 @@ class DefaultModuleExclusionTest extends Specification { def spec = excludeAny(rule1) expect: - def union1 = union(spec, excludeAny(rule2, rule3, rule4)) + def union1 = both(spec, excludeAny(rule2, rule3, rule4)) union1 == excludeAny(rule2, rule3) - def union2 = union(spec, excludeAny(rule5)) + def union2 = both(spec, excludeAny(rule5)) union2 == excludeAny(excludeRule("org", "module3")) - def union3 = union(spec, excludeAny(rule6, rule2)) + def union3 = both(spec, excludeAny(rule6, rule2)) union3 == excludeAny(rule2) } @@ -437,13 +437,13 @@ class DefaultModuleExclusionTest extends Specification { def spec = excludeAny(rule1) expect: - def union1 = union(spec, excludeAny(rule2, rule3, rule4)) + def union1 = both(spec, excludeAny(rule2, rule3, rule4)) union1 == excludeAny(rule2, rule4) - def union2 = union(spec, excludeAny(rule5)) + def union2 = both(spec, excludeAny(rule5)) union2 == excludeAny(excludeRule("org", "module")) - def union3 = union(spec, excludeAny(rule6)) + def union3 = both(spec, excludeAny(rule6)) union3 == excludeNone() } @@ -454,7 +454,7 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2) expect: - def union = union(spec, spec2) + def union = both(spec, spec2) union == excludeNone() } @@ -465,8 +465,8 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2) expect: - union(spec1, spec2) == spec2 - union(spec2, spec1) == spec2 + both(spec1, spec2) == spec2 + both(spec2, spec1) == spec2 } def "union of module spec and artifact spec uses the artifact spec"() { @@ -479,13 +479,13 @@ class DefaultModuleExclusionTest extends Specification { def artifactSpec2 = excludeAny(artifactRule1, artifactRule2) expect: - def union1 = union(artifactSpec1, excludeAny(rule1)) + def union1 = both(artifactSpec1, excludeAny(rule1)) union1 == artifactSpec1 - def union2 = union(artifactSpec1, excludeAny(rule1, rule2, rule3)) + def union2 = both(artifactSpec1, excludeAny(rule1, rule2, rule3)) union2 == artifactSpec1 - def union3 = union(artifactSpec2, excludeAny(rule1, rule2, rule3)) + def union3 = both(artifactSpec2, excludeAny(rule1, rule2, rule3)) union3 == artifactSpec2 } @@ -496,9 +496,9 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2) expect: - def union = union(spec, spec2) + def union = both(spec, spec2) def specs = [] - union.unpackUnion(specs) + union.unpackAll(specs) specs.size() == 2 specs[0] == spec specs[1] == spec2 @@ -513,18 +513,18 @@ class DefaultModuleExclusionTest extends Specification { def spec3 = excludeAny(rule3) expect: - def union = union(union(spec, spec3), spec2) + def union = both(both(spec, spec3), spec2) - union instanceof UnionExclusion + union instanceof AllExclusion union.filters.size() == 2 union.filters.any { - it instanceof IntersectionExclusion && it.excludeSpecs == spec.excludeSpecs + it instanceof EitherExclusion && it.excludeSpecs == spec.excludeSpecs } union.filters.contains(spec3) } // Regression test for GRADLE-3275, also exercises GRADLE-3434 - def "intersection propagates through child union rules"() { + def "either propagates through child union rules"() { def rule1 = excludeRule("org", "module") def rule2 = regexpExcludeRule("org", "module2") def rule3 = regexpExcludeRule("org", "module3") @@ -532,28 +532,28 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule1, rule2) def spec3 = excludeAny(rule3) - def excludeBacked1 = intersect(spec, spec2); // module + module2 - def union1 = union(spec2, spec3); // module, module2, module3 - def excludeBacked2 = intersect(spec2, union1); // module, module2 - def finalUnion = union(spec3, excludeBacked2); // module + 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.unpackUnion(specs) + union1.unpackAll(specs) specs == [spec2, spec3]; // Verify test is exercising the function it's supposed to. - excludeBacked1 instanceof IntersectionExclusion - excludeBacked2 instanceof IntersectionExclusion + excludeBacked1 instanceof EitherExclusion + excludeBacked2 instanceof EitherExclusion - union1 instanceof UnionExclusion - finalUnion instanceof UnionExclusion + union1 instanceof AllExclusion + finalUnion instanceof AllExclusion !spec2.excludeModule(moduleId("org", "module4")) - // Verify that this function passes the intersection operation through to union2's rules. + // 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")) @@ -566,7 +566,7 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule1) expect: - def union1 = union(spec, spec2) + def union1 = both(spec, spec2) spec.excludeModule(moduleId("org", "module")) union1.excludeModule(moduleId("org", "module")) @@ -583,7 +583,7 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(excludeB) when: - def union1 = union(spec, spec2) + def union1 = both(spec, spec2) then: union1.excludeArtifact(moduleId, artifactName("a", "zip", "zip")) @@ -602,35 +602,35 @@ class DefaultModuleExclusionTest extends Specification { def spec3 = excludeAny(rule3) expect: - union(spec1, spec2).excludesSameModulesAs(union(spec2, spec1)) + both(spec1, spec2).excludesSameModulesAs(both(spec2, spec1)) - !union(spec1, spec2).excludesSameModulesAs(spec2) - !union(spec1, spec2).excludesSameModulesAs(spec1) - !union(spec1, spec2).excludesSameModulesAs(union(spec1, spec3)) + !both(spec1, spec2).excludesSameModulesAs(spec2) + !both(spec1, spec2).excludesSameModulesAs(spec1) + !both(spec1, spec2).excludesSameModulesAs(both(spec1, spec3)) } - def "intersection with empty spec is original spec"() { + 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: - intersect(spec, spec2).is(spec) - intersect(spec2, spec).is(spec) + either(spec, spec2).is(spec) + either(spec2, spec).is(spec) } - def "intersection of a spec with itself returns the original 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: - intersect(spec, spec).is(spec) + either(spec, spec).is(spec) } - def "intersection of two specs with the same exclude rule instances returns one of the original specs"() { + 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", "*") @@ -639,10 +639,10 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2, rule3, rule1, rule4) expect: - intersect(spec, spec2).is(spec) + either(spec, spec2).is(spec) } - def "intersection of two specs where one spec contains a superset of the rules of the other returns the spec containing the superset"() { + 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", "*") @@ -651,31 +651,31 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(rule2, rule1, rule4) expect: - intersect(spec, spec2).is(spec) - intersect(spec2, spec).is(spec) + either(spec, spec2).is(spec) + either(spec2, spec).is(spec) } - def "intersection does not accept module that is not accepted by any merged exclude rules"() { + 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 intersection = intersect(spec, spec2) + def either = either(spec, spec2) spec.excludeModule(moduleId("org", "module")) - intersection.excludeModule(moduleId("org", "module")) + either.excludeModule(moduleId("org", "module")) spec.excludeModule(moduleId("org", "module2")) - intersection.excludeModule(moduleId("org", "module2")) + either.excludeModule(moduleId("org", "module2")) !spec.excludeModule(moduleId("org", "module3")) !spec2.excludeModule(moduleId("org", "module3")) - !intersection.excludeModule(moduleId("org", "module3")) + !either.excludeModule(moduleId("org", "module3")) } - def "intersection accepts artifact that is accepted by every merged exclude rule"() { + 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") @@ -683,41 +683,41 @@ class DefaultModuleExclusionTest extends Specification { def spec2 = excludeAny(excludeA) expect: - def intersection = intersect(spec, spec2) + def either = either(spec, spec2) - intersection.excludeArtifact(moduleId, artifactName("a", "zip", "zip")) - intersection.excludeArtifact(moduleId, artifactName("b", "zip", "zip")) - !intersection.excludeArtifact(moduleId, artifactName("c", "zip", "zip")) + either.excludeArtifact(moduleId, artifactName("a", "zip", "zip")) + either.excludeArtifact(moduleId, artifactName("b", "zip", "zip")) + !either.excludeArtifact(moduleId, artifactName("c", "zip", "zip")) - intersection.mayExcludeArtifacts() + either.mayExcludeArtifacts() } - def "intersection of two specs with exclude rules is the union of the exclude rules"() { + 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 intersection = intersect(spec, spec2) - intersection == excludeAny(rule1, rule2) + def either = either(spec, spec2) + either == excludeAny(rule1, rule2) } - def "intersections accepts same modules when original specs accept same modules"() { + 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 = union(excludeAny(rule1), excludeAny(rule2)) - def spec2 = union(excludeAny(rule2), excludeAny(rule1)) + def spec1 = both(excludeAny(rule1), excludeAny(rule2)) + def spec2 = both(excludeAny(rule2), excludeAny(rule1)) def spec3 = excludeAny(rule3) assert spec1.excludesSameModulesAs(spec2) expect: - intersect(spec1, spec2).excludesSameModulesAs(intersect(spec2, spec1)) + either(spec1, spec2).excludesSameModulesAs(either(spec2, spec1)) - !intersect(spec1, spec2).excludesSameModulesAs(spec1) - !intersect(spec1, spec2).excludesSameModulesAs(spec2) - !intersect(spec1, spec2).excludesSameModulesAs(intersect(spec1, spec3)) + !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"() { @@ -751,19 +751,19 @@ class DefaultModuleExclusionTest extends Specification { 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 = union(simpleExclude, regexpExclude) - def intersection = intersect(unmergedUnion, simpleExclude) + def unmergedUnion = both(simpleExclude, regexpExclude) + def either = either(unmergedUnion, simpleExclude) expect: - union(intersection, simpleExclude) + both(either, simpleExclude) } - ModuleExclusion union(ModuleExclusion spec, ModuleExclusion otherRule) { - moduleExclusions.union(spec, otherRule) + ModuleExclusion both(ModuleExclusion spec, ModuleExclusion otherRule) { + moduleExclusions.both(spec, otherRule) } - ModuleExclusion intersect(ModuleExclusion spec, ModuleExclusion otherRule) { - moduleExclusions.intersect(spec, otherRule) + ModuleExclusion either(ModuleExclusion spec, ModuleExclusion otherRule) { + moduleExclusions.either(spec, otherRule) } ModuleExclusion excludeAny(Exclude... excludes) {