From 837788d18a77ad05e64574ceaa73be8adffa5a38 Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Sat, 12 Jul 2025 12:06:20 +0200 Subject: [PATCH 1/2] Port the bug fixes identified when using that class in Maven clean and compiler plugin. --- .../org/apache/maven/impl/PathSelector.java | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 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 05401739341e..8705a36a1d99 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 @@ -28,6 +28,7 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -168,6 +169,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() */ @@ -175,7 +177,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. * @@ -185,6 +188,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; @@ -197,6 +201,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; @@ -212,6 +217,13 @@ public class PathSelector implements PathMatcher { */ private final Path baseDirectory; + /** + * Whether paths must be relativized before to be 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. * @@ -225,11 +237,12 @@ public PathSelector( includePatterns = normalizePatterns(includes, false); excludePatterns = normalizePatterns(effectiveExcludes(excludes, includePatterns, useDefaultExcludes), true); baseDirectory = directory; - FileSystem system = directory.getFileSystem(); - this.includes = matchers(system, includePatterns); - this.excludes = matchers(system, excludePatterns); - dirIncludes = matchers(system, directoryPatterns(includePatterns, false)); - dirExcludes = matchers(system, directoryPatterns(excludePatterns, true)); + FileSystem fs = directory.getFileSystem(); + this.includes = matchers(fs, includePatterns); + this.excludes = matchers(fs, excludePatterns); + dirIncludes = matchers(fs, directoryPatterns(includePatterns, false)); + dirExcludes = matchers(fs, directoryPatterns(excludePatterns, true)); + needRelativize = needRelativize(includePatterns) || needRelativize(excludePatterns); } /** @@ -262,10 +275,14 @@ private static Collection 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. @@ -466,7 +483,7 @@ private static void addPatternsWithOneDirRemoved(final Set 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 */ @@ -516,6 +533,21 @@ private static String[] directoryPatterns(final String[] patterns, final boolean return simplify(directories, excludes); } + /** + * Returns {@code true} if at least one pattern requires path to be 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. @@ -528,12 +560,20 @@ private static PathMatcher[] matchers(final FileSystem fs, final String[] patter return matchers; } + /** + * {@return whether there is no include or exclude filters}. + * In such case, this {@code PathSelector} instance should be ignored. + */ + public boolean isEmpty() { + return (includes.length | 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; @@ -553,7 +593,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)); } From 1bbeb7cef229cd345cf51bbedfbb923e202e44ee Mon Sep 17 00:00:00 2001 From: Martin Desruisseaux Date: Sun, 13 Jul 2025 20:10:40 +0200 Subject: [PATCH 2/2] Apply corrections for comments posted on the pull request. --- .../src/main/java/org/apache/maven/impl/PathSelector.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 8705a36a1d99..14a53448541e 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 @@ -534,7 +534,7 @@ private static String[] directoryPatterns(final String[] patterns, final boolean } /** - * Returns {@code true} if at least one pattern requires path to be relativized before to be matched. + * 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 @@ -561,11 +561,11 @@ private static PathMatcher[] matchers(final FileSystem fs, final String[] patter } /** - * {@return whether there is no include or exclude filters}. + * {@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 | excludes.length) == 0; + return includes.length == 0 && excludes.length == 0; } /**