about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-05-08T10·32+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-05-08T10·32+0000
commitedd145d2fb2960fab414bfe2c4a1221b976815ea (patch)
tree385e57aa0b8135cf2200e0ee9b15a75a02ae1f4a
parent426593162ee4b22443dfca428083047ca1e39ac7 (diff)
* Lazily compute the derivation and output paths of derivations. This
  makes most query and installation operations much faster (e.g.,
  `nix-env -qa' on the current Nixpkgs is about 10 times faster).

-rw-r--r--src/nix-env/main.cc103
1 files changed, 63 insertions, 40 deletions
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 0d84bc610dfd..6ff80992c39e 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -51,11 +51,24 @@ struct UserEnvElem
 {
     string name;
     string system;
-    Path drvPath;
-    Path outPath;
+
+    ATermMap attrs;
+
+    string queryDrvPath(EvalState & state) const 
+    {
+        Expr a = attrs.get("drvPath");
+        return a ? evalPath(state, a) : "";
+    }
+    
+    string queryOutPath(EvalState & state) const
+    {
+        Expr a = attrs.get("outPath");
+        if (!a) throw Error("output path missing");
+        return evalPath(state, a);
+    }
 };
 
-typedef map<Path, UserEnvElem> UserEnvElems;
+typedef map<unsigned int, UserEnvElem> UserEnvElems;
 
 
 void printHelp()
@@ -69,30 +82,32 @@ static bool parseDerivation(EvalState & state, Expr e, UserEnvElem & elem)
     ATermList es;
     e = evalExpr(state, e);
     if (!matchAttrs(e, es)) return false;
-    Expr a = queryAttr(e, "type");
+
+    ATermMap attrs;
+    queryAllAttrs(e, attrs, false);
+    
+    Expr a = attrs.get("type");
     if (!a || evalString(state, a) != "derivation") return false;
 
-    a = queryAttr(e, "name");
+    a = attrs.get("name");
     if (!a) throw badTerm("derivation name missing", e);
     elem.name = evalString(state, a);
 
-    a = queryAttr(e, "system");
+    a = attrs.get("system");
     if (!a)
         elem.system = "unknown";
     else
         elem.system = evalString(state, a);
 
-    a = queryAttr(e, "drvPath");
-    if (a) elem.drvPath = evalPath(state, a);
-
-    a = queryAttr(e, "outPath");
-    if (!a) throw badTerm("output path missing", e);
-    elem.outPath = evalPath(state, a);
+    elem.attrs = attrs;
 
     return true;
 }
 
 
+static unsigned int elemCounter = 0;
+
+
 static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
 {
     ATermList es;
@@ -101,15 +116,15 @@ static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
     e = evalExpr(state, e);
 
     if (parseDerivation(state, e, elem)) 
-        elems[elem.outPath] = elem;
+        elems[elemCounter++] = elem;
 
     else if (matchAttrs(e, es)) {
         ATermMap drvMap;
         queryAllAttrs(e, drvMap);
         for (ATermIterator i(drvMap.keys()); i; ++i) {
-            debug(format("evaluating attribute `%1%'") % *i);
+            debug(format("evaluating attribute `%1%'") % aterm2String(*i));
             if (parseDerivation(state, drvMap.get(*i), elem))
-                elems[elem.outPath] = elem;
+                elems[elemCounter++] = elem;
             else
                 parseDerivations(state, drvMap.get(*i), elems);
         }
@@ -119,7 +134,7 @@ static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
         for (ATermIterator i(es); i; ++i) {
             debug(format("evaluating list element"));
             if (parseDerivation(state, *i, elem))
-                elems[elem.outPath] = elem;
+                elems[elemCounter++] = elem;
             else
                 parseDerivations(state, *i, elems);
         }
@@ -200,8 +215,9 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
          i != elems.end(); ++i)
         /* Call to `isDerivation' is for compatibility with Nix <= 0.7
            user environments. */
-        if (i->second.drvPath != "" && isDerivation(i->second.drvPath))
-            drvsToBuild.insert(i->second.drvPath);
+        if (i->second.queryDrvPath(state) != "" &&
+            isDerivation(i->second.queryDrvPath(state)))
+            drvsToBuild.insert(i->second.queryDrvPath(state));
 
     debug(format("building user environment dependencies"));
     buildDerivations(drvsToBuild);
@@ -217,7 +233,7 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
     for (UserEnvElems::const_iterator i = elems.begin(); 
          i != elems.end(); ++i)
     {
-        Path drvPath = keepDerivations ? i->second.drvPath : "";
+        Path drvPath = keepDerivations ? i->second.queryDrvPath(state) : "";
         ATerm t = makeAttrs(ATmakeList5(
             makeBind(toATerm("type"),
                 makeStr(toATerm("derivation")), makeNoPos()),
@@ -228,17 +244,17 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
             makeBind(toATerm("drvPath"),
                 makePath(toATerm(drvPath)), makeNoPos()),
             makeBind(toATerm("outPath"),
-                makePath(toATerm(i->second.outPath)), makeNoPos())
+                makePath(toATerm(i->second.queryOutPath(state))), makeNoPos())
             ));
         manifest = ATinsert(manifest, t);
-        inputs = ATinsert(inputs, makeStr(toATerm(i->second.outPath)));
+        inputs = ATinsert(inputs, makeStr(toATerm(i->second.queryOutPath(state))));
 
         /* This is only necessary when installing store paths, e.g.,
            `nix-env -i /nix/store/abcd...-foo'. */
-        addTempRoot(i->second.outPath);
-        ensurePath(i->second.outPath);
+        addTempRoot(i->second.queryOutPath(state));
+        ensurePath(i->second.queryOutPath(state));
         
-        references.insert(i->second.outPath);
+        references.insert(i->second.queryOutPath(state));
         if (drvPath != "") references.insert(drvPath);
     }
 
@@ -269,11 +285,11 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
     
     /* Realise the resulting store expression. */
     debug(format("building user environment"));
-    buildDerivations(singleton<PathSet>(topLevelDrv.drvPath));
+    buildDerivations(singleton<PathSet>(topLevelDrv.queryDrvPath(state)));
 
     /* Switch the current user environment to the output path. */
     debug(format("switching to new user environment"));
-    Path generation = createGeneration(profile, topLevelDrv.outPath);
+    Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state));
     switchLink(profile, generation);
 }
 
@@ -378,17 +394,17 @@ static void queryInstSources(EvalState & state,
                     name = string(name, dash + 1);
 
                 if (isDerivation(*i)) {
-                    elem.drvPath = *i;
-                    elem.outPath = findOutput(derivationFromPath(*i), "out");
+                    elem.queryDrvPath(state) = *i;
+                    elem.queryOutPath(state) = findOutput(derivationFromPath(*i), "out");
                     if (name.size() >= drvExtension.size() &&
                         string(name, name.size() - drvExtension.size()) == drvExtension)
                         name = string(name, 0, name.size() - drvExtension.size());
                 }
-                else elem.outPath = *i;
+                else elem.queryOutPath(state) = *i;
 
                 elem.name = name;
 
-                elems[elem.outPath] = elem;
+                elems[elemCounter++] = elem;
             }
             
             break;
@@ -511,7 +527,8 @@ static void upgradeDerivations(Globals & globals,
         }
 
         if (bestElem != availElems.end() &&
-            i->second.outPath != bestElem->second.outPath)
+            i->second.queryOutPath(globals.state) !=
+                bestElem->second.queryOutPath(globals.state))
         {
             printMsg(lvlInfo,
                 format("upgrading `%1%' to `%2%'")
@@ -678,10 +695,15 @@ static void opQuery(Globals & globals,
 
     /* We only need to know the installed paths when we are querying
        the status of the derivation. */
-    UserEnvElems installed; /* installed paths */
+    PathSet installed; /* installed paths */
     
-    if (printStatus)
-        installed = queryInstalled(globals.state, globals.profile);
+    if (printStatus) {
+        UserEnvElems installedElems; 
+        installedElems = queryInstalled(globals.state, globals.profile);
+        for (UserEnvElems::iterator i = installedElems.begin();
+             i != installedElems.end(); ++i)
+            installed.insert(i->second.queryOutPath(globals.state));
+    }
             
     /* Print the desired columns. */
     Table table;
@@ -692,11 +714,11 @@ static void opQuery(Globals & globals,
         Strings columns;
         
         if (printStatus) {
-            Substitutes subs = querySubstitutes(noTxn, i->drvPath);
+            Substitutes subs = querySubstitutes(noTxn, i->queryDrvPath(globals.state));
             columns.push_back(
-                (string) (installed.find(i->outPath)
+                (string) (installed.find(i->queryOutPath(globals.state))
                     != installed.end() ? "I" : "-")
-                + (isValidPath(i->outPath) ? "P" : "-")
+                + (isValidPath(i->queryOutPath(globals.state)) ? "P" : "-")
                 + (subs.size() > 0 ? "S" : "-"));
         }
 
@@ -704,10 +726,11 @@ static void opQuery(Globals & globals,
 
         if (printSystem) columns.push_back(i->system);
 
-        if (printDrvPath) columns.push_back(i->drvPath == "" ? "-" : i->drvPath);
+        if (printDrvPath) columns.push_back(
+            i->queryDrvPath(globals.state) == ""
+            ? "-" : i->queryDrvPath(globals.state));
         
-        if (printOutPath) columns.push_back(i->outPath);
-
+        if (printOutPath) columns.push_back(i->queryOutPath(globals.state));
         table.push_back(columns);
     }