about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2012-07-23T17·41-0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-07-25T13·30-0400
commitb1112bbef195bc8397c4e88aa8544537a6d84731 (patch)
treebc1e4827013e70fd989dc807d6934dd26dc0d5d7
parent566a30c0072690900d4d55679a2981758d6fb888 (diff)
import: If the path is a valid .drv file, parse it and generate a derivation attrset.
The generated attrset has drvPath and outPath with the right string context, type 'derivation', outputName with
the right name, all with a list of outputs, and an attribute for each output.

I see three uses for this (though certainly there may be more):

* Using derivations generated by something besides nix-instantiate (e.g. guix)

* Allowing packages provided by channels to be used in nix expressions. If a channel installed a valid deriver
  for each package it provides into the store, then those could be imported and used as dependencies or installed
  in environment.systemPackages, for example.

* Enable hydra to be consistent in how it treats inputs that are outputs of another build. Right now, if an
  input is passed as an argument to the job, it is passed as a derivation, but if it is accessed via NIX_PATH
  (i.e. through the <> syntax), then it is a path that can be imported. This is problematic because the build
  being depended upon may have been built with non-obvious arguments passed to its jobset file. With this
  feature, hydra can just set the name of that input to the path to its drv file in NIX_PATH
-rw-r--r--corepkgs/Makefile.am3
-rw-r--r--corepkgs/imported-drv-to-derivation.nix21
-rw-r--r--src/libexpr/primops.cc26
3 files changed, 48 insertions, 2 deletions
diff --git a/corepkgs/Makefile.am b/corepkgs/Makefile.am
index 729d15e7b191..4b0b8860be68 100644
--- a/corepkgs/Makefile.am
+++ b/corepkgs/Makefile.am
@@ -1,6 +1,7 @@
 all-local: config.nix
 
-files = nar.nix buildenv.nix buildenv.pl unpack-channel.nix unpack-channel.sh derivation.nix fetchurl.nix
+files = nar.nix buildenv.nix buildenv.pl unpack-channel.nix unpack-channel.sh derivation.nix fetchurl.nix \
+	imported-drv-to-derivation.nix
 
 install-exec-local:
 	$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs
diff --git a/corepkgs/imported-drv-to-derivation.nix b/corepkgs/imported-drv-to-derivation.nix
new file mode 100644
index 000000000000..bdb60169860a
--- /dev/null
+++ b/corepkgs/imported-drv-to-derivation.nix
@@ -0,0 +1,21 @@
+attrs @ { drvPath, outputs, ... }:
+
+let
+
+  commonAttrs = (builtins.listToAttrs outputsList) //
+    { all = map (x: x.value) outputsList;
+      inherit drvPath;
+      type = "derivation";
+    };
+
+  outputToAttrListElement = outputName:
+    { name = outputName;
+      value = commonAttrs // {
+        outPath = builtins.getAttr outputName attrs;
+        inherit outputName;
+      };
+    };
+    
+  outputsList = map outputToAttrListElement outputs;
+    
+in (builtins.head outputsList).value
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 5d5f0bfb3b5b..2ab3eda53f43 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -59,7 +59,31 @@ static void prim_import(EvalState & state, Value * * args, Value & v)
             }
     }
 
-    state.evalFile(path, v);
+    if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) {
+        Derivation drv = parseDerivation(readFile(path));
+        Value w;
+        state.mkAttrs(w, 1 + drv.outputs.size());
+        mkString(*state.allocAttr(w, state.sDrvPath), path, singleton<PathSet>("=" + path));
+        state.mkList(*state.allocAttr(w, state.symbols.create("outputs")), drv.outputs.size());
+        unsigned int outputs_index = 0;
+
+        Value * outputsVal = w.attrs->find(state.symbols.create("outputs"))->value;
+        foreach (DerivationOutputs::iterator, i, drv.outputs) {
+            mkString(*state.allocAttr(w, state.symbols.create(i->first)),
+                i->second.path, singleton<PathSet>("!" + i->first + "!" + path));
+            mkString(*(outputsVal->list.elems[outputs_index++] = state.allocValue()),
+                i->first);
+        }
+        w.attrs->sort();
+        Value fun;
+        state.mkThunk_(fun,
+            state.parseExprFromFile(state.findFile("nix/imported-drv-to-derivation.nix")));
+        state.forceFunction(fun);
+        mkApp(v, fun, w);
+        state.forceAttrs(v);
+    } else {
+        state.evalFile(path, v);
+    }
 }