google/jimfs

Unexpected behaviour of Path.resolve where other path does not yet exist

cmayne-r7 opened this issue · 4 comments

Is this expected behaviour? Similar behaviour on real filesystems are able to invoke Path.resolve(otherPath), where otherPath does not exist.

final FileSystem posixCompliantFs = Jimfs.newFileSystem(Configuration.unix().toBuilder().setAttributeViews("posix").build());
final Path rootPath = Files.createFile(posixCompliantFs.getPath("/root-path"));
final Path relativePath = Files.createFile(rootPath.resolve("x"));
java.nio.file.NoSuchFileException: /root-path/x
    at com.google.common.jimfs.FileTree.lookUp(FileTree.java:91)
    at com.google.common.jimfs.JimfsFileStore.lookUp(JimfsFileStore.java:138)
    at com.google.common.jimfs.FileSystemView.lookUp(FileSystemView.java:123)
    at com.google.common.jimfs.FileSystemView.createFile(FileSystemView.java:270)
    at com.google.common.jimfs.FileSystemView.getOrCreateRegularFileWithWriteLock(FileSystemView.java:349)
    at com.google.common.jimfs.FileSystemView.getOrCreateRegularFile(FileSystemView.java:312)
    at com.google.common.jimfs.JimfsFileSystemProvider.newJimfsFileChannel(JimfsFileSystemProvider.java:232)
    at com.google.common.jimfs.JimfsFileSystemProvider.newByteChannel(JimfsFileSystemProvider.java:240)
    at java.nio.file.Files.newByteChannel(Files.java:361)
    at java.nio.file.Files.createFile(Files.java:632)

Sorry, was being a numbskull. Obviously a file can't be resolved under a file...
final Path rootPath = Files.createFile(posixCompliantFs.getPath("/root-path"));
Should have been
final Path rootPath = Files.createDirectory(posixCompliantFs.getPath("/root-path"));

Just to point this out: the issue you were seeing was not with Path.resolve, but rather with Files.createFile. You can see that from the stack trace, which stems from Files.createFile. The Path.resolve call has already succeeded at that point.

Path.resolve doesn't look at what files do or don't exist on the file system at all... it basically just takes the other path and appends it to the first path (with various subtleties and exceptions, such as when the other path is absolute rather than relative).

Yeah, that all qualifies. I was having an off day...

Looking at this again though, as a completely separate issue, I think the exception message could be a little clearer. The exception, I'm assuming, is caused by the fact that the file /root-path/x can't be created as /root-path is a file, not a directory, so the message java.nio.file.NoSuchFileException: /root-path/x is a little misleading?

That error message is a product of the way Files.createFile works, and actually matches the error message you'd get on Linux or OS X. I agree that it's not great though.

Details: Files.createFile works by opening a channel to the file with the CREATE_NEW option (this isn't something the implementation of the file system can change), and what happens when you try to open a channel to /root-path/x when /root-path doesn't exist is that it reports to you that /root-path/x doesn't exist. Basically, the error message you get if you try to create a file in that situation has to be the same error message you'd get if you tried to read or write that file, because of the way Files.createFile is implemented.