MoreFiles.copyRecursive loops infinitely until failure when copying a directory into one of its subdirectories
Closed this issue · 3 comments
Repro:
Path a = Paths.get("a") // a is an existing directory with contents
Path b = Paths.get("a/b") // b does not exist in a
MoreFiles.copyRecursive(a, b)
This loops infinitely until failure because the copy generates more content to copy. It also passes both precondition checks in MoreFiles.copyRecursive because "a/b" does not exist AND "a" does exist.
This is the exception when run locally on linux:
Exception in thread "main" java.nio.file.FileSystemException: /home/gaspardvk/tmp/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob/bob: File name too long
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:383)
at java.nio.file.Files.createDirectory(Files.java:628)
at com.palantir.giraffe.file.MoreFiles$CopyVisitor.preVisitDirectory(MoreFiles.java:304)
at com.palantir.giraffe.file.MoreFiles$CopyVisitor.preVisitDirectory(MoreFiles.java:286)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:192)
at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199)
[...]
Any idea what cp -R a a/b
does in this case? I'm curious if this is only a problem with the visitor implementation or if this should be check for all implementations.
cp -R a a/b
returns an error: cannot copy a directory, "a", into itself, "a/b"
Looks like we should implement the same check for the file tree version.