about summary refs log tree commit diff
path: root/pkgs
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2018-07-25 03:11:41 +0200
committerProfpatsch <mail@profpatsch.de>2018-07-25 03:17:14 +0200
commit097307c46fc5a7bda63a5916cfd1ee3ad661a0a6 (patch)
tree21aad88f5d534f3546e3d3a6b43ed64c2d275c6e /pkgs
parentfd8db354af44cfd2142186c762d2c280c0639233 (diff)
pkgs/profpatsch: WIP execline experiments
* 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.
Diffstat (limited to 'pkgs')
-rw-r--r--pkgs/profpatsch/default.nix41
-rw-r--r--pkgs/profpatsch/execline/importer.nix45
-rw-r--r--pkgs/profpatsch/execline/run-execline.nix38
-rw-r--r--pkgs/profpatsch/execline/symlink.nix50
4 files changed, 168 insertions, 6 deletions
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
+      }
+  '';
+}