diff options
author | Robert Hensing <roberth@users.noreply.github.com> | 2023-08-04 17:00:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-04 17:00:46 +0200 |
commit | 8fa169707fa055994fe60f194027629fee8e417a (patch) | |
tree | 22e7bdef086799cabf7409ad5ce10c1327cafca4 /lib/path | |
parent | 35184dd3a52239b91a1eea5e430fa35c32139161 (diff) | |
parent | 407db583c54245136fe8e73976abadb7eb9fad80 (diff) |
Merge pull request #242695 from tweag/lib.path.subpath.components
`lib.path.subpath.components`: init
Diffstat (limited to 'lib/path')
-rw-r--r-- | lib/path/README.md | 21 | ||||
-rw-r--r-- | lib/path/default.nix | 31 | ||||
-rw-r--r-- | lib/path/tests/unit.nix | 13 |
3 files changed, 65 insertions, 0 deletions
diff --git a/lib/path/README.md b/lib/path/README.md index 87e552d120d77..89eec18b11300 100644 --- a/lib/path/README.md +++ b/lib/path/README.md @@ -187,6 +187,27 @@ Decision: All functions remove trailing slashes in their results. </details> +### Prefer returning subpaths over components +[subpath-preference]: #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) diff --git a/lib/path/default.nix b/lib/path/default.nix index 24a7f85affc1d..5c6c5f6089545 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -438,6 +438,37 @@ in /* No rec! Add dependencies on this file at the top. */ { ${subpathInvalidReason path}'' ) 0 subpaths; + /* + Split [a subpath](#function-library-lib.path.subpath.isValid) 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](#function-library-lib.path.subpath.normalise). + + Laws: + + - Splitting a subpath into components and [joining](#function-library-lib.path.subpath.join) the components gives the same subpath but [normalised](#function-library-lib.path.subpath.normalise): + + subpath.join (subpath.components s) == subpath.normalise s + + Type: + subpath.components :: String -> [ String ] + + Example: + subpath.components "." + => [ ] + + subpath.components "./foo//bar/./baz/" + => [ "foo" "bar" "baz" ] + + subpath.components "/foo" + => <error> + */ + subpath.components = + subpath: + assert assertMsg (isValid subpath) '' + lib.path.subpath.components: Argument is not a valid subpath string: + ${subpathInvalidReason subpath}''; + splitRelPath subpath; + /* Normalise a subpath. Throw an error if the subpath isn't valid, see `lib.path.subpath.isValid` diff --git a/lib/path/tests/unit.nix b/lib/path/tests/unit.nix index 8bfb6f201219f..bad6560f13a98 100644 --- a/lib/path/tests/unit.nix +++ b/lib/path/tests/unit.nix @@ -238,6 +238,19 @@ let expr = (builtins.tryEval (subpath.normalise "..")).success; expected = false; }; + + testSubpathComponentsExample1 = { + expr = subpath.components "."; + expected = [ ]; + }; + testSubpathComponentsExample2 = { + expr = subpath.components "./foo//bar/./baz/"; + expected = [ "foo" "bar" "baz" ]; + }; + testSubpathComponentsExample3 = { + expr = (builtins.tryEval (subpath.components "/foo")).success; + expected = false; + }; }; in if cases == [] then "Unit tests successful" |