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/)
 ======================
 
-[![ASF 
Jira](https://img.shields.io/endpoint?url=https%3A%2F%2Fmaven.apache.org%2Fbadges%2Fasf_jira-MCLEAN.json)][jira]
 [![Apache License, Version 2.0, January 
2004](https://img.shields.io/github/license/apache/maven.svg?label=License)][license]
+[![Maven 
Central](https://img.shields.io/maven-central/v/org.apache.maven.plugins/maven-clean-plugin.svg?label=Maven%20Central&versionPrefix=3.)](https://search.maven.org/artifact/org.apache.maven.plugins/maven-clean-plugin)
 [![Maven 
Central](https://img.shields.io/maven-central/v/org.apache.maven.plugins/maven-clean-plugin.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.maven.plugins/maven-clean-plugin)
-[![Reproducible 
Builds](https://img.shields.io/badge/Reproducible_Builds-ok-green?labelColor=blue)](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/org/apache/maven/plugins/maven-clean-plugin/README.md)
+[![Reproducible 
Builds](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/jvm-repo-rebuild/reproducible-central/master/content/org/apache/maven/plugins/maven-clean-plugin/badge.json)](https://github.com/jvm-repo-rebuild/reproducible-central/blob/master/content/org/apache/maven/plugins/maven-clean-plugin/README.md)
 [![Jenkins 
Status](https://img.shields.io/jenkins/s/https/ci-maven.apache.org/job/Maven/job/maven-box/job/maven-clean-plugin/job/master.svg?)][build]
 [![Jenkins 
tests](https://img.shields.io/jenkins/t/https/ci-maven.apache.org/job/Maven/job/maven-box/job/maven-clean-plugin/job/master.svg?)][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));
     }

Reply via email to