From 097307c46fc5a7bda63a5916cfd1ee3ad661a0a6 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Wed, 25 Jul 2018 03:11:41 +0200 Subject: pkgs/profpatsch: WIP execline experiments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * runExecline: like runCommand, but a lot more lightweight * symlink: symlink a given list of links together * importer: a small DSL to “import” “modules” into a build context Some highlights: * runExecline does not use any stdenv (apart from the `execline` build) * symlink uses netstrings to pass correct fields into the derivation * no use of bash, everything uses execline. --- pkgs/profpatsch/default.nix | 41 +++++++++++++++++++++---- pkgs/profpatsch/execline/importer.nix | 45 ++++++++++++++++++++++++++++ pkgs/profpatsch/execline/run-execline.nix | 38 +++++++++++++++++++++++ pkgs/profpatsch/execline/symlink.nix | 50 +++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 pkgs/profpatsch/execline/importer.nix create mode 100644 pkgs/profpatsch/execline/run-execline.nix create mode 100644 pkgs/profpatsch/execline/symlink.nix diff --git a/pkgs/profpatsch/default.nix b/pkgs/profpatsch/default.nix index 2fcd7c40..f14eb61c 100644 --- a/pkgs/profpatsch/default.nix +++ b/pkgs/profpatsch/default.nix @@ -1,21 +1,24 @@ -{ pkgs, callPackage, haskellPackages, droopy, fetchFromGitHub }: +{ stdenv, pkgs }: -{ +let + inherit (pkgs) callPackage; + +in rec { backlight = callPackage ./backlight { inherit (pkgs.xorg) xbacklight; }; display-infos = callPackage ./display-infos {}; nix-http-serve = callPackage ./nix-http-serve {}; nman = callPackage ./nman {}; show-qr-code = callPackage ./show-qr-code {}; warpspeed = callPackage ./warpspeed { - inherit (haskellPackages) ghcWithPackages; + inherit (pkgs.haskellPackages) ghcWithPackages; }; inherit (callPackage ./utils-hs {}) nix-gen until watch-server; # patched version of droopy, with javascript user-enhancement - droopy = droopy.overrideDerivation (old: { - src = fetchFromGitHub { + droopy = pkgs.droopy.overrideDerivation (old: { + src = pkgs.fetchFromGitHub { owner = "Profpatsch"; repo = "Droopy"; rev = "55c60c612b913f9fbce9fceebbcb3a332152f1a4"; @@ -28,6 +31,32 @@ makeWrapperArgs = old.makeWrapperArgs or [] ++ [ "--set DROOPY_STATIC \"$out/share/droopy/static\"" ]; - }); + + # wrapper for execlineb that doesn’t need the execline commands + # in PATH to work (making them appear like “builtins”) + execlineb-with-builtins = + let eldir = "${pkgs.execline}/bin"; + in pkgs.writeScriptBin "execlineb" '' + #!${eldir}/execlineb -s0 + ${eldir}/define eldir ${eldir} + ''${eldir}/importas oldpath PATH + ''${eldir}/export PATH "''${eldir}:''${oldpath}" + ''${eldir}/execlineb $@ + ''; + + runExecline = import ./execline/run-execline.nix { + inherit stdenv; + execlinebCommand = "${execlineb-with-builtins}/bin/execlineb"; + importasCommand = "${pkgs.execline}/bin/importas"; + }; + + symlink = pkgs.callPackage ./execline/symlink.nix { + inherit runExecline; + }; + + importer = pkgs.callPackage ./execline/importer.nix { + inherit symlink; + }; + } diff --git a/pkgs/profpatsch/execline/importer.nix b/pkgs/profpatsch/execline/importer.nix new file mode 100644 index 00000000..67464d17 --- /dev/null +++ b/pkgs/profpatsch/execline/importer.nix @@ -0,0 +1,45 @@ +{ lib, coreutils, s6-portable-utils, symlink }: +let + example = {from, as, just, ...}: + [ + (from coreutils [ + (just "echo") + (as "core-ls" "ls") + ]) + (from s6-portable-utils [ + (as "ls" "s6-ls") + (just "s6-echo") + ]) + ]; + + runImport = impsFn: + let + combinators = rec { + from = source: imports: { + inherit source imports; + }; + as = newname: oldname: { + inherit oldname newname; + }; + just = x: as x x; + }; + + # Drv -> As -> Symlink + toBin = module: {oldname, newname}: { + dest = "bin/${newname}"; + orig = "${module}/bin/${oldname}"; + }; + # List (Import { source: Drv + # , imports: List (As { oldname: String + # , newname: String })) + # -> Drv + run = imps: + symlink "foo" (lib.concatLists + (map ({source, imports}: + map (toBin source) imports) + imps)); + + # TODO: typecheck w/ newtypes + in run (impsFn combinators); + +in runImport example diff --git a/pkgs/profpatsch/execline/run-execline.nix b/pkgs/profpatsch/execline/run-execline.nix new file mode 100644 index 00000000..40915f25 --- /dev/null +++ b/pkgs/profpatsch/execline/run-execline.nix @@ -0,0 +1,38 @@ +{ stdenv, importasCommand, execlinebCommand }: +{ name +# the execline script +, execline +# additional arguments to pass to the derivation +, derivationArgs ? {} +}: + +# those arguments can’t be overwritten +assert !derivationArgs ? system; +assert !derivationArgs ? name; +assert !derivationArgs ? builder; +assert !derivationArgs ? args; + +derivation (derivationArgs // { + inherit (stdenv) system; + inherit name; + + # okay, `builtins.toFile` does not accept strings + # that reference drv outputs. This means we need + # to pass the script as envvar; + # this might clash with another passed envar, + # so we give it a long & unique name + _runExeclineScript = execline; + passAsFile = [ "_runExeclineScript" ] + ++ derivationArgs.passAsFile or []; + + builder = importasCommand; + args = [ + "-ui" # drop the envvar afterwards + "script" # substitution name + "_runExeclineScriptPath" # passed script file + execlinebCommand # the actual invocation + "-P" # ignore command line arguments + "-W" # die on syntax error + "$script" # substituted by importas + ]; +}) diff --git a/pkgs/profpatsch/execline/symlink.nix b/pkgs/profpatsch/execline/symlink.nix new file mode 100644 index 00000000..ca8684d2 --- /dev/null +++ b/pkgs/profpatsch/execline/symlink.nix @@ -0,0 +1,50 @@ +{ lib, s6-portable-utils, coreutils, runExecline }: +# DrvPath :: path relative to the derivation +# AbsPath :: absolute path in the store +# Name +# -> List (Symlink { dest: DrvPath, orig: AbsPath }) +# -> Drv +name: links: + +let + toNetstring = s: + "${toString (builtins.stringLength s)}:${s},"; + +in +runExecline { + inherit name; + + derivationArgs = { + pathTuples = lib.concatMapStrings + ({dest, orig}: toNetstring + (toNetstring dest + (toNetstring orig))) + links; + passAsFile = [ "pathTuples" ]; + # bah! coreutils just for cat :( + PATH = lib.makeBinPath [ s6-portable-utils ]; + }; + + execline = '' + importas -ui p pathTuplesPath + importas -ui out out + forbacktickx -d "" destorig { ${coreutils}/bin/cat $p } + importas -ui do destorig + multidefine -d "" $do { destsuffix orig } + define dest ''${out}/''${destsuffix} + + # this call happens for every file, not very efficient + foreground { + backtick -n d { s6-dirname $dest } + importas -ui d d + s6-mkdir -p $d + } + + ifthenelse { s6-test -L $orig } { + backtick -n res { s6-linkname -f $orig } + importas -ui res res + s6-ln -fs $res $dest + } { + s6-ln -fs $orig $dest + } + ''; +} -- cgit 1.4.1