From 5c4f6161981917504c50b84864dcfd2f67dc037d Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Wed, 18 Jan 2023 18:06:21 +0100 Subject: lib.path: Minor improvements - Use isValid when possible instead of subpathInvalidReason: https://github.com/NixOS/nixpkgs/pull/209099#discussion_r1068714681 - Add documentation to function arguments - Use newlines for error messages: https://github.com/NixOS/nixpkgs/pull/208887#discussion_r1069737602 - Add short comments for the unit test groups: https://github.com/NixOS/nixpkgs/pull/208887#discussion_r1072913051 - Slight formatting improvement for laws: https://github.com/NixOS/nixpkgs/pull/209099#discussion_r1068707955 --- lib/path/default.nix | 23 ++++++++++++++++------- lib/path/tests/unit.nix | 4 ++++ 2 files changed, 20 insertions(+), 7 deletions(-) (limited to 'lib/path') diff --git a/lib/path/default.nix b/lib/path/default.nix index 96a9244407b..6fa7c1dd641 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -25,6 +25,10 @@ let assertMsg ; + inherit (lib.path.subpath) + isValid + ; + # Return the reason why a subpath is invalid, or `null` if it's valid subpathInvalidReason = value: if ! isString value then @@ -133,7 +137,9 @@ in /* No rec! Add dependencies on this file at the top. */ { subpath.isValid "./foo//bar/" => true */ - subpath.isValid = value: + subpath.isValid = + # The value to check + value: subpathInvalidReason value == null; @@ -150,11 +156,11 @@ in /* No rec! Add dependencies on this file at the top. */ { Laws: - - (Idempotency) Normalising multiple times gives the same result: + - 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: + - 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}) @@ -210,9 +216,12 @@ in /* No rec! Add dependencies on this file at the top. */ { subpath.normalise "/foo" => */ - subpath.normalise = path: - assert assertMsg (subpathInvalidReason path == null) - "lib.path.subpath.normalise: Argument is not a valid subpath string: ${subpathInvalidReason path}"; - joinRelPath (splitRelPath path); + subpath.normalise = + # The subpath string to normalise + subpath: + assert assertMsg (isValid subpath) '' + lib.path.subpath.normalise: Argument is not a valid subpath string: + ${subpathInvalidReason subpath}''; + joinRelPath (splitRelPath subpath); } diff --git a/lib/path/tests/unit.nix b/lib/path/tests/unit.nix index eccf3b7b1c3..da2c950de91 100644 --- a/lib/path/tests/unit.nix +++ b/lib/path/tests/unit.nix @@ -6,6 +6,7 @@ let inherit (lib.path) subpath; cases = lib.runTests { + # Test examples from the lib.path.subpath.isValid documentation testSubpathIsValidExample1 = { expr = subpath.isValid null; expected = false; @@ -30,6 +31,7 @@ let expr = subpath.isValid "./foo//bar/"; expected = true; }; + # Some extra tests testSubpathIsValidTwoDotsEnd = { expr = subpath.isValid "foo/.."; expected = false; @@ -71,6 +73,7 @@ let expected = true; }; + # Test examples from the lib.path.subpath.normalise documentation testSubpathNormaliseExample1 = { expr = subpath.normalise "foo//bar"; expected = "./foo/bar"; @@ -107,6 +110,7 @@ let expr = (builtins.tryEval (subpath.normalise "/foo")).success; expected = false; }; + # Some extra tests testSubpathNormaliseIsValidDots = { expr = subpath.normalise "./foo/.bar/.../baz...qux"; expected = "./foo/.bar/.../baz...qux"; -- cgit 1.4.1 From eac2538707ee6edd475cb40bfa2ec3d2c05c3ac0 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Wed, 18 Jan 2023 18:09:44 +0100 Subject: lib.path.append: init This function can be used to append strings to Nix path values in a safe way. --- lib/path/default.nix | 47 +++++++++++++++++++++++++++++++++++++++++++++++ lib/path/tests/unit.nix | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) (limited to 'lib/path') diff --git a/lib/path/default.nix b/lib/path/default.nix index 6fa7c1dd641..075e2fc0d13 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -4,6 +4,7 @@ let inherit (builtins) isString + isPath split match ; @@ -98,6 +99,52 @@ let in /* No rec! Add dependencies on this file at the top. */ { + /* 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](https://nixos.org/manual/nix/stable/language/values.html#type-path"), + and that the second argument is a valid subpath string (see `lib.path.subpath.isValid`). + + Type: + append :: Path -> String -> Path + + 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" + => + + # second argument needs to be a valid subpath string + append /foo /bar + => + append /foo "" + => + append /foo "/bar" + => + append /foo "../bar" + => + */ + append = + # The absolute path to append to + path: + # The subpath string to append + subpath: + assert assertMsg (isPath path) '' + lib.path.append: The first argument is of type ${builtins.typeOf path}, but a path was expected''; + assert assertMsg (isValid subpath) '' + lib.path.append: Second argument is not a valid subpath string: + ${subpathInvalidReason subpath}''; + path + ("/" + subpath); /* Whether a value is a valid subpath string. diff --git a/lib/path/tests/unit.nix b/lib/path/tests/unit.nix index da2c950de91..a1a45173a90 100644 --- a/lib/path/tests/unit.nix +++ b/lib/path/tests/unit.nix @@ -3,9 +3,43 @@ { libpath }: let lib = import libpath; - inherit (lib.path) subpath; + inherit (lib.path) append subpath; cases = lib.runTests { + # Test examples from the lib.path.append documentation + testAppendExample1 = { + expr = append /foo "bar/baz"; + expected = /foo/bar/baz; + }; + testAppendExample2 = { + expr = append /foo "./bar//baz/./"; + expected = /foo/bar/baz; + }; + testAppendExample3 = { + expr = append /. "foo/bar"; + expected = /foo/bar; + }; + testAppendExample4 = { + expr = (builtins.tryEval (append "/foo" "bar")).success; + expected = false; + }; + testAppendExample5 = { + expr = (builtins.tryEval (append /foo /bar)).success; + expected = false; + }; + testAppendExample6 = { + expr = (builtins.tryEval (append /foo "")).success; + expected = false; + }; + testAppendExample7 = { + expr = (builtins.tryEval (append /foo "/bar")).success; + expected = false; + }; + testAppendExample8 = { + expr = (builtins.tryEval (append /foo "../bar")).success; + expected = false; + }; + # Test examples from the lib.path.subpath.isValid documentation testSubpathIsValidExample1 = { expr = subpath.isValid null; -- cgit 1.4.1