From 5d29bdae7c79eb0de53126ba3fa681d59d50e33a Mon Sep 17 00:00:00 2001 From: Andrzej Jarmoniuk Date: Sun, 12 Mar 2023 07:37:53 +0100 Subject: [PATCH 1/2] [MENFORCER-466] Apply the all levels (so, including direct) scope and optional selectors on RequireUpperBoundDeps --- .../dependency/DependencyConvergence.java | 35 ++++--------- .../dependency/RequireUpperBoundDeps.java | 11 +++- .../AllLevelsOptionalDependencySelector.java | 40 +++++++++++++++ .../AllLevelsScopeDependencySelector.java | 51 +++++++++++++++++++ .../dependency/RequireUpperBoundDepsTest.java | 3 +- .../menforcer466_requires_api150-1.0.pom | 34 +++++++++++++ .../menforcer466_requires_utils30-1.0.pom | 34 +++++++++++++ .../pom.xml | 50 ++++++++++++------ .../invoker.properties | 18 ------- 9 files changed, 215 insertions(+), 61 deletions(-) create mode 100644 enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsOptionalDependencySelector.java create mode 100644 enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java create mode 100644 maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_api150-1.0.pom create mode 100644 maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_utils30-1.0.pom rename maven-enforcer-plugin/src/it/projects/{require-upper-bound-deps-provided => require-upper-bound-dependencies-scope-optional}/pom.xml (71%) delete mode 100644 maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/invoker.properties diff --git a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/DependencyConvergence.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/DependencyConvergence.java index b235b66a..21cac73e 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/DependencyConvergence.java +++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/DependencyConvergence.java @@ -22,21 +22,21 @@ import javax.inject.Named; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; -import org.apache.maven.artifact.Artifact; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; import org.apache.maven.enforcer.rules.AbstractStandardEnforcerRule; +import org.apache.maven.enforcer.rules.dependency.selector.AllLevelsOptionalDependencySelector; +import org.apache.maven.enforcer.rules.dependency.selector.AllLevelsScopeDependencySelector; import org.apache.maven.enforcer.rules.utils.ArtifactUtils; -import org.eclipse.aether.collection.DependencyCollectionContext; -import org.eclipse.aether.collection.DependencySelector; -import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector; +import static org.apache.maven.artifact.Artifact.SCOPE_PROVIDED; +import static org.apache.maven.artifact.Artifact.SCOPE_TEST; + /** * @author Rex Hoffman */ @@ -49,8 +49,6 @@ public final class DependencyConvergence extends AbstractStandardEnforcerRule { private List excludes; - private List scopes = Arrays.asList(Artifact.SCOPE_COMPILE, Artifact.SCOPE_RUNTIME, Artifact.SCOPE_SYSTEM); - private DependencyVersionMap dependencyVersionMap; private final ResolveUtil resolveUtil; @@ -64,23 +62,8 @@ public DependencyConvergence(ResolveUtil resolveUtil) { public void execute() throws EnforcerRuleException { DependencyNode node = resolveUtil.resolveTransitiveDependenciesVerbose( - // TODO: use a modified version of ExclusionDependencySelector to process excludes and includes - new DependencySelector() { - @Override - public boolean selectDependency(Dependency dependency) { - // regular OptionalDependencySelector only discriminates optional dependencies at level 2+ - return !dependency.isOptional() - // regular scope selectors only discard transitive dependencies - // and always allow direct dependencies - && scopes.contains(dependency.getScope()); - } - - @Override - public DependencySelector deriveChildSelector(DependencyCollectionContext context) { - return this; - } - }, - // process dependency exclusions + new AllLevelsOptionalDependencySelector(), + new AllLevelsScopeDependencySelector(SCOPE_TEST, SCOPE_PROVIDED), new ExclusionDependencySelector()); dependencyVersionMap = new DependencyVersionMap().setUniqueVersions(uniqueVersions); node.accept(dependencyVersionMap); @@ -142,7 +125,7 @@ private String buildConvergenceErrorMsg(List nodeList) { @Override public String toString() { return String.format( - "DependencyConvergence[includes=%s, excludes=%s, uniqueVersions=%b, scopes=%s]", - includes, excludes, uniqueVersions, String.join(",", scopes)); + "DependencyConvergence[includes=%s, excludes=%s, uniqueVersions=%b]", + includes, excludes, uniqueVersions); } } diff --git a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDeps.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDeps.java index 0a26be3b..50e054b5 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDeps.java +++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDeps.java @@ -34,12 +34,18 @@ import org.apache.maven.artifact.versioning.OverConstrainedVersionException; import org.apache.maven.enforcer.rule.api.EnforcerRuleException; import org.apache.maven.enforcer.rules.AbstractStandardEnforcerRule; +import org.apache.maven.enforcer.rules.dependency.selector.AllLevelsOptionalDependencySelector; +import org.apache.maven.enforcer.rules.dependency.selector.AllLevelsScopeDependencySelector; import org.apache.maven.enforcer.rules.utils.ArtifactUtils; import org.apache.maven.enforcer.rules.utils.ParentNodeProvider; import org.apache.maven.enforcer.rules.utils.ParentsVisitor; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.graph.DependencyVisitor; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.selector.ExclusionDependencySelector; + +import static org.apache.maven.artifact.Artifact.SCOPE_PROVIDED; +import static org.apache.maven.artifact.Artifact.SCOPE_TEST; /** * Rule to enforce that the resolved dependency is also the most recent one of all transitive dependencies. @@ -97,7 +103,10 @@ public void setIncludes(List includes) { @Override public void execute() throws EnforcerRuleException { - DependencyNode node = resolveUtil.resolveTransitiveDependenciesVerbose(); + DependencyNode node = resolveUtil.resolveTransitiveDependenciesVerbose( + new AllLevelsOptionalDependencySelector(), + new AllLevelsScopeDependencySelector(SCOPE_TEST, SCOPE_PROVIDED), + new ExclusionDependencySelector()); upperBoundDepsVisitor = new RequireUpperBoundDepsVisitor() .setUniqueVersions(uniqueVersions) .setIncludes(includes); diff --git a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsOptionalDependencySelector.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsOptionalDependencySelector.java new file mode 100644 index 00000000..4c9e2ad6 --- /dev/null +++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsOptionalDependencySelector.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.maven.enforcer.rules.dependency.selector; + +import org.eclipse.aether.collection.DependencyCollectionContext; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.graph.Dependency; + +/** + * Dependency selector discarding {@code optional} dependencies on all levels. + * The standard {@link org.eclipse.aether.util.graph.selector.OptionalDependencySelector} + * does not discard direct dependencies. + */ +public class AllLevelsOptionalDependencySelector implements DependencySelector { + @Override + public boolean selectDependency(Dependency dependency) { + return !dependency.isOptional(); + } + + @Override + public DependencySelector deriveChildSelector(DependencyCollectionContext context) { + return this; + } +} diff --git a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java new file mode 100644 index 00000000..7aa81ffe --- /dev/null +++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.maven.enforcer.rules.dependency.selector; + +import java.util.Arrays; + +import org.eclipse.aether.collection.DependencyCollectionContext; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.graph.Dependency; + +/** + * Dependency selector discarding dependencies with the given scope on all levels. + * The standard {@link org.eclipse.aether.util.graph.selector.ScopeDependencySelector} + * does not discard direct dependencies. + */ +public class AllLevelsScopeDependencySelector implements DependencySelector { + private final String[] excluded; + + public AllLevelsScopeDependencySelector(String... excluded) { + this.excluded = excluded; + } + + @Override + public boolean selectDependency(Dependency dependency) { + return Arrays.stream(excluded) + .map(scope -> !scope.equals(dependency.getScope())) + .reduce(Boolean::logicalAnd) + .orElse(true); + } + + @Override + public DependencySelector deriveChildSelector(DependencyCollectionContext context) { + return this; + } +} diff --git a/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDepsTest.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDepsTest.java index 0cdd221a..ac66f0d0 100644 --- a/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDepsTest.java +++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/dependency/RequireUpperBoundDepsTest.java @@ -27,6 +27,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -41,7 +42,7 @@ class RequireUpperBoundDepsTest { @Test void testRule() throws Exception { - when(resolveUtil.resolveTransitiveDependenciesVerbose()) + when(resolveUtil.resolveTransitiveDependenciesVerbose(any(), any(), any())) .thenReturn(new DependencyNodeBuilder() .withType(DependencyNodeBuilder.Type.POM) .withChildNode(new DependencyNodeBuilder() diff --git a/maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_api150-1.0.pom b/maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_api150-1.0.pom new file mode 100644 index 00000000..5df5742c --- /dev/null +++ b/maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_api150-1.0.pom @@ -0,0 +1,34 @@ + + + + 4.0.0 + org.apache.maven.plugins.enforcer.its + menforcer466_requires_api150 + 1.0 + + + + org.apache.maven.plugins.enforcer.its + menforcer128_api + 1.5.0 + + + diff --git a/maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_utils30-1.0.pom b/maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_utils30-1.0.pom new file mode 100644 index 00000000..26af710c --- /dev/null +++ b/maven-enforcer-plugin/src/it/mrm/repository/menforcer466_requires_utils30-1.0.pom @@ -0,0 +1,34 @@ + + + + 4.0.0 + org.apache.maven.plugins.enforcer.its + menforcer466_requires_utils30 + 1.0 + + + + org.apache.maven.plugins.enforcer.its + menforcer138_utils + 3.0 + + + diff --git a/maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/pom.xml b/maven-enforcer-plugin/src/it/projects/require-upper-bound-dependencies-scope-optional/pom.xml similarity index 71% rename from maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/pom.xml rename to maven-enforcer-plugin/src/it/projects/require-upper-bound-dependencies-scope-optional/pom.xml index 2adf2026..b62f04ab 100644 --- a/maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/pom.xml +++ b/maven-enforcer-plugin/src/it/projects/require-upper-bound-dependencies-scope-optional/pom.xml @@ -20,18 +20,10 @@ --> 4.0.0 - org.apache.maven.plugins.enforcer.its - menforcer128 + org.apache.maven.enforcer.its + require-upper-bound-dependencies-provided 1.0-SNAPSHOT - jar - - - org.apache.maven.plugins.enforcer.its - menforcer128_api - 1.4.0 - provided - - + @@ -41,17 +33,45 @@ enforce + + enforce + - + - - enforce - + + + + org.apache.maven.plugins.enforcer.its + menforcer128_api + 1.4.0 + provided + + + + org.apache.maven.plugins.enforcer.its + menforcer138_utils + 3.0 + true + + + + org.apache.maven.plugins.enforcer.its + menforcer466_requires_api150 + 1.0 + + + + org.apache.maven.plugins.enforcer.its + menforcer466_requires_utils30 + 1.0 + + diff --git a/maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/invoker.properties b/maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/invoker.properties deleted file mode 100644 index 1dcdc656..00000000 --- a/maven-enforcer-plugin/src/it/projects/require-upper-bound-deps-provided/invoker.properties +++ /dev/null @@ -1,18 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -invoker.buildResult = success From 86a701bebe829fca4efa5fb46c49ab1ea49105c1 Mon Sep 17 00:00:00 2001 From: Slawomir Jaranowski Date: Fri, 17 Mar 2023 21:29:33 +0100 Subject: [PATCH 2/2] Simplify implementation of AllLevelsScopeDependencySelector --- .../selector/AllLevelsScopeDependencySelector.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java index 7aa81ffe..7490edf8 100644 --- a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java +++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/dependency/selector/AllLevelsScopeDependencySelector.java @@ -19,6 +19,8 @@ package org.apache.maven.enforcer.rules.dependency.selector; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import org.eclipse.aether.collection.DependencyCollectionContext; import org.eclipse.aether.collection.DependencySelector; @@ -30,18 +32,15 @@ * does not discard direct dependencies. */ public class AllLevelsScopeDependencySelector implements DependencySelector { - private final String[] excluded; + private final Collection excluded; public AllLevelsScopeDependencySelector(String... excluded) { - this.excluded = excluded; + this.excluded = excluded != null ? Arrays.asList(excluded) : Collections.emptyList(); } @Override public boolean selectDependency(Dependency dependency) { - return Arrays.stream(excluded) - .map(scope -> !scope.equals(dependency.getScope())) - .reduce(Boolean::logicalAnd) - .orElse(true); + return !excluded.contains(dependency.getScope()); } @Override