Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package maven-clean-plugin for openSUSE:Factory checked in at 2025-06-10 09:03:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/maven-clean-plugin (Old) and /work/SRC/openSUSE:Factory/.maven-clean-plugin.new.19631 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "maven-clean-plugin" Tue Jun 10 09:03:23 2025 rev:6 rq:1283731 version:3.5.0 Changes: -------- --- /work/SRC/openSUSE:Factory/maven-clean-plugin/maven-clean-plugin.changes 2025-02-21 21:37:04.053987101 +0100 +++ /work/SRC/openSUSE:Factory/.maven-clean-plugin.new.19631/maven-clean-plugin.changes 2025-06-10 09:06:46.183117237 +0200 @@ -1,0 +2,15 @@ +Thu Jun 5 15:37:22 UTC 2025 - Fridrich Strba <[email protected]> + +- Update to upstream version 3.5.0 + * New features and improvements + + Configuration parameter for deleting read-only files + * Maintenance + + Bump project to 3.5.0-SNAPSHOT version + + Update README in 3.x branch + * Dependency updates + + Bump org.apache.maven.resolver:maven-resolver-api from 1.9.22 + to 1.9.23 + + Bump org.codehaus.plexus:plexus-testing from 1.4.0 to 1.5.0 + + Bump org.apache.maven.plugins:maven-plugins from 43 to 44 + +------------------------------------------------------------------- Old: ---- maven-clean-plugin-3.4.1-source-release.zip New: ---- maven-clean-plugin-3.5.0-source-release.zip ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ maven-clean-plugin.spec ++++++ --- /var/tmp/diff_new_pack.GQ39xr/_old 2025-06-10 09:06:46.723139555 +0200 +++ /var/tmp/diff_new_pack.GQ39xr/_new 2025-06-10 09:06:46.723139555 +0200 @@ -17,7 +17,7 @@ Name: maven-clean-plugin -Version: 3.4.1 +Version: 3.5.0 Release: 0 Summary: Maven plugin to remove generated files License: Apache-2.0 ++++++ maven-clean-plugin-3.4.1-source-release.zip -> maven-clean-plugin-3.5.0-source-release.zip ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/DEPENDENCIES new/maven-clean-plugin-3.5.0/DEPENDENCIES --- old/maven-clean-plugin-3.4.1/DEPENDENCIES 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/DEPENDENCIES 2025-05-27 21:55:46.000000000 +0200 @@ -8,7 +8,7 @@ From: 'Codehaus Plexus' (https://codehaus-plexus.github.io/) - - Plexus Common Utilities (https://codehaus-plexus.github.io/plexus-utils/) org.codehaus.plexus:plexus-utils:jar:4.0.1 + - Plexus Common Utilities (https://codehaus-plexus.github.io/plexus-utils/) org.codehaus.plexus:plexus-utils:jar:4.0.2 License: Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/README.md new/maven-clean-plugin-3.5.0/README.md --- old/maven-clean-plugin-3.4.1/README.md 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/README.md 2025-05-27 21:55:46.000000000 +0200 @@ -17,15 +17,14 @@ Contributing to [Apache Maven Clean Plugin](https://maven.apache.org/plugins/maven-clean-plugin/) ====================== -[][jira] [][license] +[](https://search.maven.org/artifact/org.apache.maven.plugins/maven-clean-plugin) [](https://search.maven.org/artifact/org.apache.maven.plugins/maven-clean-plugin) -[](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/org/apache/maven/plugins/maven-clean-plugin/README.md) +[](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/org/apache/maven/plugins/maven-clean-plugin/README.md) [][build] [][test-results] - -You have found a bug or you have an idea for a cool new feature? Contributing +You have found a bug, or you have an idea for a cool new feature? Contributing code is a great way to give something back to the open source community. Before you dig right into the code, there are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of @@ -34,11 +33,10 @@ Getting Started --------------- -+ Make sure you have a [JIRA account](https://issues.apache.org/jira/). + Make sure you have a [GitHub account](https://github.com/signup/free). -+ If you're planning to implement a new feature, it makes sense to discuss your changes - on the [dev list][ml-list] first. - This way you can make sure you're not wasting your time on something that isn't ++ If you're planning to implement a new feature, it makes sense to discuss your changes + on the [dev list][ml-list] first. + This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Maven's scope. + Submit a ticket for your issue, assuming one does not already exist. + Clearly describe the issue, including steps to reproduce when it is a bug. @@ -57,44 +55,30 @@ + Respect the original code style: by using the same [codestyle][code-style], patches should only highlight the actual difference, not being disturbed by any formatting issues: + Only use spaces for indentation. - + Create minimal diffs - disable on save actions like reformat source code or organize imports. + + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted, create a separate PR for this change. + Check for unnecessary whitespace with `git diff --check` before committing. -+ Make sure your commit messages are in the proper format. Your commit message should contain the key of the JIRA issue. -``` -[MCLEAN-XXX] - Subject of the JIRA Ticket - Optional supplemental description. -``` + Make sure you have added the necessary tests (JUnit/IT) for your changes. + Run all the tests with `mvn -Prun-its verify` to assure nothing else was accidentally broken. + Submit a pull request to the repository in the Apache organization. -+ Update your JIRA ticket and include a link to the pull request in the ticket. If you plan to contribute on a regular basis, please consider filing a [contributor license agreement][cla]. -Making Trivial Changes ----------------------- - -For changes of a trivial nature to comments and documentation, it is not always -necessary to create a new ticket in JIRA. In this case, it is appropriate to -start the first line of a commit with '(doc)' instead of a ticket number. - Additional Resources -------------------- + [Contributing patches](https://maven.apache.org/guides/development/guide-maven-development.html#Creating_and_submitting_a_patch) -+ [Apache Maven Clean JIRA project page][jira] + [Contributor License Agreement][cla] + [General GitHub documentation](https://help.github.com/) + [GitHub pull request documentation](https://help.github.com/send-pull-requests/) -+ [Apache Maven Twitter Account](https://twitter.com/ASFMavenProject) -+ #Maven IRC channel on freenode.org ++ [Apache Maven X Account](https://x.com/ASFMavenProject) ++ [Apache Maven Bluesky Account](https://bsky.app/profile/maven.apache.org) ++ [Apache Maven Mastodon Account](https://mastodon.social/deck/@[email protected]) -[jira]: https://issues.apache.org/jira/projects/MCLEAN/ [license]: https://www.apache.org/licenses/LICENSE-2.0 [ml-list]: https://maven.apache.org/mailing-lists.html [code-style]: https://maven.apache.org/developers/conventions/code.html [cla]: https://www.apache.org/licenses/#clas [maven-wiki]: https://cwiki.apache.org/confluence/display/MAVEN/Index -[test-results]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-clean-plugin/job/master/lastCompletedBuild/testReport/ -[build]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-clean-plugin/job/master/ +[test-results]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-clean-plugin/job/maven-clean-plugin-3.x/lastCompletedBuild/testReport/ +[build]: https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven-clean-plugin/job/maven-clean-plugin-3.x/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/pom.xml new/maven-clean-plugin-3.5.0/pom.xml --- old/maven-clean-plugin-3.4.1/pom.xml 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/pom.xml 2025-05-27 21:55:46.000000000 +0200 @@ -23,12 +23,12 @@ <parent> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugins</artifactId> - <version>43</version> + <version>44</version> <relativePath /> </parent> <artifactId>maven-clean-plugin</artifactId> - <version>3.4.1</version> + <version>3.5.0</version> <packaging>maven-plugin</packaging> <name>Apache Maven Clean Plugin</name> @@ -42,7 +42,7 @@ <scm> <connection>scm:git:https://gitbox.apache.org/repos/asf/maven-clean-plugin.git</connection> <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-clean-plugin.git</developerConnection> - <tag>maven-clean-plugin-3.4.1</tag> + <tag>maven-clean-plugin-3.5.0</tag> <url>https://github.com/apache/maven-clean-plugin/tree/${project.scm.tag}</url> </scm> <issueManagement> @@ -62,7 +62,7 @@ <properties> <mavenVersion>3.9.9</mavenVersion> - <project.build.outputTimestamp>2025-02-15T18:49:15Z</project.build.outputTimestamp> + <project.build.outputTimestamp>2025-05-27T21:55:45Z</project.build.outputTimestamp> </properties> <dependencies> @@ -81,7 +81,7 @@ <dependency> <groupId>org.apache.maven.resolver</groupId> <artifactId>maven-resolver-api</artifactId> - <version>1.9.22</version> + <version>1.9.23</version> <scope>provided</scope> </dependency> <dependency> @@ -93,6 +93,7 @@ <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> + <version>${version.maven-plugin-tools}</version> <scope>provided</scope> </dependency> @@ -117,7 +118,7 @@ <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-testing</artifactId> - <version>1.4.0</version> + <version>1.5.0</version> <scope>test</scope> </dependency> <dependency> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/it/read-only/pom.xml new/maven-clean-plugin-3.5.0/src/it/read-only/pom.xml --- old/maven-clean-plugin-3.4.1/src/it/read-only/pom.xml 1970-01-01 01:00:00.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/it/read-only/pom.xml 2025-05-27 21:55:46.000000000 +0200 @@ -0,0 +1,48 @@ +<?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/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>test</groupId> + <artifactId>read-only</artifactId> + <version>1.0-SNAPSHOT</version> + + <name>Test for clean</name> + <description>Check for proper deletion (or not) of read-only files.</description> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-clean-plugin</artifactId> + <version>@pom.version@</version> + <configuration> + <force>true</force> + <retryOnError>false</retryOnError> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/it/read-only/setup.bsh new/maven-clean-plugin-3.5.0/src/it/read-only/setup.bsh --- old/maven-clean-plugin-3.4.1/src/it/read-only/setup.bsh 1970-01-01 01:00:00.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/it/read-only/setup.bsh 2025-05-27 21:55:46.000000000 +0200 @@ -0,0 +1,37 @@ +/* + * 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 java.io.File; + +if (!new File(basedir, "target/read-only-dir/read-only.properties").setWritable(false)) { + System.out.println("Cannot change file permission."); + return false; +} +if (File.separatorChar == '/') { + // Directory permission can be changed only on Unix, not on Windows. + if (!new File(basedir, "target/read-only-dir").setWritable(false)) { + System.out.println("Cannot change directory permission."); + return false; + } +} +if (!new File(basedir, "target/writable-dir/writable.properties").canWrite()) { + System.out.println("Expected a writable file."); + return false; +} +return true; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/it/read-only/target/read-only-dir/read-only.properties new/maven-clean-plugin-3.5.0/src/it/read-only/target/read-only-dir/read-only.properties --- old/maven-clean-plugin-3.4.1/src/it/read-only/target/read-only-dir/read-only.properties 1970-01-01 01:00:00.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/it/read-only/target/read-only-dir/read-only.properties 2025-05-27 21:55:46.000000000 +0200 @@ -0,0 +1,16 @@ +# 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/it/read-only/target/writable-dir/writable.properties new/maven-clean-plugin-3.5.0/src/it/read-only/target/writable-dir/writable.properties --- old/maven-clean-plugin-3.4.1/src/it/read-only/target/writable-dir/writable.properties 1970-01-01 01:00:00.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/it/read-only/target/writable-dir/writable.properties 2025-05-27 21:55:46.000000000 +0200 @@ -0,0 +1,16 @@ +# 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/it/read-only/verify.bsh new/maven-clean-plugin-3.5.0/src/it/read-only/verify.bsh --- old/maven-clean-plugin-3.4.1/src/it/read-only/verify.bsh 1970-01-01 01:00:00.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/it/read-only/verify.bsh 2025-05-27 21:55:46.000000000 +0200 @@ -0,0 +1,26 @@ +/* + * 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 java.io.File; + +if (new File(basedir, "target").exists()) { + System.out.println("target should have been deleted."); + return false; +} +return true; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java new/maven-clean-plugin-3.5.0/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java --- old/maven-clean-plugin-3.4.1/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/main/java/org/apache/maven/plugins/clean/CleanMojo.java 2025-05-27 21:55:46.000000000 +0200 @@ -129,6 +129,14 @@ private boolean followSymLinks; /** + * Whether to force the deletion of read-only files. + * + * @since 3.5.0 + */ + @Parameter(property = "maven.clean.force", defaultValue = "false") + private boolean force; + + /** * Disables the plugin execution. <br/> * Starting with <code>3.0.0</code> the property has been renamed from <code>clean.skip</code> to * <code>maven.clean.skip</code>. @@ -249,7 +257,7 @@ + FAST_MODE_BACKGROUND + "', '" + FAST_MODE_AT_END + "' and '" + FAST_MODE_DEFER + "'."); } - Cleaner cleaner = new Cleaner(session, getLog(), isVerbose(), fastDir, fastMode); + Cleaner cleaner = new Cleaner(session, getLog(), isVerbose(), fastDir, fastMode, force); try { for (Path directoryItem : getDirectories()) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/main/java/org/apache/maven/plugins/clean/Cleaner.java new/maven-clean-plugin-3.5.0/src/main/java/org/apache/maven/plugins/clean/Cleaner.java --- old/maven-clean-plugin-3.4.1/src/main/java/org/apache/maven/plugins/clean/Cleaner.java 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/main/java/org/apache/maven/plugins/clean/Cleaner.java 2025-05-27 21:55:46.000000000 +0200 @@ -23,14 +23,21 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.nio.file.AccessDeniedException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.DosFileAttributeView; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFilePermission; import java.util.ArrayDeque; import java.util.Deque; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; import org.apache.maven.execution.ExecutionListener; import org.apache.maven.execution.MavenSession; @@ -69,6 +76,13 @@ private Log log; /** + * Whether to force the deletion of read-only files. Note that on Linux, + * {@link Files#delete(Path)} and {@link Files#deleteIfExists(Path)} delete read-only files + * but throw {@link AccessDeniedException} if the directory containing the file is read-only. + */ + private final boolean force; + + /** * Creates a new cleaner. * * @param session The Maven session to be used. @@ -76,8 +90,9 @@ * @param verbose Whether to perform verbose logging. * @param fastDir The explicit configured directory or to be deleted in fast mode. * @param fastMode The fast deletion mode. + * @param force whether to force the deletion of read-only files */ - Cleaner(MavenSession session, final Log log, boolean verbose, Path fastDir, String fastMode) { + Cleaner(MavenSession session, final Log log, boolean verbose, Path fastDir, String fastMode, boolean force) { this.session = session; // This can't be null as the Cleaner gets it from the CleanMojo which gets it from AbstractMojo class, where it // is never null. @@ -85,6 +100,7 @@ this.fastDir = fastDir; this.fastMode = fastMode; this.verbose = verbose; + this.force = force; } /** @@ -263,6 +279,38 @@ } /** + * Makes the given file or directory writable. + * If the file is already writable, then this method tries to make the parent directory writable. + * + * @param file the path to the file or directory to make writable, or {@code null} if none + * @return the root path which has been made writable, or {@code null} if none + */ + private static Path setWritable(Path file) throws IOException { + while (file != null) { + PosixFileAttributeView posix = Files.getFileAttributeView(file, PosixFileAttributeView.class); + if (posix != null) { + EnumSet<PosixFilePermission> permissions = + EnumSet.copyOf(posix.readAttributes().permissions()); + if (permissions.add(PosixFilePermission.OWNER_WRITE)) { + posix.setPermissions(permissions); + return file; + } + } else { + DosFileAttributeView dos = Files.getFileAttributeView(file, DosFileAttributeView.class); + if (dos == null) { + return null; // Unknown type of file attributes. + } + // No need to update the parent directory because DOS read-only attribute does not apply to folders. + dos.setReadOnly(false); + return file; + } + // File was already writable. Maybe it is the parent directory which was not writable. + file = file.getParent(); + } + return null; + } + + /** * Deletes the specified file, directory. If the path denotes a symlink, only the link is removed, its target is * left untouched. * @@ -276,21 +324,35 @@ IOException failure = delete(file); if (failure != null) { boolean deleted = false; - - if (retryOnError) { - if (ON_WINDOWS) { - // try to release any locks held by non-closed files - System.gc(); + boolean tryWritable = force && failure instanceof AccessDeniedException; + if (tryWritable || retryOnError) { + final Set<Path> madeWritable; // Safety against never-ending loops. + if (force) { + madeWritable = new HashSet<>(); + madeWritable.add(null); // For having `add(null)` to return `false`. + } else { + madeWritable = null; } - final int[] delays = {50, 250, 750}; - for (int i = 0; !deleted && i < delays.length; i++) { - try { - Thread.sleep(delays[i]); - } catch (InterruptedException e) { - // ignore + int delayIndex = 0; + while (!deleted && delayIndex < delays.length) { + if (tryWritable) { + tryWritable = madeWritable.add(setWritable(file)); + // `true` if we successfully changed permission, in which case we will skip the delay. + } + if (!tryWritable) { + if (ON_WINDOWS) { + // Try to release any locks held by non-closed files. + System.gc(); + } + try { + Thread.sleep(delays[delayIndex++]); + } catch (InterruptedException e) { + // ignore + } } deleted = delete(file) == null || !exists(file); + tryWritable = !deleted && force && failure instanceof AccessDeniedException; } } else { deleted = !exists(file); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java new/maven-clean-plugin-3.5.0/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java --- old/maven-clean-plugin-3.4.1/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/test/java/org/apache/maven/plugins/clean/CleanMojoTest.java 2025-05-27 21:55:46.000000000 +0200 @@ -250,7 +250,7 @@ private void testSymlink(LinkCreator linkCreator) throws Exception { // We use the SystemStreamLog() as the AbstractMojo class, because from there the Log is always provided - Cleaner cleaner = new Cleaner(null, new SystemStreamLog(), false, null, null); + Cleaner cleaner = new Cleaner(null, new SystemStreamLog(), false, null, null, false); Path testDir = Paths.get("target/test-classes/unit/test-dir").toAbsolutePath(); Path dirWithLnk = testDir.resolve("dir"); Path orgDir = testDir.resolve("org-dir"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/maven-clean-plugin-3.4.1/src/test/java/org/apache/maven/plugins/clean/CleanerTest.java new/maven-clean-plugin-3.5.0/src/test/java/org/apache/maven/plugins/clean/CleanerTest.java --- old/maven-clean-plugin-3.4.1/src/test/java/org/apache/maven/plugins/clean/CleanerTest.java 2025-02-15 18:49:16.000000000 +0100 +++ new/maven-clean-plugin-3.5.0/src/test/java/org/apache/maven/plugins/clean/CleanerTest.java 2025-05-27 21:55:46.000000000 +0200 @@ -61,7 +61,7 @@ void deleteSucceedsDeeply(@TempDir Path tempDir) throws Exception { final Path basedir = createDirectory(tempDir.resolve("target")).toRealPath(); final Path file = createFile(basedir.resolve("file")); - final Cleaner cleaner = new Cleaner(null, log, false, null, null); + final Cleaner cleaner = new Cleaner(null, log, false, null, null, false); cleaner.delete(basedir, null, false, true, false); assertFalse(exists(basedir)); assertFalse(exists(file)); @@ -76,7 +76,7 @@ // Remove the executable flag to prevent directory listing, which will result in a DirectoryNotEmptyException. final Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("rw-rw-r--"); setPosixFilePermissions(basedir, permissions); - final Cleaner cleaner = new Cleaner(null, log, false, null, null); + final Cleaner cleaner = new Cleaner(null, log, false, null, null, false); final IOException exception = assertThrows(IOException.class, () -> cleaner.delete(basedir, null, false, true, false)); verify(log, never()).warn(any(CharSequence.class), any(Throwable.class)); @@ -94,7 +94,7 @@ // Remove the executable flag to prevent directory listing, which will result in a DirectoryNotEmptyException. final Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("rw-rw-r--"); setPosixFilePermissions(basedir, permissions); - final Cleaner cleaner = new Cleaner(null, log, false, null, null); + final Cleaner cleaner = new Cleaner(null, log, false, null, null, false); final IOException exception = assertThrows(IOException.class, () -> cleaner.delete(basedir, null, false, true, true)); assertEquals("Failed to delete " + basedir, exception.getMessage()); @@ -112,7 +112,7 @@ // Remove the writable flag to prevent deletion of the file, which will result in an AccessDeniedException. final Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("r-xr-xr-x"); setPosixFilePermissions(basedir, permissions); - final Cleaner cleaner = new Cleaner(null, log, false, null, null); + final Cleaner cleaner = new Cleaner(null, log, false, null, null, false); assertDoesNotThrow(() -> cleaner.delete(basedir, null, false, false, false)); verify(log, times(2)).warn(any(CharSequence.class), any(Throwable.class)); InOrder inOrder = inOrder(log); @@ -133,7 +133,7 @@ // Remove the writable flag to prevent deletion of the file, which will result in an AccessDeniedException. final Set<PosixFilePermission> permissions = PosixFilePermissions.fromString("r-xr-xr-x"); setPosixFilePermissions(basedir, permissions); - final Cleaner cleaner = new Cleaner(null, log, false, null, null); + final Cleaner cleaner = new Cleaner(null, log, false, null, null, false); assertDoesNotThrow(() -> cleaner.delete(basedir, null, false, false, false)); verify(log, never()).warn(any(CharSequence.class), any(Throwable.class)); }
