1{ lib, resholve, binlore }:
2
3rec {
4 /* These functions break up the work of partially validating the
5 'solutions' attrset and massaging it into env/cli args.
6
7 Note: some of the left-most args do not *have* to be passed as
8 deep as they are, but I've done so to provide more error context
9 */
10
11 # for brevity / line length
12 spaces = l: builtins.concatStringsSep " " l;
13 semicolons = l: builtins.concatStringsSep ";" l;
14
15 /* Throw a fit with dotted attr path context */
16 nope = path: msg:
17 throw "${builtins.concatStringsSep "." path}: ${msg}";
18
19 /* Special-case directive value representations by type */
20 makeDirective = solution: env: name: val:
21 if builtins.isInt val then builtins.toString val
22 else if builtins.isString val then name
23 else if true == val then name
24 else if false == val then "" # omit!
25 else if null == val then "" # omit!
26 else if builtins.isList val then "${name}:${semicolons val}"
27 else nope [ solution env name ] "unexpected type: ${builtins.typeOf val}";
28
29 /* Build fake/fix/keep directives from Nix types */
30 makeDirectives = solution: env: val:
31 lib.mapAttrsToList (makeDirective solution env) val;
32
33 /* Special-case value representation by type/name */
34 makeEnvVal = solution: env: val:
35 if env == "inputs" then lib.makeBinPath val
36 else if builtins.isString val then val
37 else if builtins.isList val then spaces val
38 else if builtins.isAttrs val then spaces (makeDirectives solution env val)
39 else nope [ solution env ] "unexpected type: ${builtins.typeOf val}";
40
41 /* Shell-format each env value */
42 shellEnv = solution: env: value:
43 lib.escapeShellArg (makeEnvVal solution env value);
44
45 /* Build a single ENV=val pair */
46 makeEnv = solution: env: value:
47 "RESHOLVE_${lib.toUpper env}=${shellEnv solution env value}";
48
49 /* Discard attrs claimed by makeArgs */
50 removeCliArgs = value:
51 removeAttrs value [ "scripts" "flags" ];
52
53 /* Verify required arguments are present */
54 validateSolution = { scripts, inputs, interpreter, ... }: true;
55
56 /* Pull out specific solution keys to build ENV=val pairs */
57 makeEnvs = solution: value:
58 spaces (lib.mapAttrsToList (makeEnv solution) (removeCliArgs value));
59
60 /* Pull out specific solution keys to build CLI argstring */
61 makeArgs = { flags ? [ ], scripts, ... }:
62 spaces (flags ++ scripts);
63
64 /* Build a single resholve invocation */
65 makeInvocation = solution: value:
66 if validateSolution value then
67 # we pass resholve a directory
68 "RESHOLVE_LORE=${binlore.collect { drvs = value.inputs; } } ${makeEnvs solution value} ${resholve}/bin/resholve --overwrite ${makeArgs value}"
69 else throw "invalid solution"; # shouldn't trigger for now
70
71 /* Build resholve invocation for each solution. */
72 makeCommands = solutions:
73 lib.mapAttrsToList makeInvocation solutions;
74}