From b5c492b4ba8ba13720640e7a4699a0fc119dd2e7 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Tue, 8 Aug 2023 00:06:27 +0200 Subject: [PATCH 1/3] lib.path: Make documentation more uniform - Always have a trailing dot after sentences - Link more things - Fix some formatting - Use `append` instead of `+ ("/"` --- lib/path/default.nix | 53 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/lib/path/default.nix b/lib/path/default.nix index 5c6c5f608954..fe6ff4335d4a 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -125,13 +125,13 @@ in /* No rec! Add dependencies on this file at the top. */ { 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`). + and that the second argument is a [valid subpath string](#function-library-lib.path.subpath.isValid). Laws: - - Not influenced by subpath normalisation + - Not influenced by subpath [normalisation](#function-library-lib.path.subpath.normalise): - append p s == append p (subpath.normalise s) + append p s == append p (subpath.normalise s) Type: append :: Path -> String -> Path @@ -179,9 +179,9 @@ in /* No rec! Add dependencies on this file at the top. */ { Laws: - - `hasPrefix p q` is only true if `q == append p s` for some subpath `s`. + - `hasPrefix p q` is only true if [`q == append p s`](#function-library-lib.path.append) for some [subpath](#function-library-lib.path.subpath.isValid) `s`. - - `hasPrefix` is a [non-strict partial order](https://en.wikipedia.org/wiki/Partially_ordered_set#Non-strict_partial_order) over the set of all path values + - `hasPrefix` is a [non-strict partial order](https://en.wikipedia.org/wiki/Partially_ordered_set#Non-strict_partial_order) over the set of all path values. Type: hasPrefix :: Path -> Path -> Bool @@ -220,11 +220,11 @@ in /* No rec! Add dependencies on this file at the top. */ { /* Remove the first path as a component-wise prefix from the second path. - The result is a normalised subpath string, see `lib.path.subpath.normalise`. + The result is a [normalised subpath string](#function-library-lib.path.subpath.normalise). Laws: - - Inverts `append` for normalised subpaths: + - Inverts [`append`](#function-library-lib.path.append) for [normalised subpath string](#function-library-lib.path.subpath.normalise): removePrefix p (append p s) == subpath.normalise s @@ -322,13 +322,13 @@ in /* No rec! Add dependencies on this file at the top. */ { 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 value is a string. - - The string is not empty + - The string is not empty. - - The string doesn't start with a `/` + - The string doesn't start with a `/`. - - The string doesn't contain any `..` path components + - The string doesn't contain any `..` path components. Type: subpath.isValid :: String -> Bool @@ -368,11 +368,11 @@ in /* No rec! Add dependencies on this file at the top. */ { Like `concatStringsSep "/"` but safer, specifically: - - All elements must be valid subpath strings, see `lib.path.subpath.isValid` + - All elements must be [valid subpath strings](#function-library-lib.path.subpath.isValid). - - The result gets normalised, see `lib.path.subpath.normalise` + - The result gets [normalised](#function-library-lib.path.subpath.normalise). - - The edge case of an empty list gets properly handled by returning the neutral subpath `"./."` + - The edge case of an empty list gets properly handled by returning the neutral subpath `"./."`. Laws: @@ -386,12 +386,12 @@ in /* No rec! Add dependencies on this file at the top. */ { subpath.join [ (subpath.normalise p) "./." ] == subpath.normalise p subpath.join [ "./." (subpath.normalise p) ] == subpath.normalise p - - Normalisation - the result is normalised according to `lib.path.subpath.normalise`: + - Normalisation - the result is [normalised](#function-library-lib.path.subpath.normalise): 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. + - For non-empty lists, the implementation is equivalent to [normalising](#function-library-lib.path.subpath.normalise) the result of `concatStringsSep "/"`. + Note that the above laws can be derived from this one: ps != [] -> subpath.join ps == subpath.normalise (concatStringsSep "/" ps) @@ -441,7 +441,7 @@ in /* No rec! Add dependencies on this file at the top. */ { /* 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). + Note that the returned path components are also [valid subpath strings](#function-library-lib.path.subpath.isValid), though they are intentionally not [normalised](#function-library-lib.path.subpath.normalise). Laws: @@ -469,16 +469,15 @@ in /* No rec! Add dependencies on this file at the top. */ { ${subpathInvalidReason subpath}''; splitRelPath subpath; - /* Normalise a subpath. Throw an error if the subpath isn't valid, see - `lib.path.subpath.isValid` + /* Normalise a subpath. Throw an error if the subpath isn't [valid](#function-library-lib.path.subpath.isValid). - - Limit repeating `/` to a single one + - Limit repeating `/` to a single one. - - Remove redundant `.` components + - Remove redundant `.` components. - - Remove trailing `/` and `/.` + - Remove trailing `/` and `/.`. - - Add leading `./` + - Add leading `./`. Laws: @@ -490,15 +489,15 @@ in /* No rec! Add dependencies on this file at the top. */ { subpath.normalise p != subpath.normalise q -> $(realpath ${p}) != $(realpath ${q}) - - Don't change the result when appended to a Nix path value: + - Don't change the result when [appended](#function-library-lib.path.append) to a Nix path value: - base + ("/" + p) == base + ("/" + subpath.normalise p) + 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: + - Only error on [invalid subpaths](#function-library-lib.path.subpath.isValid): builtins.tryEval (subpath.normalise p)).success == subpath.isValid p From dee307ff3023c98c11a193aae1a8341c6f46a22f Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Tue, 8 Aug 2023 00:09:08 +0200 Subject: [PATCH 2/3] lib.path: Indent comments the same --- lib/path/default.nix | 296 ++++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 146 deletions(-) diff --git a/lib/path/default.nix b/lib/path/default.nix index fe6ff4335d4a..5b2f28e90dff 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -121,7 +121,8 @@ let in /* No rec! Add dependencies on this file at the top. */ { - /* Append a subpath string to a 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](https://nixos.org/manual/nix/stable/language/values.html#type-path"), @@ -175,26 +176,26 @@ in /* No rec! Add dependencies on this file at the top. */ { path + ("/" + subpath); /* - Whether the first path is a component-wise prefix of the second path. + Whether the first path is a component-wise prefix of the second path. - Laws: + Laws: - - `hasPrefix p q` is only true if [`q == append p s`](#function-library-lib.path.append) for some [subpath](#function-library-lib.path.subpath.isValid) `s`. + - `hasPrefix p q` is only true if [`q == append p s`](#function-library-lib.path.append) for some [subpath](#function-library-lib.path.subpath.isValid) `s`. - - `hasPrefix` is a [non-strict partial order](https://en.wikipedia.org/wiki/Partially_ordered_set#Non-strict_partial_order) over the set of all path values. + - `hasPrefix` is a [non-strict partial order](https://en.wikipedia.org/wiki/Partially_ordered_set#Non-strict_partial_order) over the set of all path values. - Type: - hasPrefix :: Path -> Path -> Bool + Type: + hasPrefix :: Path -> Path -> Bool - Example: - hasPrefix /foo /foo/bar - => true - hasPrefix /foo /foo - => true - hasPrefix /foo/bar /foo - => false - hasPrefix /. /foo - => true + Example: + hasPrefix /foo /foo/bar + => true + hasPrefix /foo /foo + => true + hasPrefix /foo/bar /foo + => false + hasPrefix /. /foo + => true */ hasPrefix = path1: @@ -219,27 +220,27 @@ in /* No rec! Add dependencies on this file at the top. */ { take (length path1Deconstructed.components) path2Deconstructed.components == path1Deconstructed.components; /* - Remove the first path as a component-wise prefix from the second path. - The result is a [normalised subpath string](#function-library-lib.path.subpath.normalise). + Remove the first path as a component-wise prefix from the second path. + The result is a [normalised subpath string](#function-library-lib.path.subpath.normalise). - Laws: + Laws: - - Inverts [`append`](#function-library-lib.path.append) for [normalised subpath string](#function-library-lib.path.subpath.normalise): + - Inverts [`append`](#function-library-lib.path.append) for [normalised subpath string](#function-library-lib.path.subpath.normalise): - removePrefix p (append p s) == subpath.normalise s + removePrefix p (append p s) == subpath.normalise s - Type: - removePrefix :: Path -> Path -> String + Type: + removePrefix :: Path -> Path -> String - Example: - removePrefix /foo /foo/bar/baz - => "./bar/baz" - removePrefix /foo /foo - => "./." - removePrefix /foo/bar /foo - => - removePrefix /. /foo - => "./foo" + Example: + removePrefix /foo /foo/bar/baz + => "./bar/baz" + removePrefix /foo /foo + => "./." + removePrefix /foo/bar /foo + => + removePrefix /. /foo + => "./foo" */ removePrefix = path1: @@ -272,39 +273,39 @@ in /* No rec! Add dependencies on this file at the top. */ { 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. + 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: + Laws: + - [Appending](#function-library-lib.path.append) the `root` and `subpath` gives the original path: - p == - append - (splitRoot p).root - (splitRoot p).subpath + 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: + - 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 + dirOf (splitRoot p).root == (splitRoot p).root - Type: - splitRoot :: Path -> { root :: Path, subpath :: String } + Type: + splitRoot :: Path -> { root :: Path, subpath :: String } - Example: - splitRoot /foo/bar - => { root = /.; subpath = "./foo/bar"; } + Example: + splitRoot /foo/bar + => { root = /.; subpath = "./foo/bar"; } - splitRoot /. - => { root = /.; subpath = "./."; } + splitRoot /. + => { root = /.; subpath = "./."; } - # Nix neutralises `..` path components for all path values automatically - splitRoot /foo/../bar - => { root = /.; subpath = "./bar"; } + # Nix neutralises `..` path components for all path values automatically + splitRoot /foo/../bar + => { root = /.; subpath = "./bar"; } - splitRoot "/foo/bar" - => + splitRoot "/foo/bar" + => */ splitRoot = path: assert assertMsg @@ -317,46 +318,47 @@ in /* No rec! Add dependencies on this file at the top. */ { subpath = joinRelPath deconstructed.components; }; - /* Whether a value is a valid subpath string. + /* + 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. + 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 value is a string. - - The string is not empty. + - The string is not empty. - - The string doesn't start with a `/`. + - The string doesn't start with a `/`. - - The string doesn't contain any `..` path components. + - The string doesn't contain any `..` path components. - Type: - subpath.isValid :: String -> Bool + Type: + subpath.isValid :: String -> Bool - Example: - # Not a string - subpath.isValid null - => false + Example: + # Not a string + subpath.isValid null + => false - # Empty string - subpath.isValid "" - => false + # Empty string + subpath.isValid "" + => false - # Absolute path - subpath.isValid "/foo" - => false + # Absolute path + subpath.isValid "/foo" + => false - # Contains a `..` path component - subpath.isValid "../foo" - => false + # Contains a `..` path component + subpath.isValid "../foo" + => false - # Valid subpath - subpath.isValid "foo/bar" - => true + # Valid subpath + subpath.isValid "foo/bar" + => true - # Doesn't need to be normalised - subpath.isValid "./foo//bar/" - => true + # Doesn't need to be normalised + subpath.isValid "./foo//bar/" + => true */ subpath.isValid = # The value to check @@ -364,7 +366,8 @@ in /* No rec! Add dependencies on this file at the top. */ { subpathInvalidReason value == null; - /* Join subpath strings together using `/`, returning a normalised subpath string. + /* + Join subpath strings together using `/`, returning a normalised subpath string. Like `concatStringsSep "/"` but safer, specifically: @@ -439,28 +442,28 @@ in /* No rec! Add dependencies on this file at the top. */ { ) 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](#function-library-lib.path.subpath.isValid), though they are intentionally not [normalised](#function-library-lib.path.subpath.normalise). + 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](#function-library-lib.path.subpath.isValid), though they are intentionally not [normalised](#function-library-lib.path.subpath.normalise). - Laws: + 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): + - 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 + subpath.join (subpath.components s) == subpath.normalise s - Type: - subpath.components :: String -> [ String ] + Type: + subpath.components :: String -> [ String ] - Example: - subpath.components "." - => [ ] + Example: + subpath.components "." + => [ ] - subpath.components "./foo//bar/./baz/" - => [ "foo" "bar" "baz" ] + subpath.components "./foo//bar/./baz/" + => [ "foo" "bar" "baz" ] - subpath.components "/foo" - => + subpath.components "/foo" + => */ subpath.components = subpath: @@ -469,77 +472,78 @@ in /* No rec! Add dependencies on this file at the top. */ { ${subpathInvalidReason subpath}''; splitRelPath subpath; - /* Normalise a subpath. Throw an error if the subpath isn't [valid](#function-library-lib.path.subpath.isValid). + /* + Normalise a subpath. Throw an error if the subpath isn't [valid](#function-library-lib.path.subpath.isValid). - - Limit repeating `/` to a single one. + - Limit repeating `/` to a single one. - - Remove redundant `.` components. + - Remove redundant `.` components. - - Remove trailing `/` and `/.`. + - Remove trailing `/` and `/.`. - - Add leading `./`. + - Add leading `./`. - Laws: + 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 + 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}) + subpath.normalise p != subpath.normalise q -> $(realpath ${p}) != $(realpath ${q}) - - Don't change the result when [appended](#function-library-lib.path.append) to a Nix path value: + - Don't change the result when [appended](#function-library-lib.path.append) to a Nix path value: - append base p == append base (subpath.normalise p) + append base p == append base (subpath.normalise p) - - Don't change the path according to `realpath`: + - Don't change the path according to `realpath`: - $(realpath ${p}) == $(realpath ${subpath.normalise p}) + $(realpath ${p}) == $(realpath ${subpath.normalise p}) - - Only error on [invalid subpaths](#function-library-lib.path.subpath.isValid): + - Only error on [invalid subpaths](#function-library-lib.path.subpath.isValid): - builtins.tryEval (subpath.normalise p)).success == subpath.isValid p + builtins.tryEval (subpath.normalise p)).success == subpath.isValid p - Type: - subpath.normalise :: String -> String + Type: + subpath.normalise :: String -> String - Example: - # limit repeating `/` to a single one - subpath.normalise "foo//bar" - => "./foo/bar" + Example: + # limit repeating `/` to a single one + subpath.normalise "foo//bar" + => "./foo/bar" - # remove redundant `.` components - subpath.normalise "foo/./bar" - => "./foo/bar" + # remove redundant `.` components + subpath.normalise "foo/./bar" + => "./foo/bar" - # add leading `./` - 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" - # remove trailing `/.` - subpath.normalise "foo/bar/." - => "./foo/bar" + # remove trailing `/.` + subpath.normalise "foo/bar/." + => "./foo/bar" - # Return the current directory as `./.` - subpath.normalise "." - => "./." + # Return the current directory as `./.` + subpath.normalise "." + => "./." - # error on `..` path components - subpath.normalise "foo/../bar" - => + # error on `..` path components + subpath.normalise "foo/../bar" + => - # error on empty string - subpath.normalise "" - => + # error on empty string + subpath.normalise "" + => - # error on absolute path - subpath.normalise "/foo" - => + # error on absolute path + subpath.normalise "/foo" + => */ subpath.normalise = # The subpath string to normalise From e3ff8dbedaa0a0ee62b98b076531dbc62da50785 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Tue, 8 Aug 2023 00:10:32 +0200 Subject: [PATCH 3/3] lib.path: Add argument docs when missing --- lib/path/default.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/path/default.nix b/lib/path/default.nix index 5b2f28e90dff..1a55a2a7be8d 100644 --- a/lib/path/default.nix +++ b/lib/path/default.nix @@ -307,7 +307,9 @@ in /* No rec! Add dependencies on this file at the top. */ { splitRoot "/foo/bar" => */ - splitRoot = path: + splitRoot = + # The path to split the root off of + path: assert assertMsg (isPath path) "lib.path.splitRoot: Argument is of type ${typeOf path}, but a path was expected"; @@ -466,6 +468,7 @@ in /* No rec! Add dependencies on this file at the top. */ { => */ subpath.components = + # The subpath string to split into components subpath: assert assertMsg (isValid subpath) '' lib.path.subpath.components: Argument is not a valid subpath string: