This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch maven-4.0.x
in repository https://gitbox.apache.org/repos/asf/maven.git


The following commit(s) were added to refs/heads/maven-4.0.x by this push:
     new f1a8e5a0b5 [maven-4.0.x] Port the bug fixes identified when using that 
class in Maven clean and compiler plugin (#10935) (#10936)
f1a8e5a0b5 is described below

commit f1a8e5a0b53d406c6f6ef172cebbfdcce8a2cc4b
Author: Guillaume Nodet <gno...@gmail.com>
AuthorDate: Thu Jul 24 11:53:22 2025 +0200

    [maven-4.0.x] Port the bug fixes identified when using that class in Maven 
clean and compiler plugin (#10935) (#10936)
    
    * Port the bug fixes identified when using that class in Maven clean and 
compiler plugin (#10935)
    
    Co-authored-by: Martin Desruisseaux <martin.desruisse...@geomatys.com>
    (cherry picked from commit 012ea25636738b4b3661dc1b13af5d2fa65aa5a4)
    
    * Fixes
    
    ---------
    
    Co-authored-by: Martin Desruisseaux <martin.desruisse...@geomatys.com>
---
 .../java/org/apache/maven/impl/PathSelector.java   | 66 +++++++++++++++++-----
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git 
a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java 
b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java
index 490739c935..348d47887b 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java
@@ -59,9 +59,6 @@
  * If above changes are not desired, put an explicit {@code "glob:"} prefix 
before the pattern.
  * Note that putting such a prefix is recommended anyway for better 
performances.
  *
- * @author Benjamin Bentmann
- * @author Martin Desruisseaux
- *
  * @see java.nio.file.FileSystem#getPathMatcher(String)
  */
 public class PathSelector implements PathMatcher {
@@ -171,6 +168,7 @@ public class PathSelector implements PathMatcher {
     /**
      * String representations of the normalized include filters.
      * Each pattern shall be prefixed by its syntax, which is {@value 
#DEFAULT_SYNTAX} by default.
+     * An empty array means to include all files.
      *
      * @see #toString()
      */
@@ -178,7 +176,8 @@ public class PathSelector implements PathMatcher {
 
     /**
      * String representations of the normalized exclude filters.
-     * Each pattern shall be prefixed by its syntax, which is {@value 
#DEFAULT_SYNTAX} by default.
+     * Each pattern shall be prefixed by its syntax. If no syntax is specified,
+     * the default is a Maven 3 syntax similar, but not identical, to {@value 
#DEFAULT_SYNTAX}.
      * This array may be longer or shorter than the user-supplied excludes, 
depending on whether
      * default excludes have been added and whether some unnecessary excludes 
have been omitted.
      *
@@ -188,6 +187,7 @@ public class PathSelector implements PathMatcher {
 
     /**
      * The matcher for includes. The length of this array is equal to {@link 
#includePatterns} array length.
+     * An empty array means to include all files.
      */
     private final PathMatcher[] includes;
 
@@ -200,6 +200,7 @@ public class PathSelector implements PathMatcher {
      * The matcher for all directories to include. This array includes the 
parents of all those directories,
      * because they need to be accepted before we can walk to the 
sub-directories.
      * This is an optimization for skipping whole directories when possible.
+     * An empty array means to include all directories.
      */
     private final PathMatcher[] dirIncludes;
 
@@ -215,6 +216,13 @@ public class PathSelector implements PathMatcher {
      */
     private final Path baseDirectory;
 
+    /**
+     * Whether paths must be relativized before being given to a matcher. If 
{@code true}, then every paths
+     * will be made relative to {@link #baseDirectory} for allowing patterns 
like {@code "foo/bar/*.java"}
+     * to work. As a slight optimization, we can skip this step if all 
patterns start with {@code "**"}.
+     */
+    private final boolean needRelativize;
+
     /**
      * Creates a new selector from the given includes and excludes.
      *
@@ -232,17 +240,18 @@ public PathSelector(
         baseDirectory = Objects.requireNonNull(directory, "directory cannot be 
null");
         includePatterns = normalizePatterns(includes, false);
         excludePatterns = normalizePatterns(effectiveExcludes(excludes, 
includePatterns, useDefaultExcludes), true);
-        FileSystem system = baseDirectory.getFileSystem();
-        this.includes = matchers(system, includePatterns);
-        this.excludes = matchers(system, excludePatterns);
-        dirIncludes = matchers(system, directoryPatterns(includePatterns, 
false));
-        dirExcludes = matchers(system, directoryPatterns(excludePatterns, 
true));
+        FileSystem fileSystem = baseDirectory.getFileSystem();
+        this.includes = matchers(fileSystem, includePatterns);
+        this.excludes = matchers(fileSystem, excludePatterns);
+        dirIncludes = matchers(fileSystem, directoryPatterns(includePatterns, 
false));
+        dirExcludes = matchers(fileSystem, directoryPatterns(excludePatterns, 
true));
+        needRelativize = needRelativize(includePatterns) || 
needRelativize(excludePatterns);
     }
 
     /**
      * Returns the given array of excludes, optionally expanded with a default 
set of excludes,
      * then with unnecessary excludes omitted. An unnecessary exclude is an 
exclude which will never
-     * match a file because there is no include which would accept a file that 
could match the exclude.
+     * match a file because there are no includes which would accept a file 
that could match the exclude.
      * For example, if the only include is {@code "*.java"}, then the 
<code>"**&sol;project.pj"</code>,
      * <code>"**&sol;.DS_Store"</code> and other excludes will never match a 
file and can be omitted.
      * Because the list of {@linkplain #DEFAULT_EXCLUDES default excludes} 
contains many elements,
@@ -269,10 +278,14 @@ private static Collection<String> effectiveExcludes(
             }
         } else {
             excludes = new ArrayList<>(excludes);
+            excludes.removeIf(Objects::isNull);
             if (useDefaultExcludes) {
                 excludes.addAll(DEFAULT_EXCLUDES);
             }
         }
+        if (includes.length == 0) {
+            return excludes;
+        }
         /*
          * Get the prefixes and suffixes of all includes, stopping at the 
first special character.
          * Redundant prefixes and suffixes are omitted.
@@ -473,7 +486,7 @@ private static void addPatternsWithOneDirRemoved(final 
Set<String> patterns, fin
      * Applies some heuristic rules for simplifying the set of patterns,
      * then returns the patterns as an array.
      *
-     * @param patterns the patterns to simplify and return asarray
+     * @param patterns the patterns to simplify and return as an array
      * @param excludes whether the patterns are exclude patterns
      * @return the set content as an array, after simplification
      */
@@ -497,7 +510,7 @@ private static String[] simplify(Set<String> patterns, 
boolean excludes) {
      *
      * @param patterns the normalized include or exclude patterns
      * @param excludes whether the patterns are exclude patterns
-     * @return pattens of directories to include or exclude
+     * @return patterns of directories to include or exclude
      */
     private static String[] directoryPatterns(final String[] patterns, final 
boolean excludes) {
         // TODO: use `LinkedHashSet.newLinkedHashSet(int)` instead with JDK19.
@@ -523,6 +536,21 @@ private static String[] directoryPatterns(final String[] 
patterns, final boolean
         return simplify(directories, excludes);
     }
 
+    /**
+     * Returns {@code true} if at least one pattern requires path being 
relativized before to be matched.
+     *
+     * @param patterns include or exclude patterns
+     * @return whether at least one pattern require relativization
+     */
+    private static boolean needRelativize(String[] patterns) {
+        for (String pattern : patterns) {
+            if (!pattern.startsWith(DEFAULT_SYNTAX + "**/")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Creates the path matchers for the given patterns.
      * The syntax (usually {@value #DEFAULT_SYNTAX}) must be specified for 
each pattern.
@@ -535,12 +563,20 @@ private static PathMatcher[] matchers(final FileSystem 
fs, final String[] patter
         return matchers;
     }
 
+    /**
+     * {@return whether there are no include or exclude filters}.
+     * In such case, this {@code PathSelector} instance should be ignored.
+     */
+    public boolean isEmpty() {
+        return includes.length == 0 && excludes.length == 0;
+    }
+
     /**
      * {@return a potentially simpler matcher equivalent to this matcher}.
      */
     @SuppressWarnings("checkstyle:MissingSwitchDefault")
     public PathMatcher simplify() {
-        if (excludes.length == 0) {
+        if (!needRelativize && excludes.length == 0) {
             switch (includes.length) {
                 case 0:
                     return INCLUDES_ALL;
@@ -560,7 +596,9 @@ public PathMatcher simplify() {
      */
     @Override
     public boolean matches(Path path) {
-        path = baseDirectory.relativize(path);
+        if (needRelativize) {
+            path = baseDirectory.relativize(path);
+        }
         return (includes.length == 0 || isMatched(path, includes))
                 && (excludes.length == 0 || !isMatched(path, excludes));
     }

Reply via email to