diff options
author | Valerij Fredriksen <valerijf@oath.com> | 2018-10-10 11:57:37 +0200 |
---|---|---|
committer | Valerij Fredriksen <valerijf@oath.com> | 2018-10-10 11:57:37 +0200 |
commit | 84960d571b4603cd420cb7ee57162509d2de73d5 (patch) | |
tree | d32dbba40a65170c406f94bd8471c5f7299a0e64 | |
parent | be2e16e9fad51a2a2442087c8df19ddd845d006d (diff) |
Move stuff to UnixPath
4 files changed, 71 insertions, 58 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinder.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinder.java index 57c643819dc..c92027a659b 100644 --- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinder.java +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinder.java @@ -20,8 +20,6 @@ import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Stream; -import static com.yahoo.vespa.hosted.node.admin.task.util.file.IOExceptionUtil.uncheck; - /** * Helper class to find and list or deleteRecursively files and directories. Follows the general syntax of command line * tool `find`. @@ -76,11 +74,15 @@ public class FileFinder { return this; } - /** Recursively deletes all matching elements */ - public int deleteRecursively() { - int[] numDeletions = { 0 }; // :( - forEach(attributes -> numDeletions[0] += deleteRecursively(attributes)); - return numDeletions[0]; + /** + * Recursively deletes all matching elements + * + * @return true iff anything was matched and deleted + */ + public boolean deleteRecursively() { + boolean[] deletedAnything = { false }; // :( + forEach(attributes -> deletedAnything[0] |= attributes.unixPath().deleteRecursively()); + return deletedAnything[0]; } public List<FileAttributes> list() { @@ -160,17 +162,6 @@ public class FileFinder { } } - private static int deleteRecursively(FileAttributes fileAttributes) { - int numDeletions = 0; - if (fileAttributes.isDirectory()) { - numDeletions = FileFinder.from(fileAttributes.path()) - .match(all()) - .deleteRecursively(); - } - - return numDeletions + (deleteIfExists(fileAttributes.path()) ? 1 : 0); - } - // Ideally, we would reuse the FileAttributes in this package, but unfortunately we only get // BasicFileAttributes and not PosixFileAttributes from FileVisitor @@ -184,6 +175,7 @@ public class FileFinder { } public Path path() { return path; } + public UnixPath unixPath() { return new UnixPath(path); } public String filename() { return path.getFileName().toString(); } public Instant lastModifiedTime() { return attributes.lastModifiedTime().toInstant(); } public boolean isRegularFile() { return attributes.isRegularFile(); } @@ -224,28 +216,4 @@ public class FileFinder { public static Predicate<FileAttributes> all() { return attrs -> true; } - - - // Other helpful methods that no not throw checked exceptions - public static boolean moveIfExists(Path from, Path to) { - try { - Files.move(from, to); - return true; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - public static boolean deleteIfExists(Path path) { - return uncheck(() -> Files.deleteIfExists(path)); - } - - public static Path createDirectories(Path path) { - return uncheck(() -> Files.createDirectories(path)); - } - - public static int deleteRecursively(Path path) { - return deleteRecursively( - new FileAttributes(path, uncheck(() -> Files.readAttributes(path, BasicFileAttributes.class)))); - } } diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java index 4baba9acb4e..ae5c6f57d4c 100644 --- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPath.java @@ -1,8 +1,11 @@ // Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.hosted.node.admin.task.util.file; +import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; @@ -15,8 +18,12 @@ import java.nio.file.attribute.PosixFilePermissions; import java.nio.file.attribute.UserPrincipal; import java.nio.file.attribute.UserPrincipalLookupService; import java.time.Instant; +import java.util.Collections; +import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.yahoo.vespa.hosted.node.admin.task.util.file.IOExceptionUtil.uncheck; @@ -128,6 +135,53 @@ public class UnixPath { uncheck(() -> Files.createDirectory(path)); } + public boolean isDirectory() { + return uncheck(() -> Files.isDirectory(path)); + } + + /** + * Similar to rm -rf file: + * - It's not an error if file doesn't exist + * - If file is a directory, it and all content is removed + * - For symlinks: Only the symlink is removed, not what the symlink points to + */ + public boolean deleteRecursively() { + if (isDirectory()) { + for (UnixPath path : listContentsOfDirectory()) { + path.deleteRecursively(); + } + } + + return deleteIfExists(); + } + + public boolean deleteIfExists() { + return uncheck(() -> Files.deleteIfExists(path)); + } + + public List<UnixPath> listContentsOfDirectory() { + try (Stream<Path> stream = Files.list(path)){ + return stream + .map(UnixPath::new) + .collect(Collectors.toList()); + } catch (NoSuchFileException ignored) { + return Collections.emptyList(); + } catch (IOException e) { + throw new RuntimeException("Failed to list contents of directory " + path.toAbsolutePath(), e); + } + } + + public boolean moveIfExists(Path to) { + try { + Files.move(path, to); + return true; + } catch (NoSuchFileException ignored) { + return false; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + @Override public String toString() { return path.toString(); diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinderTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinderTest.java index a9d47f743e5..ee13de20ee4 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinderTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/FileFinderTest.java @@ -108,13 +108,6 @@ public class FileFinderTest { assertTrue(Files.exists(testRoot())); } - @Test - public void everything() { - FileFinder.deleteRecursively(testRoot()); - - assertFalse(Files.exists(testRoot())); - } - @Before public void setup() throws IOException { Path root = testRoot(); diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java index 8d3d336a4ac..9b80b9a9ca2 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/file/UnixPathTest.java @@ -17,15 +17,15 @@ import static org.junit.Assert.assertTrue; * @author hakonhall */ public class UnixPathTest { - final FileSystem fileSystem = TestFileSystem.create(); + private final FileSystem fs = TestFileSystem.create(); @Test public void createParents() { - Path parentDirectory = fileSystem.getPath("/a/b/c"); + Path parentDirectory = fs.getPath("/a/b/c"); Path filePath = parentDirectory.resolve("bar"); UnixPath path = new UnixPath(filePath); - assertFalse(Files.exists(fileSystem.getPath("/a"))); + assertFalse(Files.exists(fs.getPath("/a"))); path.createParents(); assertTrue(Files.exists(parentDirectory)); } @@ -33,7 +33,7 @@ public class UnixPathTest { @Test public void utf8File() { String original = "foo\nbar\n"; - UnixPath path = new UnixPath(fileSystem.getPath("example.txt")); + UnixPath path = new UnixPath(fs.getPath("example.txt")); path.writeUtf8File(original); String fromFile = path.readUtf8File(); assertEquals(original, fromFile); @@ -42,7 +42,7 @@ public class UnixPathTest { @Test public void permissions() { String expectedPermissions = "rwxr-x---"; - UnixPath path = new UnixPath(fileSystem.getPath("file.txt")); + UnixPath path = new UnixPath(fs.getPath("file.txt")); path.writeUtf8File("foo"); path.setPermissions(expectedPermissions); assertEquals(expectedPermissions, path.getPermissions()); @@ -50,12 +50,11 @@ public class UnixPathTest { @Test(expected = IllegalArgumentException.class) public void badPermissionsString() { - new UnixPath(fileSystem.getPath("file.txt")).setPermissions("abcdefghi"); + new UnixPath(fs.getPath("file.txt")).setPermissions("abcdefghi"); } @Test public void owner() { - FileSystem fs = TestFileSystem.create(); Path path = fs.getPath("file.txt"); UnixPath unixPath = new UnixPath(path); unixPath.writeUtf8File("foo"); @@ -69,12 +68,11 @@ public class UnixPathTest { @Test public void createDirectoryWithPermissions() { - FileSystem fs = TestFileSystem.create(); Path path = fs.getPath("dir"); UnixPath unixPath = new UnixPath(path); String permissions = "rwxr-xr--"; unixPath.createDirectory(permissions); - assertTrue(Files.isDirectory(path)); + assertTrue(unixPath.isDirectory()); assertEquals(permissions, unixPath.getPermissions()); } } |