You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2026/10/18 17:31:12 UTC
(maven-dependency-plugin) branch master updated (19479744 -> eea27057)
This is an automated email from the ASF dual-hosted git repository.
slachiewicz pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git
from 19479744 [MDEP-629] Apply unpack includes and excludes before the marker lookup
new 5a4dcf54 [MDEP-886] Add user properties and a scope segment to the analyze ignore options
new eea27057 [MDEP-807] Warn about ignore patterns with more than five segments
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../invoker.properties | 0
.../pom.xml | 42 ++++---
.../invoker.properties | 6 +-
.../pom.xml | 24 ++--
.../src/main/java/Main.java} | 12 +-
.../src/test/java/MainTest.java} | 11 +-
.../invoker.properties | 0
.../pom.xml | 18 ++-
.../src/main/java/Main.java | 0
.../verify.groovy | 14 ++-
.../dependency/analyze/AbstractAnalyzeMojo.java | 66 ++++-------
.../plugins/dependency/analyze/AnalyzeDepMgt.java | 30 +++++
.../dependency/analyze/ArtifactPatternMatcher.java | 132 +++++++++++++++++++++
...ude-dependencies-from-dependency-analysis.md.vm | 4 +
.../analyze/AbstractAnalyzeMojoTest.java | 129 ++++++++++++++++++++
.../analyze/ArtifactPatternMatcherTest.java | 115 ++++++++++++++++++
.../dependency/analyze/TestAnalyzeDepMgt.java | 20 ++++
17 files changed, 526 insertions(+), 97 deletions(-)
copy src/it/projects/{analyze-dep-mgt => analyze-dep-mgt-ignored-dependencies-mdep-596}/invoker.properties (100%)
copy src/it/projects/{analyze-exclusions-managed-dependencies => analyze-dep-mgt-ignored-dependencies-mdep-596}/pom.xml (69%)
copy src/it/projects/{analyze => analyze-ignore-properties-mdep-886}/invoker.properties (70%)
copy src/it/projects/{analyze => analyze-ignore-properties-mdep-886}/pom.xml (79%)
copy src/it/projects/{mdep-1650-scriptable-output-null-classifier/src/main/java/test/App.java => analyze-ignore-properties-mdep-886/src/main/java/Main.java} (90%)
copy src/it/projects/{used-dependencies/module/src/main/java/test/Main.java => analyze-ignore-properties-mdep-886/src/test/java/MainTest.java} (85%)
copy src/it/projects/{analyze => analyze-ignore-scope-pattern-mdep-807}/invoker.properties (100%)
copy src/it/projects/{analyze-excluded-classes => analyze-ignore-scope-pattern-mdep-807}/pom.xml (82%)
copy src/it/projects/{mdep-752-analyze-ignored-packaging-custom/ejb => analyze-ignore-scope-pattern-mdep-807}/src/main/java/Main.java (100%)
copy src/it/projects/{analyze-report => analyze-ignore-scope-pattern-mdep-807}/verify.groovy (57%)
create mode 100644 src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java
create mode 100644 src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java
create mode 100644 src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java
(maven-dependency-plugin) 01/02: [MDEP-886] Add user properties and a scope segment to the analyze ignore options
Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
slachiewicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git
commit 5a4dcf54f2f588592c3af9bc7ae702a08cac2055
Author: Sylwester Lachiewicz <sl...@apache.org>
AuthorDate: Tue Oct 13 23:37:31 2026 +0200
[MDEP-886] Add user properties and a scope segment to the analyze ignore options
Also fixes MDEP-793, MDEP-807 and MDEP-596.
The ignore lists of analyze, analyze-only and analyze-dep-mgt accept an
optional fifth [scope] segment. The shared filter never matches a pattern
with more than four segments, so the scope is matched in
ArtifactPatternMatcher and must not be folded back into that filter.
---
.../invoker.properties | 18 +++
.../pom.xml | 75 ++++++++++++
.../invoker.properties | 22 ++++
.../analyze-ignore-properties-mdep-886/pom.xml | 76 ++++++++++++
.../src/main/java/Main.java | 27 +++++
.../src/test/java/MainTest.java | 29 +++++
.../invoker.properties | 18 +++
.../analyze-ignore-scope-pattern-mdep-807/pom.xml | 68 +++++++++++
.../src/main/java/Main.java | 23 ++++
.../verify.groovy | 31 +++++
.../dependency/analyze/AbstractAnalyzeMojo.java | 61 ++++------
.../plugins/dependency/analyze/AnalyzeDepMgt.java | 28 +++++
.../dependency/analyze/ArtifactPatternMatcher.java | 113 ++++++++++++++++++
...ude-dependencies-from-dependency-analysis.md.vm | 4 +
.../analyze/AbstractAnalyzeMojoTest.java | 129 +++++++++++++++++++++
.../analyze/ArtifactPatternMatcherTest.java | 94 +++++++++++++++
.../dependency/analyze/TestAnalyzeDepMgt.java | 20 ++++
17 files changed, 796 insertions(+), 40 deletions(-)
diff --git a/src/it/projects/analyze-dep-mgt-ignored-dependencies-mdep-596/invoker.properties b/src/it/projects/analyze-dep-mgt-ignored-dependencies-mdep-596/invoker.properties
new file mode 100644
index 00000000..54cf3b7b
--- /dev/null
+++ b/src/it/projects/analyze-dep-mgt-ignored-dependencies-mdep-596/invoker.properties
@@ -0,0 +1,18 @@
+# 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.goals = ${project.groupId}:${project.artifactId}:${project.version}:analyze-dep-mgt
diff --git a/src/it/projects/analyze-dep-mgt-ignored-dependencies-mdep-596/pom.xml b/src/it/projects/analyze-dep-mgt-ignored-dependencies-mdep-596/pom.xml
new file mode 100644
index 00000000..aee23469
--- /dev/null
+++ b/src/it/projects/analyze-dep-mgt-ignored-dependencies-mdep-596/pom.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.its.dependency</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <name>Test</name>
+ <description>
+ Test dependency:analyze-dep-mgt with ignoredDependencies (MDEP-596)
+ </description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.its.dependency</groupId>
+ <artifactId>scope-leaf</artifactId>
+ <version>2.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- a direct dependency overrides the managed version, a mismatch only reported with ignoreDirect=false -->
+ <dependency>
+ <groupId>org.apache.maven.its.dependency</groupId>
+ <artifactId>scope-leaf</artifactId>
+ <version>1.0</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>@project.version@</version>
+ <configuration>
+ <failBuild>true</failBuild>
+ <ignoreDirect>false</ignoreDirect>
+ <ignoredDependencies>
+ <ignoredDependency>org.apache.maven.its.dependency:scope-leaf::*:compile</ignoredDependency>
+ </ignoredDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/src/it/projects/analyze-ignore-properties-mdep-886/invoker.properties b/src/it/projects/analyze-ignore-properties-mdep-886/invoker.properties
new file mode 100644
index 00000000..8dbb8b7b
--- /dev/null
+++ b/src/it/projects/analyze-ignore-properties-mdep-886/invoker.properties
@@ -0,0 +1,22 @@
+# 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.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze \
+ -Dmdep.analyze.ignoredDependencies=org.apache.maven:maven-artifact \
+ -Dmdep.analyze.ignoredUsedUndeclaredDependencies=org.apache.maven:maven-model \
+ -Dmdep.analyze.ignoredUnusedDeclaredDependencies=org.apache.maven:maven-repository-metadata \
+ -Dmdep.analyze.ignoredNonTestScopedDependencies=org.apache.maven:maven-settings
diff --git a/src/it/projects/analyze-ignore-properties-mdep-886/pom.xml b/src/it/projects/analyze-ignore-properties-mdep-886/pom.xml
new file mode 100644
index 00000000..4a34e925
--- /dev/null
+++ b/src/it/projects/analyze-ignore-properties-mdep-886/pom.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.its.dependency</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <name>Test</name>
+ <description>
+ Test dependency:analyze with the mdep.analyze.ignored* user properties (MDEP-886)
+ </description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.9.16</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>3.9.16</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-repository-metadata</artifactId>
+ <version>3.9.16</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings</artifactId>
+ <version>3.9.16</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>@project.version@</version>
+ <configuration>
+ <verbose>true</verbose>
+ <failOnWarning>true</failOnWarning>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/src/it/projects/analyze-ignore-properties-mdep-886/src/main/java/Main.java b/src/it/projects/analyze-ignore-properties-mdep-886/src/main/java/Main.java
new file mode 100644
index 00000000..24194045
--- /dev/null
+++ b/src/it/projects/analyze-ignore-properties-mdep-886/src/main/java/Main.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+import org.apache.maven.Maven;
+import org.apache.maven.model.Model;
+
+public class Main
+{
+ public Maven maven = null;
+ public Model model = null;
+}
diff --git a/src/it/projects/analyze-ignore-properties-mdep-886/src/test/java/MainTest.java b/src/it/projects/analyze-ignore-properties-mdep-886/src/test/java/MainTest.java
new file mode 100644
index 00000000..84acf011
--- /dev/null
+++ b/src/it/projects/analyze-ignore-properties-mdep-886/src/test/java/MainTest.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+import org.apache.maven.settings.Settings;
+
+public class MainTest
+{
+ public Settings settings = null;
+
+ public void testPass()
+ {
+ }
+}
diff --git a/src/it/projects/analyze-ignore-scope-pattern-mdep-807/invoker.properties b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/invoker.properties
new file mode 100644
index 00000000..e6028302
--- /dev/null
+++ b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/invoker.properties
@@ -0,0 +1,18 @@
+# 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.goals = clean ${project.groupId}:${project.artifactId}:${project.version}:analyze
diff --git a/src/it/projects/analyze-ignore-scope-pattern-mdep-807/pom.xml b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/pom.xml
new file mode 100644
index 00000000..94c4ebd2
--- /dev/null
+++ b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.maven.its.dependency</groupId>
+ <artifactId>test</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <name>Test</name>
+ <description>
+ Test the optional scope segment of the ignore patterns (MDEP-807)
+ </description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>3.9.16</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-repository-metadata</artifactId>
+ <version>3.9.16</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>@project.version@</version>
+ <configuration>
+ <ignoredUnusedDeclaredDependencies>
+ <ignoredUnusedDeclaredDependency>org.apache.maven:::*:runtime</ignoredUnusedDeclaredDependency>
+ </ignoredUnusedDeclaredDependencies>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/src/it/projects/analyze-ignore-scope-pattern-mdep-807/src/main/java/Main.java b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/src/main/java/Main.java
new file mode 100644
index 00000000..5e405ff1
--- /dev/null
+++ b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/src/main/java/Main.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+
+public class Main
+{
+}
diff --git a/src/it/projects/analyze-ignore-scope-pattern-mdep-807/verify.groovy b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/verify.groovy
new file mode 100644
index 00000000..702fe7bf
--- /dev/null
+++ b/src/it/projects/analyze-ignore-scope-pattern-mdep-807/verify.groovy
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+File buildLog = new File( basedir, "build.log" );
+String log = buildLog.getText( "UTF-8" );
+
+int unused = log.indexOf( "Unused declared dependencies found:" );
+assert unused >= 0 : "expected an unused declared dependencies warning in build.log";
+String report = log.substring( unused );
+assert report.contains( "org.apache.maven:maven-repository-metadata:jar:3.9.16:compile" ) :
+ "the compile scoped dependency must still be reported";
+assert !report.contains( "org.apache.maven:maven-artifact:jar:3.9.16:runtime" ) :
+ "the runtime scoped dependency matched by the scope segment must be ignored";
+
+return true;
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index 712c3145..f5758f55 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -20,8 +20,6 @@ package org.apache.maven.plugins.dependency.analyze;
import java.io.File;
import java.io.StringWriter;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -31,13 +29,11 @@ import java.util.Objects;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
-import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzerException;
@@ -167,11 +163,11 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
* unused", the "used but undeclared", and the "non-test scoped" list. The filter syntax is:
*
* <pre>
- * [groupId]:[artifactId]:[type]:[version]
+ * [groupId]:[artifactId]:[type]:[version]:[scope]
* </pre>
*
* where each pattern segment is optional and supports full and partial <code>*</code> wildcards. An empty pattern
- * segment is treated as an implicit wildcard. *
+ * segment is treated as an implicit wildcard. The <code>scope</code> segment is available since 3.12.0.
* <p>
* For example, <code>org.apache.*</code> will match all artifacts whose group id starts with
* <code>org.apache.</code>, and <code>:::*-SNAPSHOT</code> will match all snapshot artifacts.
@@ -179,18 +175,18 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
*
* @since 2.10
*/
- @Parameter
+ @Parameter(property = "mdep.analyze.ignoredDependencies")
private String[] ignoredDependencies = new String[0];
/**
* List of dependencies that will be ignored if they are used but undeclared. The filter syntax is:
*
* <pre>
- * [groupId]:[artifactId]:[type]:[version]
+ * [groupId]:[artifactId]:[type]:[version]:[scope]
* </pre>
*
* where each pattern segment is optional and supports full and partial <code>*</code> wildcards. An empty pattern
- * segment is treated as an implicit wildcard. *
+ * segment is treated as an implicit wildcard. The <code>scope</code> segment is available since 3.12.0.
* <p>
* For example, <code>org.apache.*</code> will match all artifacts whose group id starts with
* <code>org.apache.</code>, and <code>:::*-SNAPSHOT</code> will match all snapshot artifacts.
@@ -198,18 +194,18 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
*
* @since 2.10
*/
- @Parameter
+ @Parameter(property = "mdep.analyze.ignoredUsedUndeclaredDependencies")
private String[] ignoredUsedUndeclaredDependencies = new String[0];
/**
* List of dependencies that are ignored if they are declared but unused. The filter syntax is:
*
* <pre>
- * [groupId]:[artifactId]:[type]:[version]
+ * [groupId]:[artifactId]:[type]:[version]:[scope]
* </pre>
*
* where each pattern segment is optional and supports full and partial <code>*</code> wildcards. An empty pattern
- * segment is treated as an implicit wildcard. *
+ * segment is treated as an implicit wildcard. The <code>scope</code> segment is available since 3.12.0.
* <p>
* For example, <code>org.apache.*</code> matches all artifacts whose group id starts with
* <code>org.apache.</code>, and <code>:::*-SNAPSHOT</code> matches all snapshot artifacts.
@@ -220,7 +216,7 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
*
* @since 2.10
*/
- @Parameter
+ @Parameter(property = "mdep.analyze.ignoredUnusedDeclaredDependencies")
private String[] ignoredUnusedDeclaredDependencies = new String[0];
private String[] unconditionallyIgnoredDeclaredDependencies = {"org.slf4j:slf4j-simple::"};
@@ -230,11 +226,11 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
* The filter syntax is:
*
* <pre>
- * [groupId]:[artifactId]:[type]:[version]
+ * [groupId]:[artifactId]:[type]:[version]:[scope]
* </pre>
*
* where each pattern segment is optional and supports full and partial <code>*</code> wildcards. An empty pattern
- * segment is treated as an implicit wildcard. *
+ * segment is treated as an implicit wildcard. The <code>scope</code> segment is available since 3.12.0.
* <p>
* For example, <code>org.apache.*</code> matched all artifacts whose group id starts with
* <code>org.apache.</code>, and <code>:::*-SNAPSHOT</code> will match all snapshot artifacts.
@@ -242,7 +238,7 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
*
* @since 3.3.0
*/
- @Parameter(defaultValue = "org.slf4j:slf4j-simple::")
+ @Parameter(property = "mdep.analyze.ignoredNonTestScopedDependencies", defaultValue = "org.slf4j:slf4j-simple::")
private String[] ignoredNonTestScopedDependencies;
/**
@@ -374,6 +370,14 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
} else {
ignoredNonTestScope.addAll(filterDependencies(nonTestScope, ignoredDependencies));
ignoredNonTestScope.addAll(filterDependencies(nonTestScope, ignoredNonTestScopedDependencies));
+ // an ignored used undeclared dependency is deliberately not declared, so its scope cannot be changed
+ for (Iterator<Artifact> it = nonTestScope.iterator(); it.hasNext(); ) {
+ Artifact artifact = it.next();
+ if (ignoredUsedUndeclared.contains(artifact)) {
+ it.remove();
+ ignoredNonTestScope.add(artifact);
+ }
+ }
}
boolean reported = false;
@@ -559,30 +563,7 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
}
}
- /**
- * Removes artifacts matching any of the given exclude patterns from the source set
- * and returns the removed artifacts. When {@code excludes} is null or empty, no
- * artifacts are removed and an empty set is returned.
- *
- * @param artifacts the source set of artifacts (mutated in place)
- * @param excludes exclude patterns, may be null or empty
- * @return the artifacts that were removed from the source set
- */
private Set<Artifact> filterDependencies(Set<Artifact> artifacts, String[] excludes) {
- if (excludes == null || excludes.length == 0) {
- return Collections.emptySet();
- }
- ArtifactFilter filter = new StrictPatternExcludesArtifactFilter(Arrays.asList(excludes));
- Set<Artifact> result = new LinkedHashSet<>();
-
- for (Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); ) {
- Artifact artifact = it.next();
- if (!filter.include(artifact)) {
- it.remove();
- result.add(artifact);
- }
- }
-
- return result;
+ return ArtifactPatternMatcher.removeMatching(artifacts, excludes);
}
}
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java
index 1df1d74a..ecfa76a3 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java
@@ -74,6 +74,25 @@ public class AnalyzeDepMgt extends AbstractMojo {
@Parameter(property = "mdep.analyze.skip", defaultValue = "false")
private boolean skip;
+ /**
+ * List of dependencies that are skipped by the mismatch and exclusion checks. The filter syntax is:
+ *
+ * <pre>
+ * [groupId]:[artifactId]:[type]:[version]:[scope]
+ * </pre>
+ *
+ * where each pattern segment is optional and supports full and partial <code>*</code> wildcards. An empty pattern
+ * segment is treated as an implicit wildcard.
+ * <p>
+ * For example, <code>org.apache.*</code> will match all artifacts whose group id starts with
+ * <code>org.apache.</code>, and <code>:::*:test</code> will match all test scoped artifacts.
+ * </p>
+ *
+ * @since 3.12.0
+ */
+ @Parameter(property = "mdep.analyze.ignoredDependencies")
+ private String[] ignoredDependencies = new String[0];
+
@Inject
public AnalyzeDepMgt(MavenProject project) {
this.project = project;
@@ -142,6 +161,8 @@ public class AnalyzeDepMgt extends AbstractMojo {
allDependencyArtifacts.removeAll(directDependencies);
}
+ ArtifactPatternMatcher.removeMatching(allDependencyArtifacts, ignoredDependencies);
+
// log exclusion errors
List<Artifact> exclusionErrors = getExclusionErrors(exclusions, allDependencyArtifacts);
for (Artifact exclusion : exclusionErrors) {
@@ -285,6 +306,13 @@ public class AnalyzeDepMgt extends AbstractMojo {
return this.project;
}
+ /**
+ * @param theIgnoredDependencies the patterns of dependencies to skip
+ */
+ public void setIgnoredDependencies(String[] theIgnoredDependencies) {
+ this.ignoredDependencies = theIgnoredDependencies;
+ }
+
/**
* @return the ignoreDirect
*/
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java
new file mode 100644
index 00000000..b64ea90d
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java
@@ -0,0 +1,113 @@
+/*
+ * 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.plugins.dependency.analyze;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
+
+/**
+ * Matches artifacts against ignore patterns of the form
+ * <code>[groupId]:[artifactId]:[type]:[version]:[scope]</code>.
+ * <p>
+ * The first four segments are matched by {@link StrictPatternExcludesArtifactFilter}, which silently never matches a
+ * pattern with more than four segments. The optional fifth segment is therefore split off and matched here, with the
+ * same rules: an empty segment is a wildcard, and <code>*</code> is allowed as a full or partial wildcard.
+ */
+final class ArtifactPatternMatcher {
+
+ private ArtifactPatternMatcher() {}
+
+ /**
+ * Removes artifacts matching any of the given patterns from the source set and returns the removed artifacts.
+ *
+ * @param artifacts the source set of artifacts (mutated in place)
+ * @param patterns patterns, may be null or empty
+ * @return the artifacts that were removed from the source set
+ */
+ static Set<Artifact> removeMatching(Set<Artifact> artifacts, String[] patterns) {
+ if (patterns == null || patterns.length == 0) {
+ return Collections.emptySet();
+ }
+ Set<Artifact> result = new LinkedHashSet<>();
+ for (Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); ) {
+ Artifact artifact = it.next();
+ if (matchesAny(artifact, patterns)) {
+ it.remove();
+ result.add(artifact);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * @param artifact the artifact to test
+ * @param patterns patterns, may be null or empty
+ * @return true if the artifact matches at least one pattern
+ */
+ static boolean matchesAny(Artifact artifact, String[] patterns) {
+ if (patterns == null) {
+ return false;
+ }
+ for (String pattern : patterns) {
+ if (matches(artifact, pattern)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean matches(Artifact artifact, String pattern) {
+ String[] segments = pattern.split(":");
+ if (segments.length <= 4) {
+ return !new StrictPatternExcludesArtifactFilter(Collections.singletonList(pattern)).include(artifact);
+ }
+ if (segments.length > 5) {
+ return false;
+ }
+ String coordinates = String.join(":", Arrays.copyOf(segments, 4));
+ return !new StrictPatternExcludesArtifactFilter(Collections.singletonList(coordinates)).include(artifact)
+ && matchesSegment(artifact.getScope(), segments[4]);
+ }
+
+ private static boolean matchesSegment(String value, String pattern) {
+ if (pattern.isEmpty() || "*".equals(pattern)) {
+ return true;
+ }
+ if (value == null) {
+ return false;
+ }
+ boolean prefix = pattern.endsWith("*");
+ boolean suffix = pattern.startsWith("*");
+ String literal = pattern.substring(suffix ? 1 : 0, pattern.length() - (prefix ? 1 : 0));
+ if (prefix && suffix) {
+ return value.contains(literal);
+ } else if (prefix) {
+ return value.startsWith(literal);
+ } else if (suffix) {
+ return value.endsWith(literal);
+ }
+ return value.equals(literal);
+ }
+}
diff --git a/src/site/markdown/examples/exclude-dependencies-from-dependency-analysis.md.vm b/src/site/markdown/examples/exclude-dependencies-from-dependency-analysis.md.vm
index bab08391..a0dc462d 100644
--- a/src/site/markdown/examples/exclude-dependencies-from-dependency-analysis.md.vm
+++ b/src/site/markdown/examples/exclude-dependencies-from-dependency-analysis.md.vm
@@ -81,6 +81,10 @@ If you encounter other false positives, you can configure the plugin to ignore p
</project>
```
+Each ignore pattern has the form `[groupId]:[artifactId]:[type]:[version]:[scope]`. Every segment is optional and supports full and partial `*` wildcards, and the `scope` segment is available since 3.12.0. For example, `org.acme:::*:runtime` ignores only the runtime scoped dependencies of group `org.acme`. An artifact that matches `ignoredUsedUndeclaredDependencies` is also left out of the "non-test scoped" warnings, because it is deliberately not declared.
+
+The four lists can also be set on the command line, as comma-separated patterns, through the `mdep.analyze.ignoredDependencies`, `mdep.analyze.ignoredUsedUndeclaredDependencies`, `mdep.analyze.ignoredUnusedDeclaredDependencies` and `mdep.analyze.ignoredNonTestScopedDependencies` properties. The `dependency:analyze-dep-mgt` goal accepts the same patterns in its own `ignoredDependencies` parameter and skips the matching artifacts.
+
Note that the `dependency:analyze-only` goal is used in preference to `dependency:analyze` since it doesn't force a further compilation of the project, but uses the compiled classes produced from the earlier `test-compile` phase in the lifecycle.
The project's dependencies will then be automatically analyzed during the `verify` lifecycle phase, which can be executed explicitly as follows:
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java
new file mode 100644
index 00000000..556d58b4
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojoTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.plugins.dependency.analyze;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.DefaultArtifactHandler;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalysis;
+import org.apache.maven.shared.dependency.analyzer.ProjectDependencyAnalyzer;
+import org.codehaus.plexus.PlexusContainer;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.ArgumentCaptor;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class AbstractAnalyzeMojoTest {
+
+ @TempDir
+ File targetDir;
+
+ private final Artifact jodaTime = artifact("joda-time", "joda-time", Artifact.SCOPE_COMPILE);
+
+ private final Artifact commonsIo = artifact("commons-io", "commons-io", Artifact.SCOPE_COMPILE);
+
+ private Log log;
+
+ private AnalyzeOnlyMojo mojo;
+
+ private static Artifact artifact(String groupId, String artifactId, String scope) {
+ return new DefaultArtifact(groupId, artifactId, "1.0", scope, "jar", null, new DefaultArtifactHandler("jar"));
+ }
+
+ private static Set<Artifact> setOf(Artifact... artifacts) {
+ Set<Artifact> set = new LinkedHashSet<>();
+ Collections.addAll(set, artifacts);
+ return set;
+ }
+
+ private static void set(Object target, String field, Object value) throws Exception {
+ Field f = AbstractAnalyzeMojo.class.getDeclaredField(field);
+ f.setAccessible(true);
+ f.set(target, value);
+ }
+
+ /**
+ * Creates a mojo whose analyzer reports the given artifacts as used but undeclared and, at the same time, as
+ * compile scoped but used in tests only.
+ */
+ @BeforeEach
+ void setUp() throws Exception {
+ ProjectDependencyAnalyzer analyzer = mock(ProjectDependencyAnalyzer.class);
+ when(analyzer.analyze(any(MavenProject.class), any()))
+ .thenReturn(new ProjectDependencyAnalysis(
+ Collections.emptySet(), setOf(jodaTime, commonsIo), Collections.emptySet(), setOf(jodaTime)));
+ PlexusContainer container = mock(PlexusContainer.class);
+ when(container.lookup(ProjectDependencyAnalyzer.class, "default")).thenReturn(analyzer);
+
+ MavenProject project = new MavenProject();
+ project.setPackaging("jar");
+ mojo = new AnalyzeOnlyMojo(container, project);
+ log = mock(Log.class);
+ mojo.setLog(log);
+ set(mojo, "analyzer", "default");
+ set(mojo, "outputDirectory", targetDir);
+ set(mojo, "ignoredPackagings", Collections.singletonList("pom"));
+ set(mojo, "ignoredDependencies", new String[0]);
+ set(mojo, "ignoredUnusedDeclaredDependencies", new String[0]);
+ set(mojo, "ignoredUsedUndeclaredDependencies", new String[0]);
+ set(mojo, "ignoredNonTestScopedDependencies", new String[0]);
+ }
+
+ private List<String> warnings() {
+ ArgumentCaptor<CharSequence> captor = ArgumentCaptor.forClass(CharSequence.class);
+ verify(log, atLeast(0)).warn(captor.capture());
+ return captor.getAllValues().stream().map(CharSequence::toString).collect(Collectors.toList());
+ }
+
+ @Test
+ void usedUndeclaredWithoutIgnoreIsAlsoReportedAsNonTestScoped() throws Exception {
+ mojo.execute();
+
+ assertThat(warnings())
+ .contains("Non-test scoped test only dependencies found:")
+ .anyMatch(line ->
+ line.contains("joda-time:joda-time:jar:1.0:compile") && !line.startsWith("Used undeclared"));
+ }
+
+ @Test
+ void ignoredUsedUndeclaredIsNotReportedAsNonTestScoped() throws Exception {
+ set(mojo, "ignoredUsedUndeclaredDependencies", new String[] {"joda-time:joda-time"});
+
+ mojo.execute();
+
+ assertThat(warnings()).doesNotContain("Non-test scoped test only dependencies found:");
+ }
+}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java
new file mode 100644
index 00000000..c89e2a6b
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.plugins.dependency.analyze;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.DefaultArtifactHandler;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ArtifactPatternMatcherTest {
+
+ private static Artifact artifact(String groupId, String artifactId, String version, String scope) {
+ return new DefaultArtifact(groupId, artifactId, version, scope, "jar", null, new DefaultArtifactHandler("jar"));
+ }
+
+ private final Artifact compileDep = artifact("org.acme", "lib", "1.0", Artifact.SCOPE_COMPILE);
+
+ private final Artifact runtimeDep = artifact("org.acme", "lib", "1.0", Artifact.SCOPE_RUNTIME);
+
+ @Test
+ void fourSegmentPatternIgnoresScope() {
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, new String[] {"org.acme:lib:jar:1.0"}))
+ .isTrue();
+ assertThat(ArtifactPatternMatcher.matchesAny(runtimeDep, new String[] {"org.acme:lib:jar:1.0"}))
+ .isTrue();
+ }
+
+ @Test
+ void fifthSegmentSelectsScope() {
+ String[] patterns = {"org.acme:lib:jar:1.0:runtime"};
+ assertThat(ArtifactPatternMatcher.matchesAny(runtimeDep, patterns)).isTrue();
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, patterns)).isFalse();
+ }
+
+ @Test
+ void emptySegmentsAreWildcardsBeforeScope() {
+ String[] patterns = {"::::runtime"};
+ assertThat(ArtifactPatternMatcher.matchesAny(runtimeDep, patterns)).isTrue();
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, patterns)).isFalse();
+ }
+
+ @Test
+ void scopeSupportsWildcards() {
+ assertThat(ArtifactPatternMatcher.matchesAny(runtimeDep, new String[] {"org.acme:::*:run*"}))
+ .isTrue();
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, new String[] {"org.acme:::*:run*"}))
+ .isFalse();
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, new String[] {"org.acme:::*:*"}))
+ .isTrue();
+ }
+
+ @Test
+ void removeMatchingReturnsOnlyRemovedArtifacts() {
+ // Artifact equality ignores the scope, so the runtime artifact needs its own coordinates
+ Artifact runtimeLib = artifact("org.acme", "runtime-lib", "1.0", Artifact.SCOPE_RUNTIME);
+ Artifact other = artifact("org.other", "x", "2.0", Artifact.SCOPE_RUNTIME);
+ Set<Artifact> artifacts = new LinkedHashSet<>();
+ artifacts.add(compileDep);
+ artifacts.add(runtimeLib);
+ artifacts.add(other);
+
+ Set<Artifact> removed = ArtifactPatternMatcher.removeMatching(artifacts, new String[] {"org.acme:::*:runtime"});
+
+ assertThat(removed).containsExactly(runtimeLib);
+ assertThat(artifacts).containsExactly(compileDep, other);
+ }
+
+ @Test
+ void nullAndEmptyPatternsMatchNothing() {
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, null)).isFalse();
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, new String[0])).isFalse();
+ }
+}
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeDepMgt.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeDepMgt.java
index 1858dd1c..79888270 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeDepMgt.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/TestAnalyzeDepMgt.java
@@ -38,6 +38,7 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@@ -215,4 +216,23 @@ class TestAnalyzeDepMgt {
mojo.setIgnoreDirect(true);
mojo.execute();
}
+
+ @Test
+ void ignoredDependenciesAreSkipped() throws Exception {
+ mojo.setIgnoreDirect(false);
+ mojo.setFailBuild(true);
+ mojo.getProject().getModel().setDependencyManagement(depMgt);
+ String ga = exclusion.getGroupId() + ":" + exclusion.getArtifactId();
+ stubFactory.getReleaseArtifact().setScope(Artifact.SCOPE_COMPILE);
+
+ mojo.setIgnoredDependencies(new String[] {ga});
+ mojo.execute();
+
+ // a scope segment that does not match leaves the artifact checked
+ mojo.setIgnoredDependencies(new String[] {ga + "::*:provided"});
+ assertThrows(MojoExecutionException.class, mojo::execute);
+
+ mojo.setIgnoredDependencies(new String[] {ga + "::*:compile"});
+ mojo.execute();
+ }
}
(maven-dependency-plugin) 02/02: [MDEP-807] Warn about ignore patterns with more than five segments
Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
slachiewicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-dependency-plugin.git
commit eea27057976ece4b2e3f955b9ea47f11c1bbca35
Author: Sylwester Lachiewicz <sl...@apache.org>
AuthorDate: Wed Oct 14 00:05:02 2026 +0200
[MDEP-807] Warn about ignore patterns with more than five segments
---
.../dependency/analyze/AbstractAnalyzeMojo.java | 5 +++++
.../plugins/dependency/analyze/AnalyzeDepMgt.java | 2 ++
.../dependency/analyze/ArtifactPatternMatcher.java | 19 +++++++++++++++++++
.../analyze/ArtifactPatternMatcherTest.java | 21 +++++++++++++++++++++
4 files changed, 47 insertions(+)
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
index f5758f55..4a178c41 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AbstractAnalyzeMojo.java
@@ -297,6 +297,11 @@ public abstract class AbstractAnalyzeMojo extends AbstractMojo {
return;
}
+ ArtifactPatternMatcher.warnAboutUnsupportedPatterns(getLog(), ignoredDependencies);
+ ArtifactPatternMatcher.warnAboutUnsupportedPatterns(getLog(), ignoredUsedUndeclaredDependencies);
+ ArtifactPatternMatcher.warnAboutUnsupportedPatterns(getLog(), ignoredUnusedDeclaredDependencies);
+ ArtifactPatternMatcher.warnAboutUnsupportedPatterns(getLog(), ignoredNonTestScopedDependencies);
+
boolean warning = checkDependencies();
if (warning && failOnWarning) {
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java
index ecfa76a3..0f4540bf 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/AnalyzeDepMgt.java
@@ -110,6 +110,8 @@ public class AnalyzeDepMgt extends AbstractMojo {
return;
}
+ ArtifactPatternMatcher.warnAboutUnsupportedPatterns(getLog(), ignoredDependencies);
+
boolean result = checkDependencyManagement();
if (result) {
if (this.failBuild) {
diff --git a/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java b/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java
index b64ea90d..51643303 100644
--- a/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java
+++ b/src/main/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcher.java
@@ -25,6 +25,7 @@ import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.logging.Log;
import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
/**
@@ -78,6 +79,24 @@ final class ArtifactPatternMatcher {
return false;
}
+ /**
+ * Logs one warning for every pattern with more than five segments, because such a pattern never matches.
+ *
+ * @param log the log to warn on
+ * @param patterns patterns, may be null
+ */
+ static void warnAboutUnsupportedPatterns(Log log, String[] patterns) {
+ if (patterns == null) {
+ return;
+ }
+ for (String pattern : patterns) {
+ if (pattern.split(":").length > 5) {
+ log.warn("Ignoring dependency pattern '" + pattern + "' because it has more than five segments and"
+ + " can never match. The supported form is [groupId]:[artifactId]:[type]:[version]:[scope]");
+ }
+ }
+ }
+
private static boolean matches(Artifact artifact, String pattern) {
String[] segments = pattern.split(":");
if (segments.length <= 4) {
diff --git a/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java b/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java
index c89e2a6b..bd138cb7 100644
--- a/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java
+++ b/src/test/java/org/apache/maven/plugins/dependency/analyze/ArtifactPatternMatcherTest.java
@@ -24,9 +24,14 @@ import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
+import org.apache.maven.plugin.logging.Log;
import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
class ArtifactPatternMatcherTest {
@@ -91,4 +96,20 @@ class ArtifactPatternMatcherTest {
assertThat(ArtifactPatternMatcher.matchesAny(compileDep, null)).isFalse();
assertThat(ArtifactPatternMatcher.matchesAny(compileDep, new String[0])).isFalse();
}
+
+ @Test
+ void warnsOncePerPatternWithMoreThanFiveSegments() {
+ Log log = mock(Log.class);
+
+ ArtifactPatternMatcher.warnAboutUnsupportedPatterns(
+ log, new String[] {"org.acme:lib:jar:1.0:runtime:extra", "org.acme:lib:jar:1.0:runtime", "org.acme"});
+
+ ArgumentCaptor<CharSequence> message = ArgumentCaptor.forClass(CharSequence.class);
+ verify(log, times(1)).warn(message.capture());
+ assertThat(message.getValue().toString())
+ .contains("org.acme:lib:jar:1.0:runtime:extra")
+ .contains("[groupId]:[artifactId]:[type]:[version]:[scope]");
+ assertThat(ArtifactPatternMatcher.matchesAny(compileDep, new String[] {"org.acme:lib:jar:1.0:compile:extra"}))
+ .isFalse();
+ }
}