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
{ ... }:
{
collectModules =
{
path,
scope ? { },
fileName ? "default.nix",
}:
(
let
#some helpers (mostly from nixpkgs or at least derived from that)
sublist =
start: count: list:
let
len = builtins.length list;
in
builtins.genList (n: builtins.elemAt list (n + start)) (
if start >= len then
0
else if start + count > len then
len - start
else
count
);
pipe = builtins.foldl' (x: f: f x);
flatten = x: if builtins.isList x then builtins.concatMap (y: flatten y) x else [ x ];
drop = count: list: sublist count (builtins.length list) list;
splitPath = path: builtins.filter builtins.isString (builtins.split "/" (builtins.toString path));
#actual logic starts here
fileNameLength = builtins.stringLength fileName;
basePathLength = builtins.length (splitPath ./.);
collectFiles =
path:
pipe (builtins.readDir path) [
(builtins.mapAttrs (
name: value:
if value == "directory" then (collectFiles (path + "/${name}")) else (path + "/${name}")
))
builtins.attrValues
flatten
(builtins.filter (
elem:
let
pathLength = builtins.length (splitPath elem);
in
(
(
let
strLength = builtins.stringLength elem;
in
builtins.substring (strLength - fileNameLength) strLength elem
) == fileName
)
&& (pathLength - 1) != basePathLength
))
];
in
pipe (collectFiles path) [
(builtins.map (filePath: {
name = (
let
pathParts = drop basePathLength (splitPath filePath);
in
builtins.concatStringsSep "-" (sublist 0 ((builtins.length pathParts) - 1) pathParts)
);
value = import filePath scope;
}))
builtins.listToAttrs
]
);
}