blob: ce4c7f032a109aa36fe00590bc9a00e33ec01908 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
{ ... }:
let
inherit (builtins)
attrNames
baseNameOf
concatStringsSep
filter
hasAttr
head
isAttrs
length
listToAttrs
map
match
readDir
substring;
assertMsg = pred: msg:
if pred
then true
else builtins.trace msg false;
argsWithPath = args: 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);
# Create a mark containing the location of this attribute.
marker = parts: {
__readTree = parts;
};
# The marker is added to every set that was imported directly by
# readTree.
importWithMark = args: path: parts:
let
importedFile = import path;
pathType = builtins.typeOf importedFile;
imported =
assert assertMsg
(pathType == "lambda")
"readTree: trying to import ${toString path}, but it’s a ${pathType}, you need to make it a function like { depot, pkgs, ... }";
importedFile (argsWithPath args parts);
in if (isAttrs imported)
then imported // (marker parts)
else imported;
nixFileName = file:
let res = match "(.*)\\.nix" file;
in if res == null then null else head res;
readTree = args: initPath: parts:
let
dir = readDirVisible initPath;
self = importWithMark args initPath parts;
joinChild = c: initPath + ("/" + 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 args (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 args p (parts ++ [ c ]);
}) nixFiles;
in if dir ? "default.nix"
then (if isAttrs self then self // (listToAttrs children) else self)
else (listToAttrs (nixChildren ++ children) // (marker parts));
in {
__functor = _: args: initPath: readTree args initPath [ (baseNameOf initPath) ];
}
|