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 186e999 [IO-701] Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186. 186e999 is described below commit 186e999374f0ff249b37d75100f05b7c7acb14b7 Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Thu Jan 14 19:49:26 2021 -0500 [IO-701] Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186. Clean ups post PR merge. --- src/changes/changes.xml | 3 + src/main/java/org/apache/commons/io/FileUtils.java | 2 +- .../java/org/apache/commons/io/file/PathUtils.java | 16 +-- .../io/FileUtilsDeleteDirectoryBaseTestCase.java | 123 ++++++++++----------- .../io/FileUtilsDeleteDirectoryLinuxTestCase.java | 94 ++++++++-------- .../io/FileUtilsDeleteDirectoryWinTestCase.java | 43 +++---- 6 files changed, 141 insertions(+), 140 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ba34b86..8fad977 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -90,6 +90,9 @@ The <action> type attribute can be add,update,fix,remove. <action issue="IO-688" dev="ggregory" type="fix" due-to="Michael Ernst, Gary Gregory"> CopyUtils deprecation message gives wrong version. </action> + <action issue="IO-701" dev="ggregory" type="fix" due-to="Gary Gregory"> + Make PathUtils.setReadOnly deal with LinuxDosFileAttributeView #186. + </action> <!-- ADD --> <action dev="ggregory" type="add" due-to="Gary Gregory"> Add FileSystemProviders class. diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java index 7df6290..4aa0756 100644 --- a/src/main/java/org/apache/commons/io/FileUtils.java +++ b/src/main/java/org/apache/commons/io/FileUtils.java @@ -1167,7 +1167,7 @@ public class FileUtils { */ public static File delete(final File file) throws IOException { Objects.requireNonNull(file, "file"); - java.nio.file.Files.delete(file.toPath()); + Files.delete(file.toPath()); return file; } 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 9cb1ec1..06474b2 100644 --- a/src/main/java/org/apache/commons/io/file/PathUtils.java +++ b/src/main/java/org/apache/commons/io/file/PathUtils.java @@ -870,21 +870,21 @@ public final class PathUtils { * @since 2.8.0 */ public static Path setReadOnly(final Path path, final boolean readOnly, final LinkOption... linkOptions) - throws IOException { + throws IOException { final List<Exception> causeList = new ArrayList<>(2); final DosFileAttributeView fileAttributeView = Files.getFileAttributeView(path, DosFileAttributeView.class, - linkOptions); + linkOptions); if (fileAttributeView != null) { try { fileAttributeView.setReadOnly(readOnly); return path; } catch (IOException e) { - //ignore for now, retry with PosixFileAttributeView + // ignore for now, retry with PosixFileAttributeView causeList.add(e); } } final PosixFileAttributeView posixFileAttributeView = Files.getFileAttributeView(path, - PosixFileAttributeView.class, linkOptions); + PosixFileAttributeView.class, linkOptions); if (posixFileAttributeView != null) { // Works on Windows but not on Ubuntu: // Files.setAttribute(path, "unix:readonly", readOnly, options); @@ -895,17 +895,17 @@ public final class PathUtils { permissions.remove(PosixFilePermission.GROUP_WRITE); permissions.remove(PosixFilePermission.OTHERS_WRITE); try { - return Files.setPosixFilePermissions(path, permissions); + return Files.setPosixFilePermissions(path, permissions); } catch (IOException e) { causeList.add(e); } } if (!causeList.isEmpty()) { - throw new IOExceptionList(causeList); + throw new IOExceptionList(causeList); } throw new IOException( - String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path, - Arrays.toString(linkOptions))); + String.format("No DosFileAttributeView or PosixFileAttributeView for '%s' (linkOptions=%s)", path, + Arrays.toString(linkOptions))); } /** diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java index 3aacbe8..b99c1dd 100644 --- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java +++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryBaseTestCase.java @@ -22,8 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.nio.file.Files; -import java.nio.file.attribute.FileAttribute; - import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -35,72 +33,41 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase { @TempDir public File top; - // ----------------------------------------------------------------------- - - @Test - public void testDeletesRegular() throws Exception { - final File nested = new File(top, "nested"); - assertTrue(nested.mkdirs()); - - assertEquals(1, top.list().length); - - assertEquals(0, nested.list().length); - - FileUtils.deleteDirectory(nested); - - assertEquals(0, top.list().length); - } + protected abstract boolean setupSymlink(final File res, final File link) throws Exception; @Test - public void testDeletesNested() throws Exception { - final File nested = new File(top, "nested"); - assertTrue(nested.mkdirs()); - - assertEquals(1, top.list().length); - - FileUtils.touch(new File(nested, "regular")); - FileUtils.touch(new File(nested, ".hidden")); - - assertEquals(2, nested.list().length); - - FileUtils.deleteDirectory(nested); - - assertEquals(0, top.list().length); - } + public void testDeleteDirWithASymlinkDir() throws Exception { - @Test - public void testDeleteDirWithSymlinkFile() throws Exception { final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); - final File realFile = new File(realInner, "file1"); - FileUtils.touch(realFile); - + FileUtils.touch(new File(realInner, "file1")); assertEquals(1, realInner.list().length); - final File randomFile = new File(top, "randomfile"); - FileUtils.touch(randomFile); + final File randomDirectory = new File(top, "randomDir"); + assertTrue(randomDirectory.mkdirs()); - final File symlinkFile = new File(realInner, "fakeinner"); - assertTrue(setupSymlink(randomFile, symlinkFile)); + FileUtils.touch(new File(randomDirectory, "randomfile")); + assertEquals(1, randomDirectory.list().length); - assertEquals(2, realInner.list().length); - assertEquals(2, top.list().length); + final File symlinkDirectory = new File(realOuter, "fakeinner"); + assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); - // assert the real directory were removed including the symlink + assertEquals(1, symlinkDirectory.list().length); + + // assert contents of the real directory were removed including the symlink FileUtils.deleteDirectory(realOuter); assertEquals(1, top.list().length); // ensure that the contents of the symlink were NOT removed. - assertTrue(randomFile.exists()); - assertFalse(symlinkFile.exists()); + assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } @Test - public void testDeleteDirWithASymlinkDir() throws Exception { + public void testDeleteDirWithASymlinkDir2() throws Exception { final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); @@ -118,7 +85,7 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase { assertEquals(1, randomDirectory.list().length); final File symlinkDirectory = new File(realOuter, "fakeinner"); - assertTrue(setupSymlink(randomDirectory, symlinkDirectory)); + Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath()); assertEquals(1, symlinkDirectory.list().length); @@ -131,36 +98,36 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase { } @Test - public void testDeleteDirWithASymlinkDir2() throws Exception { - + public void testDeleteDirWithSymlinkFile() throws Exception { final File realOuter = new File(top, "realouter"); assertTrue(realOuter.mkdirs()); final File realInner = new File(realOuter, "realinner"); assertTrue(realInner.mkdirs()); - FileUtils.touch(new File(realInner, "file1")); - assertEquals(1, realInner.list().length); + final File realFile = new File(realInner, "file1"); + FileUtils.touch(realFile); - final File randomDirectory = new File(top, "randomDir"); - assertTrue(randomDirectory.mkdirs()); + assertEquals(1, realInner.list().length); - FileUtils.touch(new File(randomDirectory, "randomfile")); - assertEquals(1, randomDirectory.list().length); + final File randomFile = new File(top, "randomfile"); + FileUtils.touch(randomFile); - final File symlinkDirectory = new File(realOuter, "fakeinner"); - Files.createSymbolicLink(symlinkDirectory.toPath(), randomDirectory.toPath()); + final File symlinkFile = new File(realInner, "fakeinner"); + assertTrue(setupSymlink(randomFile, symlinkFile)); - assertEquals(1, symlinkDirectory.list().length); + assertEquals(2, realInner.list().length); + assertEquals(2, top.list().length); - // assert contents of the real directory were removed including the symlink + // assert the real directory were removed including the symlink FileUtils.deleteDirectory(realOuter); assertEquals(1, top.list().length); // ensure that the contents of the symlink were NOT removed. - assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); + assertTrue(randomFile.exists()); + assertFalse(symlinkFile.exists()); } - + @Test public void testDeleteParentSymlink() throws Exception { final File realParent = new File(top, "realparent"); @@ -227,7 +194,35 @@ public abstract class FileUtilsDeleteDirectoryBaseTestCase { assertEquals(1, randomDirectory.list().length, "Contents of sym link should not have been removed"); } - protected abstract boolean setupSymlink(final File res, final File link) throws Exception; + @Test + public void testDeletesNested() throws Exception { + final File nested = new File(top, "nested"); + assertTrue(nested.mkdirs()); -} + assertEquals(1, top.list().length); + FileUtils.touch(new File(nested, "regular")); + FileUtils.touch(new File(nested, ".hidden")); + + assertEquals(2, nested.list().length); + + FileUtils.deleteDirectory(nested); + + assertEquals(0, top.list().length); + } + + @Test + public void testDeletesRegular() throws Exception { + final File nested = new File(top, "nested"); + assertTrue(nested.mkdirs()); + + assertEquals(1, top.list().length); + + assertEquals(0, nested.list().length); + + FileUtils.deleteDirectory(nested); + + assertEquals(0, top.list().length); + } + +} diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java index ad54483..22857b9 100644 --- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java +++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryLinuxTestCase.java @@ -33,27 +33,42 @@ import org.junit.jupiter.api.condition.OS; @DisabledOnOs(OS.WINDOWS) public class FileUtilsDeleteDirectoryLinuxTestCase extends FileUtilsDeleteDirectoryBaseTestCase { - @Test - public void testThrowsOnNullList() throws Exception { - final File nested = new File(top, "nested"); - assertTrue(nested.mkdirs()); + /** Only runs on Linux. */ + private boolean chmod(final File file, final int mode, final boolean recurse) throws InterruptedException { + final List<String> args = new ArrayList<>(); + args.add("chmod"); - // test wont work if we can't restrict permissions on the - // directory, so skip it. - assumeTrue(chmod(nested, 0, false)); + if (recurse) { + args.add("-R"); + } + + args.add(Integer.toString(mode)); + args.add(file.getAbsolutePath()); + + final Process proc; try { - // cleanDirectory calls forceDelete - FileUtils.deleteDirectory(nested); - fail("expected IOException"); + proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); } catch (final IOException e) { - assertEquals("Unknown I/O error listing contents of directory: " + nested.getAbsolutePath(), - e.getMessage()); - } finally { - chmod(nested, 755, false); - FileUtils.deleteDirectory(nested); + return false; } - assertEquals(0, top.list().length); + return proc.waitFor() == 0; + } + + @Override + protected boolean setupSymlink(final File res, final File link) throws Exception { + // create symlink + final List<String> args = new ArrayList<>(); + args.add("ln"); + args.add("-s"); + + args.add(res.getAbsolutePath()); + args.add(link.getAbsolutePath()); + + final Process proc; + + proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); + return proc.waitFor() == 0; } @Test @@ -80,41 +95,26 @@ public class FileUtilsDeleteDirectoryLinuxTestCase extends FileUtilsDeleteDirect assertEquals(0, top.list().length); } - @Override - protected boolean setupSymlink(File res, File link) throws Exception { - // create symlink - final List<String> args = new ArrayList<>(); - args.add("ln"); - args.add("-s"); - - args.add(res.getAbsolutePath()); - args.add(link.getAbsolutePath()); - - final Process proc; - - proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); - return proc.waitFor() == 0; - } - - /** Only runs on Linux. */ - private boolean chmod(final File file, final int mode, final boolean recurse) throws InterruptedException { - final List<String> args = new ArrayList<>(); - args.add("chmod"); - - if (recurse) { - args.add("-R"); - } - - args.add(Integer.toString(mode)); - args.add(file.getAbsolutePath()); + @Test + public void testThrowsOnNullList() throws Exception { + final File nested = new File(top, "nested"); + assertTrue(nested.mkdirs()); - final Process proc; + // test wont work if we can't restrict permissions on the + // directory, so skip it. + assumeTrue(chmod(nested, 0, false)); try { - proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); + // cleanDirectory calls forceDelete + FileUtils.deleteDirectory(nested); + fail("expected IOException"); } catch (final IOException e) { - return false; + assertEquals("Unknown I/O error listing contents of directory: " + nested.getAbsolutePath(), + e.getMessage()); + } finally { + chmod(nested, 755, false); + FileUtils.deleteDirectory(nested); } - return proc.waitFor() == 0; + assertEquals(0, top.list().length); } } diff --git a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java index 4ed4eda..5ae3171 100644 --- a/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java +++ b/src/test/java/org/apache/commons/io/FileUtilsDeleteDirectoryWinTestCase.java @@ -17,6 +17,8 @@ package org.apache.commons.io; import java.io.File; +import java.io.InputStream; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @@ -26,25 +28,26 @@ import org.junit.jupiter.api.condition.OS; @EnabledOnOs(OS.WINDOWS) public class FileUtilsDeleteDirectoryWinTestCase extends FileUtilsDeleteDirectoryBaseTestCase { - @Override - protected boolean setupSymlink(File res, File link) throws Exception { - // create symlink - final List<String> args = new ArrayList<>(); - args.add("cmd"); - args.add("/C"); - args.add("mklink"); - - if (res.isDirectory()) { - args.add("/D"); - } - - args.add(link.getAbsolutePath()); - args.add(res.getAbsolutePath()); - - final Process proc; - - proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); - return proc.waitFor() == 0; - } + @Override + protected boolean setupSymlink(final File res, final File link) throws Exception { + // create symlink + final List<String> args = new ArrayList<>(); + args.add("cmd"); + args.add("/C"); + args.add("mklink"); + + if (res.isDirectory()) { + args.add("/D"); + } + + args.add(link.getAbsolutePath()); + args.add(res.getAbsolutePath()); + + final Process proc = Runtime.getRuntime().exec(args.toArray(new String[args.size()])); + final InputStream errorStream = proc.getErrorStream(); + final int rc = proc.waitFor(); + System.err.println(IOUtils.toString(errorStream, Charset.defaultCharset())); + return rc == 0; + } }