lib.path: path functions
Functions for working with path values.
lib.path.append
Type: append :: Path -> String -> Path
Append a subpath string to a path.
Like path + ("/" + string)
but safer, because it errors instead of returning potentially surprising results.
More specifically, it checks that the first argument is a path value type,
and that the second argument is a valid subpath string.
Laws:
-
Not influenced by subpath normalisation:
append p s == append p (subpath.normalise s)
path
: The absolute path to append to
subpath
: The subpath string to append
Example
lib.path.append
usage example
append /foo "bar/baz"
=> /foo/bar/baz "subpaths don't need to be normalised
append /foo "./bar//baz/./"
=> /foo/bar/baz "can append to root directory
append /. "foo/bar"
=> /foo/bar "first argument needs to be a path value type
append "/foo" "bar"
=> <error> "second argument needs to be a valid subpath string
append /foo /bar
=> <error>
append /foo ""
=> <error>
append /foo "/bar"
=> <error>
append /foo "../bar"
=> <error>
Located at lib/path/default.nix:192 in <nixpkgs>
.
lib.path.hasPrefix
Type: hasPrefix :: Path -> Path -> Bool
Whether the first path is a component-wise prefix of the second path.
Laws:
-
hasPrefix p q
is only true ifq == append p s
for some subpaths
. -
hasPrefix
is a non-strict partial order over the set of all path values.
path1
: Function argument
Example
lib.path.hasPrefix
usage example
hasPrefix /foo /foo/bar
=> true
hasPrefix /foo /foo
=> true
hasPrefix /foo/bar /foo
=> false
hasPrefix /. /foo
=> true
Located at lib/path/default.nix:226 in <nixpkgs>
.
lib.path.removePrefix
Type: removePrefix :: Path -> Path -> String
Remove the first path as a component-wise prefix from the second path. The result is a normalised subpath string.
Laws:
-
Inverts
append
for normalised subpath string:removePrefix p (append p s) == subpath.normalise s
path1
: Function argument
Example
lib.path.removePrefix
usage example
removePrefix /foo /foo/bar/baz
=> "./bar/baz"
removePrefix /foo /foo
=> "./."
removePrefix /foo/bar /foo
=> <error>
removePrefix /. /foo
=> "./foo"
Located at lib/path/default.nix:271 in <nixpkgs>
.
lib.path.splitRoot
Type: splitRoot :: Path -> { root :: Path, subpath :: String }
Split the filesystem root from a path.
The result is an attribute set with these attributes:
- root
: The filesystem root of the path, meaning that this directory has no parent directory.
- subpath
: The normalised subpath string that when appended to root
returns the original path.
Laws:
- Appending the root
and subpath
gives the original path:
p ==
append
(splitRoot p).root
(splitRoot p).subpath
-
Trying to get the parent directory of
root
usingreadDir
returnsroot
itself:dirOf (splitRoot p).root == (splitRoot p).root
path
: The path to split the root off of
Example
lib.path.splitRoot
usage example
splitRoot /foo/bar
=> { root = /.; subpath = "./foo/bar"; }
splitRoot /.
=> { root = /.; subpath = "./."; } "Nix neutralises `..` path components for all path values automatically
splitRoot /foo/../bar
=> { root = /.; subpath = "./bar"; }
splitRoot "/foo/bar"
=> <error>
Located at lib/path/default.nix:336 in <nixpkgs>
.
lib.path.hasStorePathPrefix
Type: hasStorePathPrefix :: Path -> Bool
Whether a path has a store path as a prefix.
Note
As with all functions of this lib.path
library, it does not work on paths in strings,
which is how you'd typically get store paths.
Instead, this function only handles path values themselves, which occur when Nix files in the store use relative path expressions.
path
: Function argument
Example
lib.path.hasStorePathPrefix
usage example
# Subpaths of derivation outputs have a store path as a prefix
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo/bar/baz
=> true "The store directory itself is not a store path
hasStorePathPrefix /nix/store
=> false "Derivation outputs are store paths themselves
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo
=> true "Paths outside the Nix store don't have a store path prefix
hasStorePathPrefix /home/user
=> false "Not all paths under the Nix store are store paths
hasStorePathPrefix /nix/store/.links/10gg8k3rmbw8p7gszarbk7qyd9jwxhcfq9i6s5i0qikx8alkk4hq
=> false "Store derivations are also store paths themselves
hasStorePathPrefix /nix/store/nvl9ic0pj1fpyln3zaqrf4cclbqdfn1j-foo.drv
=> true
Located at lib/path/default.nix:390 in <nixpkgs>
.
lib.path.subpath.isValid
Type: subpath.isValid :: String -> Bool
Whether a value is a valid subpath string.
A subpath string points to a specific file or directory within an absolute base directory.
It is a stricter form of a relative path that excludes ..
components, since those could escape the base directory.
-
The value is a string.
-
The string is not empty.
-
The string doesn't start with a
/
. -
The string doesn't contain any
..
path components.
value
: The value to check
Example
lib.path.subpath.isValid
usage example
# Not a string
subpath.isValid null
=> false "Empty string
subpath.isValid ""
=> false "Absolute path
subpath.isValid "/foo"
=> false "Contains a `..` path component
subpath.isValid "../foo"
=> false "Valid subpath
subpath.isValid "foo/bar"
=> true "Doesn't need to be normalised
subpath.isValid "./foo//bar/"
=> true
Located at lib/path/default.nix:447 in <nixpkgs>
.
lib.path.subpath.join
Type: subpath.join :: [ String ] -> String
Join subpath strings together using /
, returning a normalised subpath string.
Like concatStringsSep "/"
but safer, specifically:
-
All elements must be valid subpath strings.
-
The result gets normalised.
-
The edge case of an empty list gets properly handled by returning the neutral subpath
"./."
.
Laws:
-
Associativity:
subpath.join [ x (subpath.join [ y z ]) ] == subpath.join [ (subpath.join [ x y ]) z ]
-
Identity -
"./."
is the neutral element for normalised paths:subpath.join [ ] == "./." subpath.join [ (subpath.normalise p) "./." ] == subpath.normalise p subpath.join [ "./." (subpath.normalise p) ] == subpath.normalise p
-
Normalisation - the result is normalised:
subpath.join ps == subpath.normalise (subpath.join ps)
-
For non-empty lists, the implementation is equivalent to normalising the result of
concatStringsSep "/"
. Note that the above laws can be derived from this one:ps != [] -> subpath.join ps == subpath.normalise (concatStringsSep "/" ps)
subpaths
: The list of subpaths to join together
Example
lib.path.subpath.join
usage example
subpath.join [ "foo" "bar/baz" ]
=> "./foo/bar/baz" "normalise the result
subpath.join [ "./foo" "." "bar//./baz/" ]
=> "./foo/bar/baz" "passing an empty list results in the current directory
subpath.join [ ]
=> "./." "elements must be valid subpath strings
subpath.join [ /foo ]
=> <error>
subpath.join [ "" ]
=> <error>
subpath.join [ "/foo" ]
=> <error>
subpath.join [ "../foo" ]
=> <error>
Located at lib/path/default.nix:510 in <nixpkgs>
.
lib.path.subpath.components
Type: subpath.components :: String -> [ String ]
Split a subpath into its path component strings. Throw an error if the subpath isn't valid. Note that the returned path components are also valid subpath strings, though they are intentionally not normalised.
Laws:
-
Splitting a subpath into components and joining the components gives the same subpath but normalised:
subpath.join (subpath.components s) == subpath.normalise s
subpath
: The subpath string to split into components
Example
lib.path.subpath.components
usage example
subpath.components "."
=> [ ]
subpath.components "./foo//bar/./baz/"
=> [ "foo" "bar" "baz" ]
subpath.components "/foo"
=> <error>
Located at lib/path/default.nix:552 in <nixpkgs>
.
lib.path.subpath.normalise
Type: subpath.normalise :: String -> String
Normalise a subpath. Throw an error if the subpath isn't valid.
-
Limit repeating
/
to a single one. -
Remove redundant
.
components. -
Remove trailing
/
and/.
. -
Add leading
./
.
Laws:
-
Idempotency - normalising multiple times gives the same result:
subpath.normalise (subpath.normalise p) == subpath.normalise p
-
Uniqueness - there's only a single normalisation for the paths that lead to the same file system node:
subpath.normalise p != subpath.normalise q -> $(realpath ${p}) != $(realpath ${q})
-
Don't change the result when appended to a Nix path value:
append base p == append base (subpath.normalise p)
-
Don't change the path according to
realpath
:$(realpath ${p}) == $(realpath ${subpath.normalise p})
-
Only error on invalid subpaths:
builtins.tryEval (subpath.normalise p)).success == subpath.isValid p
subpath
: The subpath string to normalise
Example
lib.path.subpath.normalise
usage example
# limit repeating `/` to a single one
subpath.normalise "foo//bar"
=> "./foo/bar" "remove redundant `.` components
subpath.normalise "foo/./bar"
=> "./foo/bar" "add leading `./`
subpath.normalise "foo/bar"
=> "./foo/bar" "remove trailing `/`
subpath.normalise "foo/bar/"
=> "./foo/bar" "remove trailing `/.`
subpath.normalise "foo/bar/."
=> "./foo/bar" "Return the current directory as `./.`
subpath.normalise "."
=> "./." "error on `..` path components
subpath.normalise "foo/../bar"
=> <error> "error on empty string
subpath.normalise ""
=> <error> "error on absolute path
subpath.normalise "/foo"
=> <error>
Located at lib/path/default.nix:633 in <nixpkgs>
.