This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git


The following commit(s) were added to refs/heads/master by this push:
     new 4f71ae00 Make copyFile copy symbolic links by value rather than 
reference (#565)
4f71ae00 is described below

commit 4f71ae00a52bd6617f36654730b260417b75f98a
Author: Elliotte Rusty Harold <[email protected]>
AuthorDate: Wed Jan 24 14:02:09 2024 +0000

    Make copyFile copy symbolic links by value rather than reference (#565)
    
    * Make copyFile copy symbolic links by value rather than reference
    
    * inline variable
---
 src/main/java/org/apache/commons/io/FileUtils.java | 35 +++++++++++-----------
 .../java/org/apache/commons/io/FileUtilsTest.java  |  4 ++-
 2 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/src/main/java/org/apache/commons/io/FileUtils.java 
b/src/main/java/org/apache/commons/io/FileUtils.java
index d2e17d6b..cae3e8d7 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -57,7 +57,6 @@ import java.time.chrono.ChronoLocalDate;
 import java.time.chrono.ChronoLocalDateTime;
 import java.time.chrono.ChronoZonedDateTime;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -652,7 +651,7 @@ public class FileUtils {
      * @since 1.4
      */
     public static void copyDirectory(final File srcDir, final File destDir, 
final FileFilter filter, final boolean preserveFileDate) throws IOException {
-        copyDirectory(srcDir, destDir, filter, preserveFileDate, 
StandardCopyOption.REPLACE_EXISTING);
+        copyDirectory(srcDir, destDir, filter, preserveFileDate, 
StandardCopyOption.REPLACE_EXISTING, LinkOption.NOFOLLOW_LINKS);
     }
 
     /**
@@ -760,13 +759,13 @@ public class FileUtils {
      * <p>
      * This method copies the contents of the specified source file to the 
specified destination file. The directory
      * holding the destination file is created if it does not exist. If the 
destination file exists, then this method
-     * will overwrite it.
+     * overwrites it. A symbolic link is resolved before copying so the new 
file is not a link.
      * </p>
      * <p>
      * <strong>Note:</strong> This method tries to preserve the file's last 
modified date/times using
      * {@link BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. 
However, it is not guaranteed that the
-     * operation will succeed. If the modification operation fails it falls 
back to
-     * {@link File#setLastModified(long)} and if that fails, the method throws 
IOException.
+     * operation will succeed. If the modification operation fails, it falls 
back to
+     * {@link File#setLastModified(long)}, and if that fails, the method 
throws IOException.
      * </p>
      *
      * @param srcFile an existing file to copy, must not be {@code null}.
@@ -787,13 +786,13 @@ public class FileUtils {
      * <p>
      * This method copies the contents of the specified source file to the 
specified destination file. The directory
      * holding the destination file is created if it does not exist. If the 
destination file exists, then this method
-     * will overwrite it.
+     * overwrites it. A symbolic link is resolved before copying so the new 
file is not a link.
      * </p>
      * <p>
      * <strong>Note:</strong> Setting {@code preserveFileDate} to {@code true} 
tries to preserve the file's last
      * modified date/times using {@link 
BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is
-     * not guaranteed that the operation will succeed. If the modification 
operation fails it falls back to
-     * {@link File#setLastModified(long)} and if that fails, the method throws 
IOException.
+     * not guaranteed that the operation will succeed. If the modification 
operation fails, it falls back to
+     * {@link File#setLastModified(long)}, and if that fails, the method 
throws IOException.
      * </p>
      *
      * @param srcFile an existing file to copy, must not be {@code null}.
@@ -810,17 +809,23 @@ public class FileUtils {
     }
 
     /**
-     * Copies a file to a new location.
+     * Copies the contents of a file to a new location.
      * <p>
      * This method copies the contents of the specified source file to the 
specified destination file. The directory
      * holding the destination file is created if it does not exist. If the 
destination file exists, you can overwrite
      * it with {@link StandardCopyOption#REPLACE_EXISTING}.
      * </p>
+     *
+     * <p>
+     * By default, a symbolic link is resolved before copying so the new file 
is not a link.
+     * To copy symbolic links as links, you can pass {@code 
LinkOption.NO_FOLLOW_LINKS} as the last argument.
+     * </p>
+     *
      * <p>
      * <strong>Note:</strong> Setting {@code preserveFileDate} to {@code true} 
tries to preserve the file's last
      * modified date/times using {@link 
BasicFileAttributeView#setTimes(FileTime, FileTime, FileTime)}. However, it is
-     * not guaranteed that the operation will succeed. If the modification 
operation fails it falls back to
-     * {@link File#setLastModified(long)} and if that fails, the method throws 
IOException.
+     * not guaranteed that the operation will succeed. If the modification 
operation fails, it falls back to
+     * {@link File#setLastModified(long)}, and if that fails, the method 
throws IOException.
      * </p>
      *
      * @param srcFile an existing file to copy, must not be {@code null}.
@@ -846,17 +851,11 @@ public class FileUtils {
         }
 
         final Path srcPath = srcFile.toPath();
-        final boolean isSymLink = Files.isSymbolicLink(srcPath);
-        if (isSymLink && 
!Arrays.asList(copyOptions).contains(LinkOption.NOFOLLOW_LINKS)) {
-            final List<CopyOption> list = new 
ArrayList<>(Arrays.asList(copyOptions));
-            list.add(LinkOption.NOFOLLOW_LINKS);
-            copyOptions = list.toArray(PathUtils.EMPTY_COPY_OPTIONS);
-        }
 
         Files.copy(srcPath, destFile.toPath(), copyOptions);
 
         // On Windows, the last modified time is copied by default.
-        if (preserveFileDate && !isSymLink && !setTimes(srcFile, destFile)) {
+        if (preserveFileDate && !Files.isSymbolicLink(srcPath) && 
!setTimes(srcFile, destFile)) {
             throw new IOException("Cannot set the file time.");
         }
     }
diff --git a/src/test/java/org/apache/commons/io/FileUtilsTest.java 
b/src/test/java/org/apache/commons/io/FileUtilsTest.java
index db55429f..d7c8e7e0 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsTest.java
@@ -1115,7 +1115,9 @@ public class FileUtilsTest extends AbstractTempDirTest {
         // Now copy symlink to another directory
         final File destination = new File(tempDirFile, "destination");
         FileUtils.copyFile(linkPath.toFile(), destination);
-        assertTrue(Files.isSymbolicLink(destination.toPath()));
+        assertFalse(Files.isSymbolicLink(destination.toPath()));
+        final String contents = FileUtils.readFileToString(destination, 
StandardCharsets.UTF_8);
+        assertEquals("HELLO WORLD", contents);
     }
 
 

Reply via email to