From 4e14f5fee6a68ee5fb56d07e70e86fcfcebdc7d3 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 10 Jul 2023 21:16:25 +0200 Subject: lib.path.subpath.components: init Co-authored-by: Robert Hensing --- lib/path/default.nix | 31 +++++++++++++++++++++++++++++++ lib/path/tests/unit.nix | 13 +++++++++++++ 2 files changed, 44 insertions(+) (limited to 'lib/path') diff --git a/lib/path/default.nix b/lib/path/default.nix index 936e9b03025..181124c179a 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -336,6 +336,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" + => + */ + 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 9c5b752cf64..fc5a84493ad 100644 --- a/lib/path/tests/unit.nix +++ b/lib/path/tests/unit.nix @@ -204,6 +204,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" -- cgit 1.4.1 From 407db583c54245136fe8e73976abadb7eb9fad80 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Thu, 20 Jul 2023 22:31:57 +0200 Subject: lib/path/README.md: Justify returning subpaths Co-authored-by: Valentin Gagarin --- lib/path/README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib/path') diff --git a/lib/path/README.md b/lib/path/README.md index 87e552d120d..89eec18b113 100644 --- a/lib/path/README.md +++ b/lib/path/README.md @@ -187,6 +187,27 @@ Decision: All functions remove trailing slashes in their results. +### 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. + +
+Arguments + +- (+) 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. +
+ ## Other implementations and references - [Rust](https://doc.rust-lang.org/std/path/struct.Path.html) -- cgit 1.4.1