PathKit icon indicating copy to clipboard operation
PathKit copied to clipboard

Behavior of joining paths starting with "/" is unnatural

Open kenjitayama opened this issue 8 years ago • 4 comments

I think the following joining behavior is unnatural.

let path = Path("/usr/bin") + Path("/swift") // becomes "/swift" instead of "/usr/bin/swift"

Implemented here: https://github.com/kylef/PathKit/blob/62dca49ee33b16f209b9f2074d109e0a7191ae9e/Sources/PathKit.swift#L668

I think it is common to build paths with, left hand side not ending with "/" and right handing side starting with "/".

kenjitayama avatar Mar 22 '16 11:03 kenjitayama

I disagree that this is unnatural, it's actually consistent with many other languages and join implementations. It's exactly how I'd expect it to work.

Could you perhaps explain your use-case a bit more so we can try and find a different solution? Why would your right hand have a slash in it already?

A cross-platform solution would look more like:

let root = Path(Path.separator)
let usrBin = (root + "usr") + "bin"
let swift = usrBin + "swift"

If you're supporting multiple platforms, you cannot rely on the fact that / is the separator, it could be something else such as \. The whole point around this API is to join paths without hard-coding "/" as a string everywhere.

Python

https://docs.python.org/3.5/library/os.path.html#os.path.join

If a component is an absolute path, all previous components are thrown away and joining continues from the absolute path component.

>>> from os import path
>>> path.join("/usr/local", "/swift")
'/swift'

Ruby

Can't find a statement in the documentation, but you can see the behaviour is the same:

> Pathname.new('/usr/bin').join('/swift')
=> #<Pathname:/swift>

Cocoa (NSURL)

Again, I can't find a part of the documentation, but here is the behaviour.

NSURL(fileURLWithPath: "/swift", relativeToURL:NSURL(fileURLWithPath: "/usr/bin"))
// --> file:///swift

kylef avatar Mar 22 '16 15:03 kylef

Thank you for explaining in detail. I see you're pretty right that it's consistent and natural.

I had one counter example in mind.

let basePath = NSURL(fileURLWithPath: "/base/path")
let path = basePath.URLByAppendingPathComponent("/some/path")
// --> file:///base/path/some/path

Anyways, my use case is… I have some generated swift code that I can't control, and has let path = "/some/path" in it. And I need to concatinate it to a let basePath = Path("/base/path"). With the current implementation, I need to String(path.characters.dropFirst()) before concatination. These paths are acutually part of a URL, so I don't need to worry about path separators.

Would you say this is not a use case for PathKit, or am I missing a better approach using PathKit?

Thanks in advance for advice.

kenjitayama avatar Mar 22 '16 16:03 kenjitayama

I found this behaviour in Ruby.

base_path = "/base/path"
path = "/some/path"
result_path = File.join(base_path, path) // => /base/path/some/path

I think, at least there are some demands for this style of concatination.

kenjitayama avatar Mar 24 '16 01:03 kenjitayama

Boy, I don't want to see debate about this when Apple or somebody brings Swift to Windows... (slash and backslash works both, drives' letters etc.)

rbukovansky avatar Oct 11 '16 09:10 rbukovansky