about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-01-19T11·16+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-01-19T11·16+0000
commit863dcff6c5ffc163010ec1f9e6819bb9aaaadc29 (patch)
tree4747222c7f8c471e6cbfa07c49023853d2f6b957 /src/libexpr/primops.cc
parente9762e2d10c4a837e3d75d53e3a24452f07f47ec (diff)
* Started removing closure store expressions, i.e., the explicit
  representation of closures as ATerms in the Nix store.  Instead, the
  file system pointer graph is now stored in the Nix database.  This
  has many advantages:

  - It greatly simplifies the implementation (we can drop the notion
    of `successors', and so on).

  - It makes registering roots for the garbage collector much easier.
    Instead of specifying the closure expression as a root, you can
    simply specify the store path that must be retained as a root.
    This could not be done previously, since there was no way to find
    the closure store expression containing a given store path.
    
  - Better traceability: it is now possible to query what paths are
    referenced by a path, and what paths refer to a path.

Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r--src/libexpr/primops.cc149
1 files changed, 56 insertions, 93 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index b85cdbadd8..28bbd2859a 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -16,6 +16,7 @@ static Expr primImport(EvalState & state, const ATermVector & args)
 }
 
 
+#if 0
 static PathSet storeExprRootsCached(EvalState & state, const Path & nePath)
 {
     DrvRoots::iterator i = state.drvRoots.find(nePath);
@@ -27,6 +28,7 @@ static PathSet storeExprRootsCached(EvalState & state, const Path & nePath)
         return paths;
     }
 }
+#endif
 
 
 /* Returns the hash of a derivation modulo fixed-output
@@ -49,83 +51,42 @@ static PathSet storeExprRootsCached(EvalState & state, const Path & nePath)
    paths have been replaced by the result of a recursive call to this
    function, and that for fixed-output derivations we return
    (basically) its outputHash. */
-static Hash hashDerivationModulo(EvalState & state, StoreExpr ne)
+static Hash hashDerivationModulo(EvalState & state, Derivation drv)
 {
-    if (ne.type == StoreExpr::neDerivation) {
-
-        /* Return a fixed hash for fixed-output derivations. */
-        if (ne.derivation.outputs.size() == 1) {
-            DerivationOutputs::iterator i = ne.derivation.outputs.begin();
-            if (i->first == "out" &&
-                i->second.hash != "")
-            {
-                return hashString(htSHA256, "fixed:out:"
-                    + i->second.hashAlgo + ":"
-                    + i->second.hash + ":"
-                    + i->second.path);
-            }
+    /* Return a fixed hash for fixed-output derivations. */
+    if (drv.outputs.size() == 1) {
+        DerivationOutputs::const_iterator i = drv.outputs.begin();
+        if (i->first == "out" &&
+            i->second.hash != "")
+        {
+            return hashString(htSHA256, "fixed:out:"
+                + i->second.hashAlgo + ":"
+                + i->second.hash + ":"
+                + i->second.path);
         }
+    }
 
-        /* For other derivations, replace the inputs paths with
-           recursive calls to this function.*/
-	PathSet inputs2;
-        for (PathSet::iterator i = ne.derivation.inputs.begin();
-             i != ne.derivation.inputs.end(); ++i)
-        {
-            Hash h = state.drvHashes[*i];
-            if (h.type == htUnknown) {
-                StoreExpr ne2 = storeExprFromPath(*i);
-                h = hashDerivationModulo(state, ne2);
-                state.drvHashes[*i] = h;
-            }
-            inputs2.insert(printHash(h));
+    /* For other derivations, replace the inputs paths with recursive
+       calls to this function.*/
+    PathSet inputs2;
+    for (PathSet::iterator i = drv.inputDrvs.begin();
+         i != drv.inputDrvs.end(); ++i)
+    {
+        Hash h = state.drvHashes[*i];
+        if (h.type == htUnknown) {
+            Derivation drv2 = derivationFromPath(*i);
+            h = hashDerivationModulo(state, drv2);
+            state.drvHashes[*i] = h;
         }
-	ne.derivation.inputs = inputs2;
+        inputs2.insert(printHash(h));
     }
+    drv.inputDrvs = inputs2;
     
-    return hashTerm(unparseStoreExpr(ne));
-}
-
-
-static Path copyAtom(EvalState & state, const Path & srcPath)
-{
-    /* !!! should be cached */
-    Path dstPath(addToStore(srcPath));
-
-    ClosureElem elem;
-    StoreExpr ne;
-    ne.type = StoreExpr::neClosure;
-    ne.closure.roots.insert(dstPath);
-    ne.closure.elems[dstPath] = elem;
-
-    Path drvPath = writeTerm(unparseStoreExpr(ne), "c");
-
-    /* !!! can we get rid of drvRoots? */
-    state.drvRoots[drvPath] = ne.closure.roots;
-
-    /* Optimisation, but required in read-only mode! because in that
-       case we don't actually write store expressions, so we can't
-       read them later. */
-    state.drvHashes[drvPath] = hashDerivationModulo(state, ne);
-
-    printMsg(lvlChatty, format("copied `%1%' -> closure `%2%'")
-        % srcPath % drvPath);
-    return drvPath;
-}
-
-
-static string addInput(EvalState & state, 
-    Path & nePath, StoreExpr & ne)
-{
-    PathSet paths = storeExprRootsCached(state, nePath);
-    if (paths.size() != 1) abort();
-    Path path = *(paths.begin());
-    ne.derivation.inputs.insert(nePath);
-    return path;
+    return hashTerm(unparseDerivation(drv));
 }
 
 
-static void processBinding(EvalState & state, Expr e, StoreExpr & ne,
+static void processBinding(EvalState & state, Expr e, Derivation & drv,
     Strings & ss)
 {
     e = evalExpr(state, e);
@@ -155,25 +116,28 @@ static void processBinding(EvalState & state, Expr e, StoreExpr & ne,
 
             a = queryAttr(e, "outPath");
             if (!a) throw Error("output path missing");
-            PathSet drvRoots;
-            drvRoots.insert(evalPath(state, a));
-            
-            state.drvRoots[drvPath] = drvRoots;
+            /* !!! supports only single output path */
+            Path outPath = evalPath(state, a);
 
-            ss.push_back(addInput(state, drvPath, ne));
+            drv.inputDrvs.insert(drvPath);
+            ss.push_back(outPath);
         } else
             throw Error("invalid derivation attribute");
     }
 
     else if (matchPath(e, s)) {
-        Path drvPath = copyAtom(state, aterm2String(s));
-        ss.push_back(addInput(state, drvPath, ne));
+        Path srcPath(aterm2String(s));
+        Path dstPath(addToStore(srcPath));
+        printMsg(lvlChatty, format("copied source `%1%' -> `%2%'")
+            % srcPath % dstPath);
+        drv.inputSrcs.insert(dstPath);
+        ss.push_back(dstPath);
     }
     
     else if (matchList(e, es)) {
         for (ATermIterator i(es); i; ++i) {
             startNest(nest, lvlVomit, format("processing list element"));
-	    processBinding(state, evalExpr(state, *i), ne, ss);
+	    processBinding(state, evalExpr(state, *i), drv, ss);
         }
     }
 
@@ -181,7 +145,7 @@ static void processBinding(EvalState & state, Expr e, StoreExpr & ne,
 
     else if (matchSubPath(e, e1, e2)) {
         Strings ss2;
-        processBinding(state, evalExpr(state, e1), ne, ss2);
+        processBinding(state, evalExpr(state, e1), drv, ss2);
         if (ss2.size() != 1)
             throw Error("left-hand side of `~' operator cannot be a list");
         e2 = evalExpr(state, e2);
@@ -223,8 +187,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
     queryAllAttrs(args, attrs, true);
 
     /* Build the derivation expression by processing the attributes. */
-    StoreExpr ne;
-    ne.type = StoreExpr::neDerivation;
+    Derivation drv;
 
     string drvName;
     
@@ -241,7 +204,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
 
         Strings ss;
         try {
-            processBinding(state, value, ne, ss);
+            processBinding(state, value, drv, ss);
         } catch (Error & e) {
             throw Error(format("while processing the derivation attribute `%1%' at %2%:\n%3%")
                 % key % showPos(pos) % e.msg());
@@ -251,16 +214,16 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
            command-line arguments to the builder. */
         if (key == "args") {
             for (Strings::iterator i = ss.begin(); i != ss.end(); ++i)
-                ne.derivation.args.push_back(*i);
+                drv.args.push_back(*i);
         }
 
         /* All other attributes are passed to the builder through the
            environment. */
         else {
             string s = concatStrings(ss);
-            ne.derivation.env[key] = s;
-            if (key == "builder") ne.derivation.builder = s;
-            else if (key == "system") ne.derivation.platform = s;
+            drv.env[key] = s;
+            if (key == "builder") drv.builder = s;
+            else if (key == "system") drv.platform = s;
             else if (key == "name") drvName = s;
             else if (key == "outputHash") outputHash = s;
             else if (key == "outputHashAlgo") outputHashAlgo = s;
@@ -268,9 +231,9 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
     }
     
     /* Do we have all required attributes? */
-    if (ne.derivation.builder == "")
+    if (drv.builder == "")
         throw Error("required attribute `builder' missing");
-    if (ne.derivation.platform == "")
+    if (drv.platform == "")
         throw Error("required attribute `system' missing");
     if (drvName == "")
         throw Error("required attribute `name' missing");
@@ -312,22 +275,22 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
        paths are empty, and the corresponding environment variables
        have an empty value.  This ensures that changes in the set of
        output names do get reflected in the hash. */
-    ne.derivation.env["out"] = "";
-    ne.derivation.outputs["out"] =
+    drv.env["out"] = "";
+    drv.outputs["out"] =
         DerivationOutput("", outputHashAlgo, outputHash);
         
     /* Use the masked derivation expression to compute the output
        path. */
     Path outPath = makeStorePath("output:out",
-        hashDerivationModulo(state, ne), drvName);
+        hashDerivationModulo(state, drv), drvName);
 
     /* Construct the final derivation store expression. */
-    ne.derivation.env["out"] = outPath;
-    ne.derivation.outputs["out"] =
+    drv.env["out"] = outPath;
+    drv.outputs["out"] =
         DerivationOutput(outPath, outputHashAlgo, outputHash);
 
     /* Write the resulting term into the Nix store directory. */
-    Path drvPath = writeTerm(unparseStoreExpr(ne), "d-" + drvName);
+    Path drvPath = writeTerm(unparseDerivation(drv), "d-" + drvName);
 
     printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
         % drvName % drvPath);
@@ -335,7 +298,7 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
     /* Optimisation, but required in read-only mode! because in that
        case we don't actually write store expressions, so we can't
        read them later. */
-    state.drvHashes[drvPath] = hashDerivationModulo(state, ne);
+    state.drvHashes[drvPath] = hashDerivationModulo(state, drv);
 
     /* !!! assumes a single output */
     attrs.set("outPath", makeAttrRHS(makePath(toATerm(outPath)), makeNoPos()));