diff options
author | Robert Hensing <roberth@users.noreply.github.com> | 2023-07-27 11:05:48 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-27 11:05:48 +0200 |
commit | 399ac29381a5abc7bc17d41ff96f00b17716727c (patch) | |
tree | f067ddf7dfa90636d4cc114b326dd095b5ede0e3 /lib | |
parent | 6fbe34cb763925313bfd0a29ad3b900ba96f269c (diff) | |
parent | d7bf0d777a0edba5a6c87d59e9b7516c796fcd1f (diff) |
Merge pull request #244358 from tweag/lib.path.parts
`lib.path.splitRoot`: init
Diffstat (limited to 'lib')
-rw-r--r-- | lib/path/default.nix | 49 | ||||
-rw-r--r-- | lib/path/tests/unit.nix | 19 |
2 files changed, 67 insertions, 1 deletions
diff --git a/lib/path/default.nix b/lib/path/default.nix index 3a871bc05283c..24a7f85affc1d 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -271,8 +271,57 @@ in /* No rec! Add dependencies on this file at the top. */ { second argument: "${toString path2}" with root "${toString path2Deconstructed.root}"''; joinRelPath components; + /* + Split the filesystem root from a [path](https://nixos.org/manual/nix/stable/language/values.html#type-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](#function-library-lib.path.subpath.normalise) that when [appended](#function-library-lib.path.append) to `root` returns the original path. + + Laws: + - [Appending](#function-library-lib.path.append) the `root` and `subpath` gives the original path: + + p == + append + (splitRoot p).root + (splitRoot p).subpath + + - Trying to get the parent directory of `root` using [`readDir`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-readDir) returns `root` itself: + + dirOf (splitRoot p).root == (splitRoot p).root + + Type: + splitRoot :: Path -> { root :: Path, subpath :: String } + + 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> + */ + splitRoot = path: + assert assertMsg + (isPath path) + "lib.path.splitRoot: Argument is of type ${typeOf path}, but a path was expected"; + let + deconstructed = deconstructPath path; + in { + root = deconstructed.root; + subpath = joinRelPath deconstructed.components; + }; + /* 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 diff --git a/lib/path/tests/unit.nix b/lib/path/tests/unit.nix index 3e4b216f099ff..8bfb6f201219f 100644 --- a/lib/path/tests/unit.nix +++ b/lib/path/tests/unit.nix @@ -3,7 +3,7 @@ { libpath }: let lib = import libpath; - inherit (lib.path) hasPrefix removePrefix append subpath; + inherit (lib.path) hasPrefix removePrefix append splitRoot subpath; cases = lib.runTests { # Test examples from the lib.path.append documentation @@ -74,6 +74,23 @@ let expected = "./foo"; }; + testSplitRootExample1 = { + expr = splitRoot /foo/bar; + expected = { root = /.; subpath = "./foo/bar"; }; + }; + testSplitRootExample2 = { + expr = splitRoot /.; + expected = { root = /.; subpath = "./."; }; + }; + testSplitRootExample3 = { + expr = splitRoot /foo/../bar; + expected = { root = /.; subpath = "./bar"; }; + }; + testSplitRootExample4 = { + expr = (builtins.tryEval (splitRoot "/foo/bar")).success; + expected = false; + }; + # Test examples from the lib.path.subpath.isValid documentation testSubpathIsValidExample1 = { expr = subpath.isValid null; |