-
Notifications
You must be signed in to change notification settings - Fork 0
/
engine.nix
105 lines (93 loc) · 2.96 KB
/
engine.nix
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
94
95
96
97
98
99
100
101
102
103
104
105
pkgs: src: {extraArgs, entries, templates}: let
inherit (pkgs) lib;
inherit (builtins) abort dirOf toString;
inherit (lib.attrsets) hasAttr;
inherit (lib.lists) forEach findFirst;
inherit (lib.path) removePrefix;
inherit (lib.strings) concatMapStrings concatStrings escapeShellArg hasSuffix isString removeSuffix;
inherit (lib.trivial) functionArgs;
templates' = templates ++ [
(pkgs.writeText "passthrough.nix" /*nix*/''
{ format, output, ... }: {
name = "passthrough";
inherit format output;
}
'')
];
args = {inherit pkgs getEntry applyTemplate;}
// (import ./stdlib.nix pkgs)
// extraArgs;
isBaseTemplate = template:
isString template.output;
findTemplateFn = entry: let
template = findFirst (templateFile: let
templateFn = import templateFile;
template' = templateFn (functionArgs templateFn);
in
template'.name == entry.template)
null
templates';
in
if template == null then
abort "unknown template `${entry.template}`"
else
(import template);
applyTemplate = templateFn: entry: let
template = templateFn (args // entry);
in
if isBaseTemplate template then
template.output
else let
newEntry = template.output;
foundTemplateFn = findTemplateFn newEntry;
in
applyTemplate foundTemplateFn newEntry;
applyTemplateFile = templateFn: entry: {
inherit (entry) file;
output = applyTemplate templateFn entry;
};
replaceSuffix = from: to: string:
if !(hasSuffix from string) then
abort "invalid suffix `${from}` for string `${string}`"
else
concatStrings [ (removeSuffix from string) to ];
getTemplateFormat = entry: templateFn: let
# getEntry needs to go down to the base template for the format
# but any template through the way can ask for a file
# so we just give it a placeholder - an empty string here
# since the output of this thing doesn't matter
template = templateFn (args // entry // { file = ""; });
in
if isBaseTemplate template then
template.format
else let
newEntry = template.output;
foundTemplateFn = findTemplateFn newEntry;
in
getTemplateFormat newEntry foundTemplateFn;
getEntry = entryFile: let
sourceFile = toString (removePrefix src entryFile);
entry = (import entryFile) args;
foundTemplateFn = findTemplateFn entry;
entryFormat = getTemplateFormat entry foundTemplateFn;
in
if !(hasAttr "file" entry) then
entry // {
file = replaceSuffix ".nix" ".${entryFormat}" sourceFile;
}
else
entry;
processEntryFile = entryFile: let
foundTemplateFn = findTemplateFn entry;
entry = getEntry entryFile;
in
applyTemplateFile foundTemplateFn entry;
in /*sh*/''
${concatMapStrings
(result: /*sh*/''
mkdir -p $out/${dirOf result.file}
echo ${escapeShellArg result.output} > $out/${result.file}
'')
(forEach entries processEntryFile)
}
''