tvl-depot/nix/readTree/default.nix
Vincent Ambo dbda84bac3 fix(readTree): Add __readTree attribute to folders
This is required to automatically walk the tree (see subsequent
commits).

Note: Lisp packages are removed from the CI builds in this commit
because the attrValues of third_party.lisp will contain an element
that is simply `true`, which causes a type error.

These packages are re-added when CI refactoring is complete.

Change-Id: I21e2b719e6c7161c23d2867a216f4daa1c6c8394
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1848
Tested-by: BuildkiteCI
Reviewed-by: glittershark <grfn@gws.fyi>
2020-08-26 23:49:32 +00:00

74 lines
2.1 KiB
Nix

{ ... }:
args: initPath:
let
inherit (builtins)
attrNames
baseNameOf
filter
hasAttr
head
isAttrs
length
listToAttrs
map
match
readDir
substring;
argsWithPath = parts:
let meta.locatedAt = parts;
in meta // (if isAttrs args then args else args meta);
readDirVisible = path:
let
children = readDir path;
isVisible = f: f == ".skip-subtree" || (substring 0 1 f) != ".";
names = filter isVisible (attrNames children);
in listToAttrs (map (name: {
inherit name;
value = children.${name};
}) names);
# The marker is added to every set that was imported directly by
# readTree.
importWithMark = path: parts:
let imported = import path (argsWithPath parts);
in if (isAttrs imported)
then imported // { __readTree = true; }
else imported;
nixFileName = file:
let res = match "(.*)\.nix" file;
in if res == null then null else head res;
readTree = path: parts:
let
dir = readDirVisible path;
self = importWithMark path parts;
joinChild = c: path + ("/" + c);
# Import subdirectories of the current one, unless the special
# `.skip-subtree` file exists which makes readTree ignore the
# children.
#
# This file can optionally contain information on why the tree
# should be ignored, but its content is not inspected by
# readTree
filterDir = f: dir."${f}" == "directory";
children = if hasAttr ".skip-subtree" dir then [] else map (c: {
name = c;
value = readTree (joinChild c) (parts ++ [ c ]);
}) (filter filterDir (attrNames dir));
# Import Nix files
nixFiles = filter (f: f != null) (map nixFileName (attrNames dir));
nixChildren = map (c: let p = joinChild (c + ".nix"); in {
name = c;
value = importWithMark p (parts ++ [ c ]);
}) nixFiles;
in if dir ? "default.nix"
then (if isAttrs self then self // (listToAttrs children) else self)
else (listToAttrs (nixChildren ++ children) // { __readTree = true; });
in readTree initPath [ (baseNameOf initPath) ]