about summary refs log tree commit diff
path: root/src/eval.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.cc')
-rw-r--r--src/eval.cc80
1 files changed, 67 insertions, 13 deletions
diff --git a/src/eval.cc b/src/eval.cc
index a1b8db6e0732..4eb222197d38 100644
--- a/src/eval.cc
+++ b/src/eval.cc
@@ -25,7 +25,7 @@ bool pathExists(const string & path)
     res = stat(path.c_str(), &st);
     if (!res) return true;
     if (errno != ENOENT)
-        throw SysError("getting status of " + path);
+        throw SysError(format("getting status of %1%") % path);
     return false;
 }
 
@@ -105,7 +105,7 @@ static void runProgram(const string & program, Environment env)
             throw SysError(format("unable to execute %1%") % program);
             
         } catch (exception & e) {
-            cerr << "build error: " << e.what() << endl;
+            cerr << format("build error: %1%\n") % e.what();
         }
         _exit(1);
 
@@ -199,15 +199,62 @@ struct RStatus
 };
 
 
+static ATerm termFromHash(const Hash & hash)
+{
+    string path = queryFromStore(hash);
+    ATerm t = ATreadFromNamedFile(path.c_str());
+    if (!t) throw Error(format("cannot read aterm %1%") % path);
+    return t;
+}
+
+
+static Hash writeTerm(ATerm t)
+{
+    string path = nixStore + "/tmp.nix"; /* !!! */
+    if (!ATwriteToNamedTextFile(t, path.c_str()))
+        throw Error(format("cannot write aterm %1%") % path);
+    Hash hash = hashPath(path);
+    string path2 = nixStore + "/" + (string) hash + ".nix";
+    if (rename(path.c_str(), path2.c_str()) == -1)
+        throw SysError(format("renaming %1% to %2%") % path % path2);
+    setDB(nixDB, dbRefs, hash, path2);
+    return hash;
+}
+
+
 static FState realise(RStatus & status, FState fs)
 {
     char * s1, * s2, * s3;
     Content content;
-    ATermList refs, ins, outs, bnds;
+    ATermList refs, ins, bnds;
+
+    /* First repeatedly try to substitute $fs$ by any known successors
+       in order to speed up the rewrite process. */
+    {
+        string fsHash, scHash;
+        while (queryDB(nixDB, dbSuccessors, fsHash = hashTerm(fs), scHash)) {
+            debug(format("successor %1% -> %2%") % (string) fsHash % scHash);
+            FState fs2 = termFromHash(parseHash(scHash));
+            if (fs == fs2) {
+                debug(format("successor cycle detected in %1%") % printTerm(fs));
+                break;
+            }
+            fs = fs2;
+        }
+    }
+
+    /* Fall through. */
+
+    if (ATmatch(fs, "Include(<str>)", &s1)) {
+        return realise(status, termFromHash(parseHash(s1)));
+    }
     
-    if (ATmatch(fs, "File(<str>, <term>, [<list>])", &s1, &content, &refs)) {
+    else if (ATmatch(fs, "File(<str>, <term>, [<list>])", &s1, &content, &refs)) {
         string path(s1);
 
+        msg(format("realising atomic path %1%") % path);
+        Nest nest(true);
+
         if (path[0] != '/') throw Error("absolute path expected: " + path);
 
         /* Realise referenced paths. */
@@ -223,9 +270,15 @@ static FState realise(RStatus & status, FState fs)
         Hash hash = parseHash(s1);
 
         /* Normal form. */
-        ATerm nf = ATmake("File(<str>, <term>, <list>)",
+        ATerm nf = ATmake("File(<str>, <term>, <term>)",
             path.c_str(), content, refs2);
 
+        /* Register the normal form. */
+        if (fs != nf) {
+            Hash nfHash = writeTerm(nf);
+            setDB(nixDB, dbSuccessors, hashTerm(fs), nfHash);
+        }
+
         /* Perhaps the path already exists and has the right hash? */
         if (pathExists(path)) {
             if (hash == hashPath(path)) {
@@ -250,6 +303,9 @@ static FState realise(RStatus & status, FState fs)
     {
         string platform(s1), builder(s2), outPath(s3);
 
+        msg(format("realising derivate path %1%") % outPath);
+        Nest nest(true);
+
         checkPlatform(platform);
         
         /* Realise inputs. */
@@ -297,15 +353,13 @@ static FState realise(RStatus & status, FState fs)
            values.cc. */
         setDB(nixDB, dbRefs, outHash, outPath);
 
-#if 0
-        /* Register that targetHash was produced by evaluating
-           sourceHash; i.e., that targetHash is a normal form of
-           sourceHash. !!! this shouldn't be here */
-        setDB(nixDB, dbNFs, sourceHash, targetHash);
-#endif
-
-        return ATmake("File(<str>, Hash(<str>), <list>)",
+        /* Register the normal form of fs. */
+        FState nf = ATmake("File(<str>, Hash(<str>), <term>)",
             outPath.c_str(), ((string) outHash).c_str(), ins2);
+        Hash nfHash = writeTerm(nf);
+        setDB(nixDB, dbSuccessors, hashTerm(fs), nfHash);
+
+        return nf;
     }
 
     throw badTerm("bad file system state expression", fs);