From 4d852e2ef73a0901a3426ae5ab93232b6a0a8ed2 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Fri, 15 Nov 2019 14:52:23 +0000 Subject: [PATCH] feat(build): Add initial read-tree.nix implementation This file can read a directory tree into a package set structure, paving the way for getting rid of top-level mapping in default.nix. --- read-tree.nix | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 read-tree.nix diff --git a/read-tree.nix b/read-tree.nix new file mode 100644 index 000000000..00a2e738b --- /dev/null +++ b/read-tree.nix @@ -0,0 +1,67 @@ +path: self: super: + +let + inherit (builtins) + attrNames + attrValues + filter + head + isString + listToAttrs + map + match + readDir + tail + toPath + toString; + + args = { pkgs = self; }; + + zipAttrs = names: values: + if (names == []) || (values == []) + then [] + else [{ + name = head names; + value = head values; + }] ++ zipAttrs (tail names) (tail values); + + attrsToList = attrs: zipAttrs (attrNames attrs) (attrValues attrs); + + isFile = s: s == "regular"; + isDir = s: s == "directory"; + + joinPath = p: f: toPath ((toString p) + "/" + f); + + isNixFile = file: + let res = match "(.*)\.nix" file; + in if res == null then null else head res; + + filterNixFiles = dir: + let files = filter (e: isFile e.value) dir; + nixFiles = map (f: { + # Name and value are intentionally flipped to get the + # correct attribute set structure back out + name = isNixFile f.name; + value = f.name; # i.e. the path + }) files; + in filter (f: isString f.name) nixFiles; + + traverse = path: dir: + let nixFiles = filterNixFiles dir; + imported = map (f: { + inherit (f) name; + value = import (joinPath path f.value) args; + }) nixFiles; + dirs = map (d: { + inherit (d) name; + value = readTree (joinPath path d.name); + }) (filter (e: isDir e.value) dir); + in listToAttrs (imported ++ dirs); + + importOr = path: dir: f: + if dir ? "default.nix" + then import path args + else f path (attrsToList dir); + + readTree = path: importOr path (readDir path) traverse; +in readTree path