You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/06/14 21:34:14 UTC
[commons-io] 02/02: Add PathUtils.touch(Path)
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
commit fd7c8182d2117d01f43ccc9fe939105f834ba672
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Jun 14 17:34:05 2022 -0400
Add PathUtils.touch(Path)
Refactor
---
src/changes/changes.xml | 3 ++
src/main/java/org/apache/commons/io/FileUtils.java | 19 ++++-------
.../java/org/apache/commons/io/file/PathUtils.java | 21 ++++++++++++
.../java/org/apache/commons/io/FileUtilsTest.java | 8 ++---
.../org/apache/commons/io/file/PathUtilsTest.java | 39 ++++++++++++++++++++++
5 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c9db4116..31122869 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -368,6 +368,9 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="add" due-to="Gary Gregory">
Reduce boilerplate through new UncheckedIO class and friends in org.apache.commons.io.function.
</action>
+ <action dev="ggregory" type="add" due-to="Gary Gregory">
+ Add PathUtils.touch(Path).
+ </action>
<!-- UPDATE -->
<action dev="kinow" type="update" due-to="Dependabot, Gary Gregory">
Bump actions/cache from 2.1.6 to 3.0.4 #307, #337.
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java
index 6bda85a4..c2d8945b 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -70,7 +70,6 @@ import org.apache.commons.io.file.Counters;
import org.apache.commons.io.file.PathFilter;
import org.apache.commons.io.file.PathUtils;
import org.apache.commons.io.file.StandardDeleteOption;
-import org.apache.commons.io.file.attribute.FileTimes;
import org.apache.commons.io.filefilter.FileEqualsFileFilter;
import org.apache.commons.io.filefilter.FileFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
@@ -3050,25 +3049,19 @@ public class FileUtils {
}
/**
- * Implements the same behavior as the "touch" utility on Unix. It creates
- * a new file with size 0 or, if the file exists already, it is opened and
- * closed without modifying it, but updating the file date and time.
+ * Implements behavior similar to the Unix "touch" utility. Creates a new file with size 0, or, if the file exists, just
+ * updates the file's modified time.
* <p>
- * NOTE: As from v1.3, this method throws an IOException if the last
- * modified date of the file cannot be set. Also, as from v1.3 this method
- * creates parent directories if they do not exist.
+ * NOTE: As from v1.3, this method throws an IOException if the last modified date of the file cannot be set. Also, as
+ * from v1.3 this method creates parent directories if they do not exist.
* </p>
*
* @param file the File to touch.
* @throws NullPointerException if the parameter is {@code null}.
- * @throws IOException if setting the last-modified time failed or an I/O problem occurs.
+ * @throws IOException if setting the last-modified time failed or an I/O problem occurs.
*/
public static void touch(final File file) throws IOException {
- Objects.requireNonNull(file, "file");
- if (!file.exists()) {
- newOutputStream(file, false).close();
- }
- FileTimes.setLastModifiedTime(file.toPath());
+ PathUtils.touch(Objects.requireNonNull(file, "file").toPath());
}
/**
diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java b/src/main/java/org/apache/commons/io/file/PathUtils.java
index 2c56895a..be7e216b 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -71,6 +71,7 @@ import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.UncheckedIO;
import org.apache.commons.io.file.Counters.PathCounters;
+import org.apache.commons.io.file.attribute.FileTimes;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.function.IOFunction;
@@ -1533,6 +1534,26 @@ public final class PathUtils {
return fileVisitOptions == null ? EnumSet.noneOf(FileVisitOption.class) : Stream.of(fileVisitOptions).collect(Collectors.toSet());
}
+ /**
+ * Implements behavior similar to the Unix "touch" utility. Creates a new file with size 0, or, if the file exists, just
+ * updates the file's modified time.
+ *
+ * @param file the file to touch.
+ * @return The given file.
+ * @throws NullPointerException if the parameter is {@code null}.
+ * @throws IOException if setting the last-modified time failed or an I/O problem occurs.\
+ * @since 2.12.0
+ */
+ public static Path touch(final Path file) throws IOException {
+ Objects.requireNonNull(file, "file");
+ if (!Files.exists(file)) {
+ Files.createFile(file);
+ } else {
+ FileTimes.setLastModifiedTime(file);
+ }
+ return file;
+ }
+
/**
* Performs {@link Files#walkFileTree(Path,FileVisitor)} and returns the given visitor.
*
diff --git a/src/test/java/org/apache/commons/io/FileUtilsTest.java b/src/test/java/org/apache/commons/io/FileUtilsTest.java
index 2108582b..1d431c14 100644
--- a/src/test/java/org/apache/commons/io/FileUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/FileUtilsTest.java
@@ -2700,10 +2700,10 @@ public class FileUtilsTest extends AbstractTempDirTest {
assertFalse(file.exists(), "Bad test: test file still exists");
FileUtils.touch(file);
assertTrue(file.exists(), "FileUtils.touch() created file");
- final OutputStream out = Files.newOutputStream(file.toPath());
- assertEquals(0, file.length(), "Created empty file.");
- out.write(0);
- out.close();
+ try (final OutputStream out = Files.newOutputStream(file.toPath())) {
+ assertEquals(0, file.length(), "Created empty file.");
+ out.write(0);
+ }
assertEquals(1, file.length(), "Wrote one byte to file");
final long y2k = new GregorianCalendar(2000, 0, 1).getTime().getTime();
final boolean res = setLastModifiedMillis(file, y2k); // 0L fails on Win98
diff --git a/src/test/java/org/apache/commons/io/file/PathUtilsTest.java b/src/test/java/org/apache/commons/io/file/PathUtilsTest.java
index 6f53093f..bc76f7fd 100644
--- a/src/test/java/org/apache/commons/io/file/PathUtilsTest.java
+++ b/src/test/java/org/apache/commons/io/file/PathUtilsTest.java
@@ -20,7 +20,9 @@ package org.apache.commons.io.file;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
@@ -39,11 +41,14 @@ import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.DosFileAttributeView;
+import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFileAttributes;
+import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.test.TestUtils;
import org.apache.commons.lang3.ArrayUtils;
@@ -84,6 +89,10 @@ public class PathUtilsTest extends AbstractTempDirTest {
return symlinkDir;
}
+ private Long getLastModifiedMillis(final Path file) throws IOException {
+ return Files.getLastModifiedTime(file).toMillis();
+ }
+
private FileSystem openArchive(final Path p, final boolean createNew) throws IOException {
if (createNew) {
final Map<String, String> env = new HashMap<>();
@@ -95,6 +104,10 @@ public class PathUtilsTest extends AbstractTempDirTest {
return FileSystems.newFileSystem(p, (ClassLoader) null);
}
+ private void setLastModifiedMillis(final Path file, final long millis) throws IOException {
+ Files.setLastModifiedTime(file, FileTime.fromMillis(millis));
+ }
+
@Test
public void testCopyDirectoryForDifferentFilesystemsWithAbsolutePath() throws IOException {
final Path archivePath = Paths.get(TEST_JAR_PATH);
@@ -407,6 +420,32 @@ public class PathUtilsTest extends AbstractTempDirTest {
PathUtils.deleteFile(resolved);
}
+ @Test
+ public void testTouch() throws IOException {
+ assertThrows(NullPointerException.class, () -> FileUtils.touch(null));
+
+ final Path file = managedTempDirPath.resolve("touch.txt");
+ Files.deleteIfExists(file);
+ assertFalse(Files.exists(file), "Bad test: test file still exists");
+ PathUtils.touch(file);
+ assertTrue(Files.exists(file), "touch() created file");
+ try (final OutputStream out = Files.newOutputStream(file)) {
+ assertEquals(0, Files.size(file), "Created empty file.");
+ out.write(0);
+ }
+ assertEquals(1, Files.size(file), "Wrote one byte to file");
+ final long y2k = new GregorianCalendar(2000, 0, 1).getTime().getTime();
+ setLastModifiedMillis(file, y2k); // 0L fails on Win98
+ assertEquals(y2k, getLastModifiedMillis(file), "Bad test: set lastModified set incorrect value");
+ final long nowMillis = System.currentTimeMillis();
+ PathUtils.touch(file);
+ assertEquals(1, Files.size(file), "FileUtils.touch() didn't empty the file.");
+ assertNotEquals(y2k, getLastModifiedMillis(file), "FileUtils.touch() changed lastModified");
+ final int delta = 3000;
+ assertTrue(getLastModifiedMillis(file) >= nowMillis - delta, "FileUtils.touch() changed lastModified to more than now-3s");
+ assertTrue(getLastModifiedMillis(file) <= nowMillis + delta, "FileUtils.touch() changed lastModified to less than now+3s");
+ }
+
@Test
public void testWriteStringToFile1() throws Exception {
final Path file = tempDirPath.resolve("write.txt");