Fix PathUtils.deleteFile() on symbolic links pointing to non-existing files
MODIFY
src/changes/changes.xml
src/changes/changes.xml
@@ -74,6 +74,10 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="fix" due-to="Gary Gregory">
FileUtils.forceDelete(File) actually forces deletion of read-only files as it did in version 2.6.
</action>
+ <action issue="IO-692" dev="ebourg" type="fix" due-to="Matthew Rooney, Emmanuel Bourg">
+ PathUtils.deleteFile() no longer throws a NoSuchFileException when applied on a symbolic link pointing
+ to a file that doesn't exist.
+ </action>
<!-- ADD -->
<action dev="ggregory" type="add" due-to="Gary Gregory">
Add FileSystemProviders class.

MODIFY
src/main/java/org/apache/commons/io/file/PathUtils.java
src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -481,7 +481,7 @@ public static PathCounters deleteFile(final Path file, final LinkOption[] linkOp
}
final PathCounters pathCounts = Counters.longPathCounters();
final boolean exists = Files.exists(file, linkOptions);
- final long size = exists ? Files.size(file) : 0;
+ final long size = exists && !Files.isSymbolicLink(file) ? Files.size(file) : 0;
if (overrideReadOnly(deleteOptions) && exists) {
setReadOnly(file, false, linkOptions);
}

MODIFY
src/test/java/org/apache/commons/io/file/PathUtilsDeleteFileTest.java
src/test/java/org/apache/commons/io/file/PathUtilsDeleteFileTest.java
import static org.apache.commons.io.file.CounterAssertions.assertCounts;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -142,4 +145,20 @@ public void testSetReadOnlyFileDirectory1FileSize1() throws IOException {
// This will throw if not empty.
Files.deleteIfExists(tempDir);
}
+
+ @Test
+ public void testDeleteBrokenLink() throws IOException {
+ assumeFalse(SystemUtils.IS_OS_WINDOWS);
+
+ Path missingFile = tempDir.resolve("missing.txt");
+ Path brokenLink = tempDir.resolve("broken.txt");
+ Files.createSymbolicLink(brokenLink, missingFile);
+
+ assertTrue(Files.exists(brokenLink, LinkOption.NOFOLLOW_LINKS));
+ assertFalse(Files.exists(missingFile, LinkOption.NOFOLLOW_LINKS));
+
+ PathUtils.deleteFile(brokenLink);
+
+ assertFalse(Files.exists(brokenLink, LinkOption.NOFOLLOW_LINKS), "Symbolic link not removed");
+ }
}

IO-692: Fix PathUtils.deleteFile() on symbolic links pointing to non-existing files