diff --git a/modules/lib/path.nix b/modules/lib/path.nix index 2f118366..74f65032 100644 --- a/modules/lib/path.nix +++ b/modules/lib/path.nix @@ -8,30 +8,34 @@ let path = rec { # split "a//b/" => ["a" "b"] # split "/a/b" => ["a" "b"] split = str: builtins.filter (seg: seg != "") (lib.splitString "/" str); + # given an array of components, returns the equivalent string path join = comps: "/" + (builtins.concatStringsSep "/" comps); + # given an a sequence of string paths, concatenates them into one long string path concat = paths: path.join (builtins.concatLists (builtins.map path.split paths)); + # normalize the given path + # canonical form is an *absolute* path; + # always starting with '/', never trailing with '/' unless it's the empty (root) path norm = str: path.join (path.split str); + # return the parent directory. doesn't care about leading/trailing slashes. # the parent of "/" is "/". parent = str: path.norm (builtins.dirOf (path.norm str)); hasParent = str: (path.parent str) != (path.norm str); - # return the path from `from` to `to`, but keeping absolute form - # e.g. `pathFrom "/home/colin" "/home/colin/foo/bar"` -> "/foo/bar" # return the last path component; error on the empty path leaf = str: lib.last (split str); - # XXX: this is bugged in that - # from "/foo/bar" "/foo/barbag" => "/bag" + # return the path from `from` to `to`, but keeping absolute form + # e.g. `pathFrom "/home/colin" "/home/colin/foo/bar"` -> "/foo/bar" from = start: end: let s = path.norm start; e = path.norm end; in ( - assert lib.hasPrefix s e; - "/" + (lib.removePrefix s e) + assert isChild start end; + "/" + lib.removePrefix s e ); isChild = parent: child: @@ -40,7 +44,7 @@ let path = rec { (walk "/" child) ; - # yield every node between start and end, including each the endpoints + # yield every node between start and end, including each of the endpoints # e.g. walk "/foo" "/foo/bar/baz" => [ "/foo" "/foo/bar" "/foo/bar/baz" ] # XXX: assumes input paths are normalized walk = start: end: if start == end then