about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-10-16T16·29+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-10-16T16·29+0000
commit0791282b2f42313c94dd9bc85b24428e585cd099 (patch)
tree38cb57ffea3c700aeed5836afd7927369782d315 /src
parentab5e8767fafb2d62213e3f1558ead2882bc65c05 (diff)
* Substitutes and nix-pull now work again.
* Fixed a segfault caused by the buffering of stderr.
* Fix now allows the specification of the full output path.  This
  should be used with great care, since it by-passes the normal hash
  generation.
* Incremented the version number to 0.4 (prerelease).

Diffstat (limited to 'src')
-rw-r--r--src/dotgraph.cc5
-rw-r--r--src/expr.cc8
-rw-r--r--src/expr.hh3
-rw-r--r--src/fix.cc12
-rw-r--r--src/normalise.cc53
-rw-r--r--src/normalise.hh8
-rw-r--r--src/shared.cc3
-rw-r--r--src/store.cc14
-rw-r--r--src/store.hh3
9 files changed, 79 insertions, 30 deletions
diff --git a/src/dotgraph.cc b/src/dotgraph.cc
index 514fda325914..36daf7f9966d 100644
--- a/src/dotgraph.cc
+++ b/src/dotgraph.cc
@@ -1,4 +1,5 @@
 #include "dotgraph.hh"
+#include "normalise.hh"
 
 
 static string dotQuote(const string & s)
@@ -98,8 +99,8 @@ void printDotGraph(const PathSet & roots)
 
 	if (doneSet.find(nePath) == doneSet.end()) {
 	    doneSet.insert(nePath);
-                    
-	    NixExpr ne = parseNixExpr(termFromPath(nePath));
+
+	    NixExpr ne = exprFromPath(nePath);
 
 	    string label, colour;
                     
diff --git a/src/expr.cc b/src/expr.cc
index cfc4af1f39a8..cead803425ba 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -22,14 +22,6 @@ Hash hashTerm(ATerm t)
 }
 
 
-ATerm termFromPath(const Path & path)
-{
-    ATerm t = ATreadFromNamedFile(path.c_str());
-    if (!t) throw Error(format("cannot read aterm from `%1%'") % path);
-    return t;
-}
-
-
 Path writeTerm(ATerm t, const string & suffix)
 {
     /* The id of a term is its hash. */
diff --git a/src/expr.hh b/src/expr.hh
index b345643223cc..7d0420935f9d 100644
--- a/src/expr.hh
+++ b/src/expr.hh
@@ -53,9 +53,6 @@ Error badTerm(const format & f, ATerm t);
 /* Hash an aterm. */
 Hash hashTerm(ATerm t);
 
-/* Read an aterm from disk. */
-ATerm termFromPath(const Path & path);
-
 /* Write an aterm to the Nix store directory, and return its path. */
 Path writeTerm(ATerm t, const string & suffix);
 
diff --git a/src/fix.cc b/src/fix.cc
index cbf759b31763..c1f9c1ad68d0 100644
--- a/src/fix.cc
+++ b/src/fix.cc
@@ -299,6 +299,7 @@ static Expr evalExpr2(EvalState & state, Expr e)
         ne.type = NixExpr::neDerivation;
         ne.derivation.platform = SYSTEM;
         string name;
+        Path outPath;
         Hash outHash;
         bool outHashGiven = false;
         bnds = ATempty;
@@ -327,6 +328,7 @@ static Expr evalExpr2(EvalState & state, Expr e)
 
                 if (key == "build") ne.derivation.builder = s;
                 if (key == "name") name = s;
+                if (key == "outPath") outPath = s;
                 if (key == "id") { 
                     outHash = parseHash(s);
                     outHashGiven = true;
@@ -343,11 +345,13 @@ static Expr evalExpr2(EvalState & state, Expr e)
         if (name == "")
             throw badTerm("no package name specified", e);
         
-        /* Hash the Nix expression with no outputs to produce a
-           unique but deterministic path name for this package. */
+        /* Determine the output path. */
         if (!outHashGiven) outHash = hashPackage(state, ne);
-        Path outPath = 
-            canonPath(nixStore + "/" + ((string) outHash).c_str() + "-" + name);
+        if (outPath == "")
+            /* Hash the Nix expression with no outputs to produce a
+               unique but deterministic path name for this package. */
+            outPath = 
+                canonPath(nixStore + "/" + ((string) outHash).c_str() + "-" + name);
         ne.derivation.env["out"] = outPath;
         ne.derivation.outputs.insert(outPath);
 
diff --git a/src/normalise.cc b/src/normalise.cc
index 160130d96634..be71081ffb25 100644
--- a/src/normalise.cc
+++ b/src/normalise.cc
@@ -122,7 +122,7 @@ Path normaliseNixExpr(const Path & _nePath, PathSet pending)
     Path nePath = useSuccessor(_nePath);
 
     /* Get the Nix expression. */
-    NixExpr ne = parseNixExpr(termFromPath(nePath));
+    NixExpr ne = exprFromPath(nePath, pending);
 
     /* If this is a normal form (i.e., a closure) we are done. */
     if (ne.type == NixExpr::neClosure) return nePath;
@@ -172,7 +172,7 @@ Path normaliseNixExpr(const Path & _nePath, PathSet pending)
     {
         Path nePath2 = useSuccessor(nePath);
         if (nePath != nePath2) {
-            NixExpr ne = parseNixExpr(termFromPath(nePath2));
+            NixExpr ne = exprFromPath(nePath2, pending);
             debug(format("skipping build of expression `%1%', someone beat us to it")
 		  % (string) nePath);
             if (ne.type != NixExpr::neClosure) abort();
@@ -193,7 +193,7 @@ Path normaliseNixExpr(const Path & _nePath, PathSet pending)
         realiseClosure(nfPath, pending);
         /* !!! nfPath should be a root of the garbage collector while
            we are building */
-        NixExpr ne = parseNixExpr(termFromPath(nfPath));
+        NixExpr ne = exprFromPath(nfPath, pending);
         if (ne.type != NixExpr::neClosure) abort();
         for (ClosureElems::iterator j = ne.closure.elems.begin();
              j != ne.closure.elems.end(); j++)
@@ -364,16 +364,49 @@ void realiseClosure(const Path & nePath, PathSet pending)
 {
     Nest nest(lvlDebug, format("realising closure `%1%'") % nePath);
 
-    NixExpr ne = parseNixExpr(termFromPath(nePath));
+    NixExpr ne = exprFromPath(nePath, pending);
     if (ne.type != NixExpr::neClosure)
         throw Error(format("expected closure in `%1%'") % nePath);
     
     for (ClosureElems::const_iterator i = ne.closure.elems.begin();
          i != ne.closure.elems.end(); i++)
-        assert(isValidPath(i->first));
-#if 0
-        expandId(i->second.id, i->first, "/", pending);
-#endif
+        ensurePath(i->first, pending);
+}
+
+
+void ensurePath(const Path & path, PathSet pending)
+{
+    /* If the path is already valid, we're done. */
+    if (isValidPath(path)) return;
+    
+    /* Otherwise, try the substitutes. */
+    Paths subPaths = querySubstitutes(path);
+
+    for (Paths::iterator i = subPaths.begin(); 
+         i != subPaths.end(); i++)
+    {
+        try {
+            normaliseNixExpr(*i, pending);
+            if (isValidPath(path)) return;
+            throw Error(format("substitute failed to produce expected output path"));
+        } catch (Error & e) {
+            msg(lvlTalkative, 
+                format("building of substitute `%1%' for `%2%' failed: %3%")
+                % *i % path % e.what());
+        }
+    }
+
+    throw Error(format("path `%1%' is required, "
+        "but there are no (successful) substitutes") % path);
+}
+
+
+NixExpr exprFromPath(const Path & path, PathSet pending)
+{
+    ensurePath(path, pending);
+    ATerm t = ATreadFromNamedFile(path.c_str());
+    if (!t) throw Error(format("cannot read aterm from `%1%'") % path);
+    return parseNixExpr(t);
 }
 
 
@@ -381,7 +414,7 @@ PathSet nixExprRoots(const Path & nePath)
 {
     PathSet paths;
 
-    NixExpr ne = parseNixExpr(termFromPath(nePath));
+    NixExpr ne = exprFromPath(nePath);
 
     if (ne.type == NixExpr::neClosure)
         paths.insert(ne.closure.roots.begin(), ne.closure.roots.end());
@@ -401,7 +434,7 @@ static void requisitesWorker(const Path & nePath,
     if (doneSet.find(nePath) != doneSet.end()) return;
     doneSet.insert(nePath);
 
-    NixExpr ne = parseNixExpr(termFromPath(nePath));
+    NixExpr ne = exprFromPath(nePath);
 
     if (ne.type == NixExpr::neClosure)
         for (ClosureElems::iterator i = ne.closure.elems.begin();
diff --git a/src/normalise.hh b/src/normalise.hh
index e8e72f5bc857..bbe846404cc0 100644
--- a/src/normalise.hh
+++ b/src/normalise.hh
@@ -18,6 +18,14 @@ Path normaliseNixExpr(const Path & nePath, PathSet pending = PathSet());
    its output paths through substitutes... kaboom!). */
 void realiseClosure(const Path & nePath, PathSet pending = PathSet());
 
+/* Ensure that a path exists, possibly by instantiating it by
+   realising a substitute. */
+void ensurePath(const Path & path, PathSet pending = PathSet());
+
+/* Read a Nix expression, after ensuring its existence through
+   ensurePath(). */
+NixExpr exprFromPath(const Path & path, PathSet pending = PathSet());
+
 /* Get the list of root (output) paths of the given Nix expression. */
 PathSet nixExprRoots(const Path & nePath);
 
diff --git a/src/shared.cc b/src/shared.cc
index dcda0b50abe6..80463308a3f0 100644
--- a/src/shared.cc
+++ b/src/shared.cc
@@ -47,6 +47,8 @@ static void initAndRun(int argc, char * * argv)
 }
 
 
+static char buf[1024];
+
 int main(int argc, char * * argv)
 {
     /* ATerm setup. */
@@ -54,7 +56,6 @@ int main(int argc, char * * argv)
     ATinit(argc, argv, &bottomOfStack);
 
     /* Turn on buffering for cerr. */
-    char buf[1024];
     cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));
 
     try {
diff --git a/src/store.cc b/src/store.cc
index 7f10c6377dc6..2d223313b612 100644
--- a/src/store.cc
+++ b/src/store.cc
@@ -175,7 +175,8 @@ void registerSuccessor(const Transaction & txn,
 
     Paths revs;
     nixDB.queryStrings(txn, dbSuccessorsRev, sucPath, revs);
-    revs.push_back(srcPath);
+    if (find(revs.begin(), revs.end(), srcPath) == revs.end())
+        revs.push_back(srcPath);
 
     nixDB.setString(txn, dbSuccessors, srcPath, sucPath);
     nixDB.setStrings(txn, dbSuccessorsRev, sucPath, revs);
@@ -212,7 +213,8 @@ void registerSubstitute(const Path & srcPath, const Path & subPath)
 
     Paths revs;
     nixDB.queryStrings(txn, dbSubstitutesRev, subPath, revs);
-    revs.push_back(srcPath);
+    if (find(revs.begin(), revs.end(), srcPath) == revs.end())
+        revs.push_back(srcPath);
     
     nixDB.setStrings(txn, dbSubstitutes, srcPath, subs);
     nixDB.setStrings(txn, dbSubstitutesRev, subPath, revs);
@@ -221,6 +223,14 @@ void registerSubstitute(const Path & srcPath, const Path & subPath)
 }
 
 
+Paths querySubstitutes(const Path & srcPath)
+{
+    Paths subPaths;
+    nixDB.queryStrings(noTxn, dbSubstitutes, srcPath, subPaths);
+    return subPaths;
+}
+
+
 void registerValidPath(const Transaction & txn, const Path & _path)
 {
     Path path(canonPath(_path));
diff --git a/src/store.hh b/src/store.hh
index 3d7575c3e86c..dab3d603f802 100644
--- a/src/store.hh
+++ b/src/store.hh
@@ -42,6 +42,9 @@ Paths queryPredecessors(const Path & sucPath);
 /* Register a substitute. */
 void registerSubstitute(const Path & srcPath, const Path & subPath);
 
+/* Return the substitutes expression for the given path. */
+Paths querySubstitutes(const Path & srcPath);
+
 /* Register the validity of a path. */
 void registerValidPath(const Transaction & txn, const Path & path);