Home Explore Blog Models CI



nixpkgs

5th chunk of `lib/path/README.md`
226861673c91713e7fb577806b58a3dcef7969a8cb0daeae0000000100000e60
    - (+) Doesn't preserve them when returning individual [components](https://doc.rust-lang.org/std/path/struct.Path.html#method.components).
    - (+) Doesn't preserve them when [canonicalizing](https://doc.rust-lang.org/std/path/struct.Path.html#method.canonicalize).
  - (+) [Python 3's pathlib](https://docs.python.org/3/library/pathlib.html#module-pathlib) doesn't preserve them during [construction](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath).
    - Notably it represents the individual components as a list internally.
  - (-) [Haskell's filepath](https://hackage.haskell.org/package/filepath-1.4.100.0) has [explicit support](https://hackage.haskell.org/package/filepath-1.4.100.0/docs/System-FilePath.html#g:6) for handling trailing slashes.
    - (-) Does preserve them for [normalisation](https://hackage.haskell.org/package/filepath-1.4.100.0/docs/System-FilePath.html#v:normalise).
  - (-) [NodeJS's Path library](https://nodejs.org/api/path.html) preserves trailing slashes for [normalisation](https://nodejs.org/api/path.html#pathnormalizepath).
    - (+) For [parsing a path](https://nodejs.org/api/path.html#pathparsepath) into its significant elements, trailing slashes are not preserved.
- (+) Nix's builtin function `dirOf` gives an unexpected result for paths with trailing slashes: `dirOf "foo/bar/" == "foo/bar"`.
  Inconsistently, `baseNameOf` works correctly though: `baseNameOf "foo/bar/" == "bar"`.
  - (-) We are writing a path library to improve handling of paths though, so we shouldn't use these functions and discourage their use.
- (-) Unexpected result when normalising intermediate paths, like `relative.normalise ("foo" + "/") + "bar" == "foobar"`.
  - (+) This is not a practical use case though.
  - (+) Don't use `+` to append paths, this library has a `join` function for that.
    - (-) Users might use `+` out of habit though.
- (+) The `realpath` command also removes trailing slashes.
- (+) Even with a trailing slash, the path is the same, it's only an indication that it's a directory.

</details>

### Prefer returning subpaths over components

Observing: Functions could return subpaths or lists of path component strings.

Considering: Subpaths are used as inputs for some functions.
Using them for outputs, too, makes the library more consistent and composable.

Decision: Subpaths should be preferred over list of path component strings.

<details>
<summary>Arguments</summary>

- (+) It is consistent with functions accepting subpaths, making the library more composable
- (-) It is less efficient when the components are needed, because after creating the normalised subpath string, it will have to be parsed into components again
  - (+) If necessary, we can still make it faster by adding builtins to Nix
  - (+) Alternatively if necessary, versions of these functions that return components could later still be introduced.
- (+) It makes the path library simpler because there's only two types (paths and subpaths).
  Only `lib.path.subpath.components` can be used to get a list of components.
  And once we have a list of component strings, `lib.lists` and `lib.strings` can be used to operate on them.
  For completeness, `lib.path.subpath.join` allows converting the list of components back to a subpath.
</details>

## Other implementations and references

- [Rust](https://doc.rust-lang.org/std/path/struct.Path.html)
- [Python](https://docs.python.org/3/library/pathlib.html)
- [Haskell](https://hackage.haskell.org/package/filepath-1.4.100.0/docs/System-FilePath.html)
- [Nodejs](https://nodejs.org/api/path.html)
- [POSIX.1-2017](https://pubs.opengroup.org/onlinepubs/9699919799/nframe.html)

Title: Nix `lib.path` Design Decisions: Trailing Slashes and Subpath Return Types
Summary
This document outlines further design decisions for the Nix `lib.path` library. It reinforces the choice to remove trailing slashes from normalized paths, citing inconsistencies in Nix's `dirOf` and the behavior of `realpath`. It also advises against using string concatenation (`+`) for paths with trailing slashes, advocating for the library's `join` function instead. The second major decision is to prefer returning subpaths over lists of path component strings from functions. This promotes composability and consistency within the library, despite a potential minor efficiency trade-off. Users can still access components via `lib.path.subpath.components` if needed. The document also lists various other programming language path implementations and POSIX standards as references.