Skip to content

Commit f1a8e5a

Browse files
gnodetdesruisseaux
andauthored
[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.desruisseaux@geomatys.com> (cherry picked from commit 012ea25) * Fixes --------- Co-authored-by: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
1 parent a7b5e0e commit f1a8e5a

File tree

1 file changed

+52
-14
lines changed

1 file changed

+52
-14
lines changed

impl/maven-impl/src/main/java/org/apache/maven/impl/PathSelector.java

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@
5959
* If above changes are not desired, put an explicit {@code "glob:"} prefix before the pattern.
6060
* Note that putting such a prefix is recommended anyway for better performances.
6161
*
62-
* @author Benjamin Bentmann
63-
* @author Martin Desruisseaux
64-
*
6562
* @see java.nio.file.FileSystem#getPathMatcher(String)
6663
*/
6764
public class PathSelector implements PathMatcher {
@@ -171,14 +168,16 @@ public class PathSelector implements PathMatcher {
171168
/**
172169
* String representations of the normalized include filters.
173170
* Each pattern shall be prefixed by its syntax, which is {@value #DEFAULT_SYNTAX} by default.
171+
* An empty array means to include all files.
174172
*
175173
* @see #toString()
176174
*/
177175
private final String[] includePatterns;
178176

179177
/**
180178
* String representations of the normalized exclude filters.
181-
* Each pattern shall be prefixed by its syntax, which is {@value #DEFAULT_SYNTAX} by default.
179+
* Each pattern shall be prefixed by its syntax. If no syntax is specified,
180+
* the default is a Maven 3 syntax similar, but not identical, to {@value #DEFAULT_SYNTAX}.
182181
* This array may be longer or shorter than the user-supplied excludes, depending on whether
183182
* default excludes have been added and whether some unnecessary excludes have been omitted.
184183
*
@@ -188,6 +187,7 @@ public class PathSelector implements PathMatcher {
188187

189188
/**
190189
* The matcher for includes. The length of this array is equal to {@link #includePatterns} array length.
190+
* An empty array means to include all files.
191191
*/
192192
private final PathMatcher[] includes;
193193

@@ -200,6 +200,7 @@ public class PathSelector implements PathMatcher {
200200
* The matcher for all directories to include. This array includes the parents of all those directories,
201201
* because they need to be accepted before we can walk to the sub-directories.
202202
* This is an optimization for skipping whole directories when possible.
203+
* An empty array means to include all directories.
203204
*/
204205
private final PathMatcher[] dirIncludes;
205206

@@ -215,6 +216,13 @@ public class PathSelector implements PathMatcher {
215216
*/
216217
private final Path baseDirectory;
217218

219+
/**
220+
* Whether paths must be relativized before being given to a matcher. If {@code true}, then every paths
221+
* will be made relative to {@link #baseDirectory} for allowing patterns like {@code "foo/bar/*.java"}
222+
* to work. As a slight optimization, we can skip this step if all patterns start with {@code "**"}.
223+
*/
224+
private final boolean needRelativize;
225+
218226
/**
219227
* Creates a new selector from the given includes and excludes.
220228
*
@@ -232,17 +240,18 @@ public PathSelector(
232240
baseDirectory = Objects.requireNonNull(directory, "directory cannot be null");
233241
includePatterns = normalizePatterns(includes, false);
234242
excludePatterns = normalizePatterns(effectiveExcludes(excludes, includePatterns, useDefaultExcludes), true);
235-
FileSystem system = baseDirectory.getFileSystem();
236-
this.includes = matchers(system, includePatterns);
237-
this.excludes = matchers(system, excludePatterns);
238-
dirIncludes = matchers(system, directoryPatterns(includePatterns, false));
239-
dirExcludes = matchers(system, directoryPatterns(excludePatterns, true));
243+
FileSystem fileSystem = baseDirectory.getFileSystem();
244+
this.includes = matchers(fileSystem, includePatterns);
245+
this.excludes = matchers(fileSystem, excludePatterns);
246+
dirIncludes = matchers(fileSystem, directoryPatterns(includePatterns, false));
247+
dirExcludes = matchers(fileSystem, directoryPatterns(excludePatterns, true));
248+
needRelativize = needRelativize(includePatterns) || needRelativize(excludePatterns);
240249
}
241250

242251
/**
243252
* Returns the given array of excludes, optionally expanded with a default set of excludes,
244253
* then with unnecessary excludes omitted. An unnecessary exclude is an exclude which will never
245-
* match a file because there is no include which would accept a file that could match the exclude.
254+
* match a file because there are no includes which would accept a file that could match the exclude.
246255
* For example, if the only include is {@code "*.java"}, then the <code>"**&sol;project.pj"</code>,
247256
* <code>"**&sol;.DS_Store"</code> and other excludes will never match a file and can be omitted.
248257
* Because the list of {@linkplain #DEFAULT_EXCLUDES default excludes} contains many elements,
@@ -269,10 +278,14 @@ private static Collection<String> effectiveExcludes(
269278
}
270279
} else {
271280
excludes = new ArrayList<>(excludes);
281+
excludes.removeIf(Objects::isNull);
272282
if (useDefaultExcludes) {
273283
excludes.addAll(DEFAULT_EXCLUDES);
274284
}
275285
}
286+
if (includes.length == 0) {
287+
return excludes;
288+
}
276289
/*
277290
* Get the prefixes and suffixes of all includes, stopping at the first special character.
278291
* Redundant prefixes and suffixes are omitted.
@@ -473,7 +486,7 @@ private static void addPatternsWithOneDirRemoved(final Set<String> patterns, fin
473486
* Applies some heuristic rules for simplifying the set of patterns,
474487
* then returns the patterns as an array.
475488
*
476-
* @param patterns the patterns to simplify and return asarray
489+
* @param patterns the patterns to simplify and return as an array
477490
* @param excludes whether the patterns are exclude patterns
478491
* @return the set content as an array, after simplification
479492
*/
@@ -497,7 +510,7 @@ private static String[] simplify(Set<String> patterns, boolean excludes) {
497510
*
498511
* @param patterns the normalized include or exclude patterns
499512
* @param excludes whether the patterns are exclude patterns
500-
* @return pattens of directories to include or exclude
513+
* @return patterns of directories to include or exclude
501514
*/
502515
private static String[] directoryPatterns(final String[] patterns, final boolean excludes) {
503516
// TODO: use `LinkedHashSet.newLinkedHashSet(int)` instead with JDK19.
@@ -523,6 +536,21 @@ private static String[] directoryPatterns(final String[] patterns, final boolean
523536
return simplify(directories, excludes);
524537
}
525538

539+
/**
540+
* Returns {@code true} if at least one pattern requires path being relativized before to be matched.
541+
*
542+
* @param patterns include or exclude patterns
543+
* @return whether at least one pattern require relativization
544+
*/
545+
private static boolean needRelativize(String[] patterns) {
546+
for (String pattern : patterns) {
547+
if (!pattern.startsWith(DEFAULT_SYNTAX + "**/")) {
548+
return true;
549+
}
550+
}
551+
return false;
552+
}
553+
526554
/**
527555
* Creates the path matchers for the given patterns.
528556
* 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
535563
return matchers;
536564
}
537565

566+
/**
567+
* {@return whether there are no include or exclude filters}.
568+
* In such case, this {@code PathSelector} instance should be ignored.
569+
*/
570+
public boolean isEmpty() {
571+
return includes.length == 0 && excludes.length == 0;
572+
}
573+
538574
/**
539575
* {@return a potentially simpler matcher equivalent to this matcher}.
540576
*/
541577
@SuppressWarnings("checkstyle:MissingSwitchDefault")
542578
public PathMatcher simplify() {
543-
if (excludes.length == 0) {
579+
if (!needRelativize && excludes.length == 0) {
544580
switch (includes.length) {
545581
case 0:
546582
return INCLUDES_ALL;
@@ -560,7 +596,9 @@ public PathMatcher simplify() {
560596
*/
561597
@Override
562598
public boolean matches(Path path) {
563-
path = baseDirectory.relativize(path);
599+
if (needRelativize) {
600+
path = baseDirectory.relativize(path);
601+
}
564602
return (includes.length == 0 || isMatched(path, includes))
565603
&& (excludes.length == 0 || !isMatched(path, excludes));
566604
}

0 commit comments

Comments
 (0)