diff options
Diffstat (limited to 'pkgs/development/misc/resholve/resholve-package.nix')
-rw-r--r-- | pkgs/development/misc/resholve/resholve-package.nix | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/pkgs/development/misc/resholve/resholve-package.nix b/pkgs/development/misc/resholve/resholve-package.nix new file mode 100644 index 00000000000..cc971196a4f --- /dev/null +++ b/pkgs/development/misc/resholve/resholve-package.nix @@ -0,0 +1,97 @@ +{ stdenv, lib, resholve }: + +{ pname +, src +, version +, passthru ? { } +, solutions +, ... +}@attrs: +let + inherit stdenv; + /* These functions break up the work of partially validating the + * 'solutions' attrset and massaging it into env/cli args. + * + * Note: some of the left-most args do not *have* to be passed as + * deep as they are, but I've done so to provide more error context + */ + + # for brevity / line length + spaces = l: builtins.concatStringsSep " " l; + semicolons = l: builtins.concatStringsSep ";" l; + + /* Throw a fit with dotted attr path context */ + nope = path: msg: + throw "${builtins.concatStringsSep "." path}: ${msg}"; + + /* Special-case directive value representations by type */ + makeDirective = solution: env: name: val: + if builtins.isInt val then builtins.toString val + else if builtins.isString val then name + else if true == val then name + else if false == val then "" # omit! + else if null == val then "" # omit! + else if builtins.isList val then "${name}:${semicolons val}" + else nope [ solution env name ] "unexpected type: ${builtins.typeOf val}"; + + /* Build fake/fix/keep directives from Nix types */ + makeDirectives = solution: env: val: + lib.mapAttrsToList (makeDirective solution env) val; + + /* Special-case value representation by type/name */ + makeEnvVal = solution: env: val: + if env == "inputs" then lib.makeBinPath val + else if builtins.isString val then val + else if builtins.isList val then spaces val + else if builtins.isAttrs val then spaces (makeDirectives solution env val) + else nope [ solution env ] "unexpected type: ${builtins.typeOf val}"; + + /* Shell-format each env value */ + shellEnv = solution: env: value: + lib.escapeShellArg (makeEnvVal solution env value); + + /* Build a single ENV=val pair */ + makeEnv = solution: env: value: + "RESHOLVE_${lib.toUpper env}=${shellEnv solution env value}"; + + /* Discard attrs claimed by makeArgs */ + removeCliArgs = value: + removeAttrs value [ "scripts" "flags" ]; + + /* Verify required arguments are present */ + validateSolution = { scripts, inputs, interpreter, ... }: true; + + /* Pull out specific solution keys to build ENV=val pairs */ + makeEnvs = solution: value: + spaces (lib.mapAttrsToList (makeEnv solution) (removeCliArgs value)); + + /* Pull out specific solution keys to build CLI argstring */ + makeArgs = { flags ? [ ], scripts, ... }: + spaces (flags ++ scripts); + + /* Build a single resholve invocation */ + makeInvocation = solution: value: + if validateSolution value then + "${makeEnvs solution value} resholve --overwrite ${makeArgs value}" + else throw "invalid solution"; # shouldn't trigger for now + + /* Build resholve invocation for each solution. */ + makeCommands = solutions: + lib.mapAttrsToList makeInvocation solutions; + + self = (stdenv.mkDerivation ((removeAttrs attrs [ "solutions" ]) + // { + inherit pname version src; + buildInputs = [ resholve ]; + + # enable below for verbose debug info if needed + # supports default python.logging levels + # LOGLEVEL="INFO"; + preFixup = '' + pushd "$out" + ${builtins.concatStringsSep "\n" (makeCommands solutions)} + popd + ''; + })); +in +lib.extendDerivation true passthru self |