about summary refs log tree commit diff
path: root/read-tree.nix
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2019-11-15T14·52+0000
committerVincent Ambo <tazjin@google.com>2019-11-15T14·52+0000
commit4d852e2ef73a0901a3426ae5ab93232b6a0a8ed2 (patch)
tree99a1a6bfe12b89fc6e034f0dd0de58371a436ffd /read-tree.nix
parent8e53dec88cf7a09da48be66312f6ad0a1f1d3022 (diff)
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.
Diffstat (limited to 'read-tree.nix')
-rw-r--r--read-tree.nix67
1 files changed, 67 insertions, 0 deletions
diff --git a/read-tree.nix b/read-tree.nix
new file mode 100644
index 0000000000..00a2e738bd
--- /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