forked from mirrors/nixpkgs
lib.path.subpath.join: init
This function can be used to safely join subpaths together
This commit is contained in:
parent
a770c0393c
commit
1a2c2846b0
|
@ -15,6 +15,9 @@ let
|
||||||
last
|
last
|
||||||
genList
|
genList
|
||||||
elemAt
|
elemAt
|
||||||
|
all
|
||||||
|
concatMap
|
||||||
|
foldl'
|
||||||
;
|
;
|
||||||
|
|
||||||
inherit (lib.strings)
|
inherit (lib.strings)
|
||||||
|
@ -190,6 +193,80 @@ in /* No rec! Add dependencies on this file at the top. */ {
|
||||||
subpathInvalidReason value == null;
|
subpathInvalidReason value == null;
|
||||||
|
|
||||||
|
|
||||||
|
/* Join subpath strings together using `/`, returning a normalised subpath string.
|
||||||
|
|
||||||
|
Like `concatStringsSep "/"` but safer, specifically:
|
||||||
|
|
||||||
|
- All elements must be valid subpath strings, see `lib.path.subpath.isValid`
|
||||||
|
|
||||||
|
- The result gets normalised, see `lib.path.subpath.normalise`
|
||||||
|
|
||||||
|
- The edge case of an empty list gets properly handled by returning the neutral subpath `"./."`
|
||||||
|
|
||||||
|
Laws:
|
||||||
|
|
||||||
|
- Associativity:
|
||||||
|
|
||||||
|
subpath.join [ x (subpath.join [ y z ]) ] == subpath.join [ (subpath.join [ x y ]) z ]
|
||||||
|
|
||||||
|
- Identity - `"./."` is the neutral element for normalised paths:
|
||||||
|
|
||||||
|
subpath.join [ ] == "./."
|
||||||
|
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`:
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
ps != [] -> subpath.join ps == subpath.normalise (concatStringsSep "/" ps)
|
||||||
|
|
||||||
|
Type:
|
||||||
|
subpath.join :: [ String ] -> String
|
||||||
|
|
||||||
|
Example:
|
||||||
|
subpath.join [ "foo" "bar/baz" ]
|
||||||
|
=> "./foo/bar/baz"
|
||||||
|
|
||||||
|
# normalise the result
|
||||||
|
subpath.join [ "./foo" "." "bar//./baz/" ]
|
||||||
|
=> "./foo/bar/baz"
|
||||||
|
|
||||||
|
# passing an empty list results in the current directory
|
||||||
|
subpath.join [ ]
|
||||||
|
=> "./."
|
||||||
|
|
||||||
|
# elements must be valid subpath strings
|
||||||
|
subpath.join [ /foo ]
|
||||||
|
=> <error>
|
||||||
|
subpath.join [ "" ]
|
||||||
|
=> <error>
|
||||||
|
subpath.join [ "/foo" ]
|
||||||
|
=> <error>
|
||||||
|
subpath.join [ "../foo" ]
|
||||||
|
=> <error>
|
||||||
|
*/
|
||||||
|
subpath.join =
|
||||||
|
# The list of subpaths to join together
|
||||||
|
subpaths:
|
||||||
|
# Fast in case all paths are valid
|
||||||
|
if all isValid subpaths
|
||||||
|
then joinRelPath (concatMap splitRelPath subpaths)
|
||||||
|
else
|
||||||
|
# Otherwise we take our time to gather more info for a better error message
|
||||||
|
# Strictly go through each path, throwing on the first invalid one
|
||||||
|
# Tracks the list index in the fold accumulator
|
||||||
|
foldl' (i: path:
|
||||||
|
if isValid path
|
||||||
|
then i + 1
|
||||||
|
else throw ''
|
||||||
|
lib.path.subpath.join: Element at index ${toString i} is not a valid subpath string:
|
||||||
|
${subpathInvalidReason path}''
|
||||||
|
) 0 subpaths;
|
||||||
|
|
||||||
/* Normalise a subpath. Throw an error if the subpath isn't valid, see
|
/* Normalise a subpath. Throw an error if the subpath isn't valid, see
|
||||||
`lib.path.subpath.isValid`
|
`lib.path.subpath.isValid`
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,36 @@ let
|
||||||
expected = true;
|
expected = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Test examples from the lib.path.subpath.join documentation
|
||||||
|
testSubpathJoinExample1 = {
|
||||||
|
expr = subpath.join [ "foo" "bar/baz" ];
|
||||||
|
expected = "./foo/bar/baz";
|
||||||
|
};
|
||||||
|
testSubpathJoinExample2 = {
|
||||||
|
expr = subpath.join [ "./foo" "." "bar//./baz/" ];
|
||||||
|
expected = "./foo/bar/baz";
|
||||||
|
};
|
||||||
|
testSubpathJoinExample3 = {
|
||||||
|
expr = subpath.join [ ];
|
||||||
|
expected = "./.";
|
||||||
|
};
|
||||||
|
testSubpathJoinExample4 = {
|
||||||
|
expr = (builtins.tryEval (subpath.join [ /foo ])).success;
|
||||||
|
expected = false;
|
||||||
|
};
|
||||||
|
testSubpathJoinExample5 = {
|
||||||
|
expr = (builtins.tryEval (subpath.join [ "" ])).success;
|
||||||
|
expected = false;
|
||||||
|
};
|
||||||
|
testSubpathJoinExample6 = {
|
||||||
|
expr = (builtins.tryEval (subpath.join [ "/foo" ])).success;
|
||||||
|
expected = false;
|
||||||
|
};
|
||||||
|
testSubpathJoinExample7 = {
|
||||||
|
expr = (builtins.tryEval (subpath.join [ "../foo" ])).success;
|
||||||
|
expected = false;
|
||||||
|
};
|
||||||
|
|
||||||
# Test examples from the lib.path.subpath.normalise documentation
|
# Test examples from the lib.path.subpath.normalise documentation
|
||||||
testSubpathNormaliseExample1 = {
|
testSubpathNormaliseExample1 = {
|
||||||
expr = subpath.normalise "foo//bar";
|
expr = subpath.normalise "foo//bar";
|
||||||
|
|
Loading…
Reference in a new issue