Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
7.7 kB · 293 lines
Nix
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294{ lib, stdenv, resholve, binlore, writeTextFile,}:
rec { /* 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; colons = 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 phraseDirective = 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 (map lib.escapeShellArg val)}" else nope [ solution env name ] "unexpected type: ${builtins.typeOf val}";
# Build fake/fix/keep directives from Nix types phraseDirectives = solution: env: val: lib.mapAttrsToList (phraseDirective solution env) val;
# Custom ~search-path routine to handle relative path strings relSafeBinPath = input: if lib.isDerivation input then ((lib.getOutput "bin" input) + "/bin") else if builtins.isString input then input else throw "unexpected type for input: ${builtins.typeOf input}";
# Special-case value representation by type/name phraseEnvVal = solution: env: val: if env == "inputs" then (colons (map relSafeBinPath val)) else if builtins.isString val then val else if builtins.isList val then spaces val else if builtins.isAttrs val then spaces (phraseDirectives solution env val) else nope [ solution env ] "unexpected type: ${builtins.typeOf val}";
# Shell-format each env value shellEnv = solution: env: value: lib.escapeShellArg (phraseEnvVal solution env value);
# Build a single ENV=val pair phraseEnv = solution: env: value: "RESHOLVE_${lib.toUpper env}=${shellEnv solution env value}";
/* Discard attrs: - claimed by phraseArgs - only needed for binlore.collect */ removeUnneededArgs = value: removeAttrs value [ "scripts" "flags" "unresholved" ];
# Verify required arguments are present validateSolution = { scripts, inputs, interpreter, ... }: true;
# Pull out specific solution keys to build ENV=val pairs phraseEnvs = solution: value: spaces (lib.mapAttrsToList (phraseEnv solution) (removeUnneededArgs value));
# Pull out specific solution keys to build CLI argstring phraseArgs = { flags ? [ ], scripts, ... }: spaces (flags ++ scripts);
phraseBinloreArgs = value: let hasUnresholved = builtins.hasAttr "unresholved" value; in { drvs = value.inputs ++ lib.optionals hasUnresholved [ value.unresholved ]; strip = if hasUnresholved then [ value.unresholved ] else [ ]; };
# Build a single resholve invocation phraseInvocation = solution: value: if validateSolution value then # we pass resholve a directory "RESHOLVE_LORE=${binlore.collect (phraseBinloreArgs value)} ${phraseEnvs solution value} ${resholve}/bin/resholve --overwrite ${phraseArgs value}" else throw "invalid solution"; # shouldn't trigger for now
injectUnresholved = solutions: unresholved: (builtins.mapAttrs (name: value: value // { inherit unresholved; }) solutions);
# Build resholve invocation for each solution. phraseCommands = solutions: unresholved: builtins.concatStringsSep "\n" ( lib.mapAttrsToList phraseInvocation (injectUnresholved solutions unresholved) );
/* subshell/PS4/set -x and : command to output resholve envs and invocation. Extra context makes it clearer what the Nix API is doing, makes nix-shell debugging easier, etc. */ phraseContext = { invokable, prep ? ''cd "$out"'', }: '' ( ${prep} PS4=$'\x1f'"\033[33m[resholve context]\033[0m " set -x : invoking resholve with PWD=$PWD ${invokable} ) ''; phraseContextForPWD = invokable: phraseContext { inherit invokable; prep = ""; }; phraseContextForOut = invokable: phraseContext { inherit invokable; };
phraseSolution = name: solution: (phraseContextForOut (phraseInvocation name solution)); phraseSolutions = solutions: unresholved: phraseContextForOut (phraseCommands solutions unresholved);
writeScript = name: partialSolution: text: writeTextFile { inherit name text; executable = true; checkPhase = '' ${ (phraseContextForPWD ( phraseInvocation name ( partialSolution // { scripts = [ "${placeholder "out"}" ]; } ) )) } '' + lib.optionalString (partialSolution.interpreter != "none") '' ${partialSolution.interpreter} -n $out ''; }; writeScriptBin = name: partialSolution: text: writeTextFile rec { inherit name text; executable = true; destination = "/bin/${name}"; checkPhase = '' ${phraseContextForOut ( phraseInvocation name ( partialSolution // { scripts = [ "bin/${name}" ]; } ) )} '' + lib.optionalString (partialSolution.interpreter != "none") '' ${partialSolution.interpreter} -n $out/bin/${name} ''; }; mkDerivation = { pname, src, version, passthru ? { }, solutions, ... }@attrs: let inherit stdenv;
/* Knock out our special solutions arg, but otherwise just build what the caller is giving us. We'll actually resholve it separately below (after we generate binlore for it). */ unresholved = ( stdenv.mkDerivation ( (removeAttrs attrs [ "solutions" ]) // { inherit version src; pname = "${pname}-unresholved"; } ) ); in /* resholve in a separate derivation; some concerns: - we aren't keeping many of the user's args, so they can't readily set LOGLEVEL and such... - not sure how this affects multiple outputs */ lib.extendDerivation true passthru ( stdenv.mkDerivation { src = unresholved; inherit version pname; buildInputs = [ resholve ]; disallowedReferences = [ resholve ];
# retain a reference to the base passthru = unresholved.passthru // { unresholved = unresholved; # fallback attr for update bot to query our src originalSrc = unresholved.src; };
# do these imply that we should use NoCC or something? dontConfigure = true; dontBuild = true;
installPhase = '' cp -R $src $out '';
# enable below for verbose debug info if needed # supports default python.logging levels # LOGLEVEL="INFO"; preFixup = phraseSolutions solutions unresholved;
# don't break the metadata... meta = unresholved.meta; } );}