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 2d37ab6 IO-700: provide method overload for moveFile (#185) 2d37ab6 is described below commit 2d37ab6a0d53fce60095b352d36dddd9d26f5ab0 Author: tza <t...@silbergrau.com> AuthorDate: Tue Jan 12 21:32:04 2021 +0100 IO-700: provide method overload for moveFile (#185) - added test cases - updated javadoc for "copy and delete" with setLastModified --- src/main/java/org/apache/commons/io/FileUtils.java | 34 +++++++++++- .../org/apache/commons/io/FileUtilsTestCase.java | 61 ++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java index 4919d02..2c25bac 100644 --- a/src/main/java/org/apache/commons/io/FileUtils.java +++ b/src/main/java/org/apache/commons/io/FileUtils.java @@ -2159,6 +2159,11 @@ public class FileUtils { * <p> * When the destination file is on another file system, do a "copy and delete". * </p> + * <p> + * <strong>Note:</strong> This method tries to preserve the file's last modified date/times using + * {@link File#setLastModified(long)} when destination is another file system, however it is not guaranteed that the + * operation will succeed. If the modification operation fails, the methods throws IOException. + * </p> * * @param srcFile the file to be moved. * @param destFile the destination file. @@ -2169,12 +2174,39 @@ public class FileUtils { * @since 1.4 */ public static void moveFile(final File srcFile, final File destFile) throws IOException { + moveFile(srcFile, destFile, true); + } + + /** + * Moves a file. + * <p> + * When the destination file is on another file system, do a "copy and delete". + * </p> + * <p> + * <strong>Note:</strong> Setting <code>preserveFileDate</code> to {@code true} tries to preserve the files' last + * modified date/times using {@link File#setLastModified(long)} when destination is another file system, however it + * is not guaranteed that those operations will succeed. If the modification operation fails, the methods throws + * IOException. + * </p> + * + * @param srcFile the file to be moved. + * @param destFile the destination file. + * @param preserveFileDate true if the file date of the "copy and delete" should be the same as the original when + * destination is on another file system. Param is not used if destination is on same file system. + * @throws NullPointerException if any of the given {@code File}s are {@code null}. + * @throws FileExistsException if the destination file exists. + * @throws IOException if source or destination is invalid. + * @throws IOException if an error occurs or setting the last-modified time didn't succeeded. + * @since 2.9.0 + */ + public static void moveFile(final File srcFile, final File destFile, final boolean preserveFileDate) + throws IOException { validateMoveParameters(srcFile, destFile); requireFile(srcFile, "srcFile"); requireAbsent(destFile, null); final boolean rename = srcFile.renameTo(destFile); if (!rename) { - copyFile(srcFile, destFile); + copyFile(srcFile, destFile, preserveFileDate); if (!srcFile.delete()) { FileUtils.deleteQuietly(destFile); throw new IOException("Failed to delete original file '" + srcFile + diff --git a/src/test/java/org/apache/commons/io/FileUtilsTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsTestCase.java index dad0628..327322f 100644 --- a/src/test/java/org/apache/commons/io/FileUtilsTestCase.java +++ b/src/test/java/org/apache/commons/io/FileUtilsTestCase.java @@ -2164,6 +2164,67 @@ public class FileUtilsTestCase { assertTrue(destination.exists(), "Check Exist"); assertTrue(!src.exists(), "Original deleted"); } + + @Test + public void testMoveFile_CopyDelete_WithFileDatePreservation() throws Exception { + final File destination = new File(temporaryFolder, "move2.txt"); + + backDateFile10Minutes(testFile1); // set test file back 10 minutes + + final File src = new File(testFile1.getAbsolutePath()) { + private static final long serialVersionUID = 1L; + + // Force renameTo to fail, as if destination is on another + // filesystem + @Override + public boolean renameTo(final File f) { + return false; + } + }; + final long expected = getLastModifiedMillis(testFile1); + + FileUtils.moveFile(src, destination, true); + assertTrue(destination.exists(), "Check Exist"); + assertTrue(!src.exists(), "Original deleted"); + + final long destLastMod = getLastModifiedMillis(destination); + final long delta = destLastMod - expected; + assertEquals(expected, destLastMod, "Check last modified date same as input, delta " + delta); + } + + @Test + public void testMoveFile_CopyDelete_WithoutFileDatePreservation() throws Exception { + final File destination = new File(temporaryFolder, "move2.txt"); + + backDateFile10Minutes(testFile1); // set test file back 10 minutes + + // destination file time should not be less than this (allowing for granularity) + final long now = System.currentTimeMillis() - 1000L; + + final File src = new File(testFile1.getAbsolutePath()) { + private static final long serialVersionUID = 1L; + + // Force renameTo to fail, as if destination is on another + // filesystem + @Override + public boolean renameTo(final File f) { + return false; + } + }; + final long unexpected = getLastModifiedMillis(testFile1); + + FileUtils.moveFile(src, destination, false); + assertTrue(destination.exists(), "Check Exist"); + assertTrue(!src.exists(), "Original deleted"); + + // On Windows, the last modified time is copied by default. + if (!SystemUtils.IS_OS_WINDOWS) { + final long destLastMod = getLastModifiedMillis(destination); + final long delta = destLastMod - unexpected; + assertNotEquals(unexpected, destLastMod, "Check last modified date not same as input, delta " + delta); + assertTrue(destLastMod > now, destLastMod + " > " + now + " (delta " + delta + ")"); + } + } @Test public void testMoveFile_CopyDelete_Failed() throws Exception {