summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-02-08 13:21:16 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-02-08 13:21:16 +0000
commit39f50db731bb1924d3c18b153dfe4258208b8812 (patch)
treeb0a4c793d826353580de19e0151cfa6a8096ca3a
parent4db4b61380d94c2626b7c4ee2e613b6b6223f803 (diff)
downloadguix-39f50db731bb1924d3c18b153dfe4258208b8812.tar.gz
* Refactoring: move derivation evaluation to libexpr.
-rw-r--r--src/libexpr/Makefile.am3
-rw-r--r--src/libexpr/get-drvs.cc67
-rw-r--r--src/libexpr/get-drvs.hh64
-rw-r--r--src/nix-env/main.cc262
4 files changed, 209 insertions, 187 deletions
diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am
index dbc93abd5e..ad95dff1d6 100644
--- a/src/libexpr/Makefile.am
+++ b/src/libexpr/Makefile.am
@@ -3,7 +3,8 @@ lib_LTLIBRARIES = libexpr.la
 libexpr_la_SOURCES = nixexpr.cc nixexpr.hh parser.cc parser.hh \
  eval.cc eval.hh primops.cc \
  lexer-tab.c lexer-tab.h parser-tab.c parser-tab.h \
- nixexpr-ast.hh
+ nixexpr-ast.hh \
+ get-drvs.cc get-drvs.hh
 
 EXTRA_DIST = lexer.l parser.y nixexpr-ast.def nixexpr-ast.cc
 
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
new file mode 100644
index 0000000000..c158a71dff
--- /dev/null
+++ b/src/libexpr/get-drvs.cc
@@ -0,0 +1,67 @@
+#include "get-drvs.hh"
+#include "nixexpr-ast.hh"
+
+
+bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
+{
+    ATermList es;
+    e = evalExpr(state, e);
+    if (!matchAttrs(e, es)) return false;
+
+    ATermMap attrs;
+    queryAllAttrs(e, attrs, false);
+    
+    Expr a = attrs.get("type");
+    if (!a || evalString(state, a) != "derivation") return false;
+
+    a = attrs.get("name");
+    if (!a) throw badTerm("derivation name missing", e);
+    drv.name = evalString(state, a);
+
+    a = attrs.get("system");
+    if (!a)
+        drv.system = "unknown";
+    else
+        drv.system = evalString(state, a);
+
+    drv.attrs = attrs;
+
+    return true;
+}
+
+
+void getDerivations(EvalState & state, Expr e, DrvInfos & drvs)
+{
+    ATermList es;
+    DrvInfo drv;
+
+    e = evalExpr(state, e);
+
+    if (getDerivation(state, e, drv)) 
+        drvs.push_back(drv);
+
+    else if (matchAttrs(e, es)) {
+        ATermMap drvMap;
+        queryAllAttrs(e, drvMap);
+        for (ATermIterator i(drvMap.keys()); i; ++i) {
+            debug(format("evaluating attribute `%1%'") % aterm2String(*i));
+            if (getDerivation(state, drvMap.get(*i), drv))
+                drvs.push_back(drv);
+            else
+                ;
+                //                parseDerivations(state, drvMap.get(*i), drvs);
+        }
+    }
+
+    else if (matchList(e, es)) {
+        for (ATermIterator i(es); i; ++i) {
+            debug(format("evaluating list element"));
+            if (getDerivation(state, *i, drv))
+                drvs.push_back(drv);
+            else
+                getDerivations(state, *i, drvs);
+        }
+    }
+}
+
+
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
new file mode 100644
index 0000000000..bfcff8cca3
--- /dev/null
+++ b/src/libexpr/get-drvs.hh
@@ -0,0 +1,64 @@
+#ifndef __GET_DRVS_H
+#define __GET_DRVS_H
+
+#include <string>
+#include <map>
+
+#include "eval.hh"
+
+
+struct DrvInfo
+{
+private:
+    string drvPath;
+    string outPath;
+    
+public:
+    string name;
+    string system;
+
+    ATermMap attrs;
+
+    string queryDrvPath(EvalState & state) const
+    {
+        if (drvPath == "") {
+            Expr a = attrs.get("drvPath");
+            (string &) drvPath = a ? evalPath(state, a) : "";
+        }
+        return drvPath;
+    }
+    
+    string queryOutPath(EvalState & state) const
+    {
+        if (outPath == "") {
+            Expr a = attrs.get("outPath");
+            if (!a) throw Error("output path missing");
+            (string &) outPath = evalPath(state, a);
+        }
+        return outPath;
+    }
+
+    void setDrvPath(const string & s)
+    {
+        drvPath = s;
+    }
+    
+    void setOutPath(const string & s)
+    {
+        outPath = s;
+    }
+};
+
+
+typedef list<DrvInfo> DrvInfos;
+
+
+/* Evaluate expression `e'.  If it evaluates to a derivation, store
+   information about the derivation in `drv' and return true.
+   Otherwise, return false. */
+bool getDerivation(EvalState & state, Expr e, DrvInfo & drv);
+
+void getDerivations(EvalState & state, Expr e, DrvInfos & drvs);
+
+
+#endif /* !__GET_DRVS_H */
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 043316d112..5d55b3bdbc 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -8,6 +8,7 @@
 #include "eval.hh"
 #include "help.txt.hh"
 #include "nixexpr-ast.hh"
+#include "get-drvs.hh"
 
 #include <cerrno>
 #include <ctime>
@@ -49,133 +50,23 @@ typedef void (* Operation) (Globals & globals,
     Strings opFlags, Strings opArgs);
 
 
-struct UserEnvElem
-{
-private:
-    string drvPath;
-    string outPath;
-    
-public:
-    string name;
-    string system;
-
-    ATermMap attrs;
-
-    string queryDrvPath(EvalState & state) const
-    {
-        if (drvPath == "") {
-            Expr a = attrs.get("drvPath");
-            (string &) drvPath = a ? evalPath(state, a) : "";
-        }
-        return drvPath;
-    }
-    
-    string queryOutPath(EvalState & state) const
-    {
-        if (outPath == "") {
-            Expr a = attrs.get("outPath");
-            if (!a) throw Error("output path missing");
-            (string &) outPath = evalPath(state, a);
-        }
-        return outPath;
-    }
-
-    void setDrvPath(const string & s)
-    {
-        drvPath = s;
-    }
-    
-    void setOutPath(const string & s)
-    {
-        outPath = s;
-    }
-};
-
-typedef map<unsigned int, UserEnvElem> UserEnvElems;
-
-
 void printHelp()
 {
     cout << string((char *) helpText, sizeof helpText);
 }
 
 
-static bool parseDerivation(EvalState & state, Expr e, UserEnvElem & elem)
-{
-    ATermList es;
-    e = evalExpr(state, e);
-    if (!matchAttrs(e, es)) return false;
-
-    ATermMap attrs;
-    queryAllAttrs(e, attrs, false);
-    
-    Expr a = attrs.get("type");
-    if (!a || evalString(state, a) != "derivation") return false;
-
-    a = attrs.get("name");
-    if (!a) throw badTerm("derivation name missing", e);
-    elem.name = evalString(state, a);
-
-    a = attrs.get("system");
-    if (!a)
-        elem.system = "unknown";
-    else
-        elem.system = evalString(state, a);
-
-    elem.attrs = attrs;
-
-    return true;
-}
-
-
-static unsigned int elemCounter = 0;
-
-
-static void parseDerivations(EvalState & state, Expr e, UserEnvElems & elems)
-{
-    ATermList es;
-    UserEnvElem elem;
-
-    e = evalExpr(state, e);
-
-    if (parseDerivation(state, e, 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%'") % aterm2String(*i));
-            if (parseDerivation(state, drvMap.get(*i), elem))
-                elems[elemCounter++] = elem;
-            else
-                parseDerivations(state, drvMap.get(*i), elems);
-        }
-    }
-
-    else if (matchList(e, es)) {
-        for (ATermIterator i(es); i; ++i) {
-            debug(format("evaluating list element"));
-            if (parseDerivation(state, *i, elem))
-                elems[elemCounter++] = elem;
-            else
-                parseDerivations(state, *i, elems);
-        }
-    }
-}
-
-
 static void loadDerivations(EvalState & state, Path nixExprPath,
-    string systemFilter, UserEnvElems & elems)
+    string systemFilter, DrvInfos & elems)
 {
-    parseDerivations(state,
+    getDerivations(state,
         parseExprFromFile(state, absPath(nixExprPath)), elems);
 
     /* Filter out all derivations not applicable to the current
        system. */
-    for (UserEnvElems::iterator i = elems.begin(), j; i != elems.end(); i = j) {
+    for (DrvInfos::iterator i = elems.begin(), j; i != elems.end(); i = j) {
         j = i; j++;
-        if (systemFilter != "*" && i->second.system != systemFilter)
+        if (systemFilter != "*" && i->system != systemFilter)
             elems.erase(i);
     }
 }
@@ -208,12 +99,12 @@ struct AddPos : TermFun
 };
 
 
-static UserEnvElems queryInstalled(EvalState & state, const Path & userEnv)
+static DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
 {
     Path path = userEnv + "/manifest";
 
     if (!pathExists(path))
-        return UserEnvElems(); /* not an error, assume nothing installed */
+        return DrvInfos(); /* not an error, assume nothing installed */
 
     Expr e = ATreadFromNamedFile(path.c_str());
     if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path);
@@ -222,25 +113,25 @@ static UserEnvElems queryInstalled(EvalState & state, const Path & userEnv)
     AddPos addPos;
     e = bottomupRewrite(addPos, e);
 
-    UserEnvElems elems;
-    parseDerivations(state, e, elems);
+    DrvInfos elems;
+    getDerivations(state, e, elems);
     return elems;
 }
 
 
-static void createUserEnv(EvalState & state, const UserEnvElems & elems,
+static void createUserEnv(EvalState & state, const DrvInfos & elems,
     const Path & profile, bool keepDerivations)
 {
     /* Build the components in the user environment, if they don't
        exist already. */
     PathSet drvsToBuild;
-    for (UserEnvElems::const_iterator i = elems.begin(); 
+    for (DrvInfos::const_iterator i = elems.begin(); 
          i != elems.end(); ++i)
         /* Call to `isDerivation' is for compatibility with Nix <= 0.7
            user environments. */
-        if (i->second.queryDrvPath(state) != "" &&
-            isDerivation(i->second.queryDrvPath(state)))
-            drvsToBuild.insert(i->second.queryDrvPath(state));
+        if (i->queryDrvPath(state) != "" &&
+            isDerivation(i->queryDrvPath(state)))
+            drvsToBuild.insert(i->queryDrvPath(state));
 
     debug(format("building user environment dependencies"));
     buildDerivations(drvsToBuild);
@@ -253,31 +144,31 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
     PathSet references;
     ATermList manifest = ATempty;
     ATermList inputs = ATempty;
-    for (UserEnvElems::const_iterator i = elems.begin(); 
+    for (DrvInfos::const_iterator i = elems.begin(); 
          i != elems.end(); ++i)
     {
-        Path drvPath = keepDerivations ? i->second.queryDrvPath(state) : "";
+        Path drvPath = keepDerivations ? i->queryDrvPath(state) : "";
         ATerm t = makeAttrs(ATmakeList5(
             makeBind(toATerm("type"),
                 makeStr(toATerm("derivation")), makeNoPos()),
             makeBind(toATerm("name"),
-                makeStr(toATerm(i->second.name)), makeNoPos()),
+                makeStr(toATerm(i->name)), makeNoPos()),
             makeBind(toATerm("system"),
-                makeStr(toATerm(i->second.system)), makeNoPos()),
+                makeStr(toATerm(i->system)), makeNoPos()),
             makeBind(toATerm("drvPath"),
                 makePath(toATerm(drvPath)), makeNoPos()),
             makeBind(toATerm("outPath"),
-                makePath(toATerm(i->second.queryOutPath(state))), makeNoPos())
+                makePath(toATerm(i->queryOutPath(state))), makeNoPos())
             ));
         manifest = ATinsert(manifest, t);
-        inputs = ATinsert(inputs, makeStr(toATerm(i->second.queryOutPath(state))));
+        inputs = ATinsert(inputs, makeStr(toATerm(i->queryOutPath(state))));
 
         /* This is only necessary when installing store paths, e.g.,
            `nix-env -i /nix/store/abcd...-foo'. */
-        addTempRoot(i->second.queryOutPath(state));
-        ensurePath(i->second.queryOutPath(state));
+        addTempRoot(i->queryOutPath(state));
+        ensurePath(i->queryOutPath(state));
         
-        references.insert(i->second.queryOutPath(state));
+        references.insert(i->queryOutPath(state));
         if (drvPath != "") references.insert(drvPath);
     }
 
@@ -302,8 +193,8 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
 
     /* Instantiate it. */
     debug(format("evaluating builder expression `%1%'") % topLevel);
-    UserEnvElem topLevelDrv;
-    if (!parseDerivation(state, topLevel, topLevelDrv))
+    DrvInfo topLevelDrv;
+    if (!getDerivation(state, topLevel, topLevelDrv))
         abort();
     
     /* Realise the resulting store expression. */
@@ -317,24 +208,24 @@ static void createUserEnv(EvalState & state, const UserEnvElems & elems,
 }
 
 
-static UserEnvElems filterBySelector(const UserEnvElems & allElems,
+static DrvInfos filterBySelector(const DrvInfos & allElems,
     const Strings & args)
 {
     DrvNames selectors = drvNamesFromArgs(args);
 
-    UserEnvElems elems;
+    DrvInfos elems;
 
     /* Filter out the ones we're not interested in. */
-    for (UserEnvElems::const_iterator i = allElems.begin();
+    for (DrvInfos::const_iterator i = allElems.begin();
          i != allElems.end(); ++i)
     {
-        DrvName drvName(i->second.name);
+        DrvName drvName(i->name);
         for (DrvNames::iterator j = selectors.begin();
              j != selectors.end(); ++j)
         {
             if (j->matches(drvName)) {
                 j->hits++;
-                elems.insert(*i);
+                elems.push_back(*i);
             }
         }
     }
@@ -352,7 +243,7 @@ static UserEnvElems filterBySelector(const UserEnvElems & allElems,
 
 static void queryInstSources(EvalState & state,
     const InstallSourceInfo & instSource, const Strings & args,
-    UserEnvElems & elems)
+    DrvInfos & elems)
 {
     InstallSourceType type = instSource.type;
     if (type == srcUnknown && args.size() > 0 && args.front()[0] == '/')
@@ -368,7 +259,7 @@ static void queryInstSources(EvalState & state,
 
             /* Load the derivations from the (default or specified)
                Nix expression. */
-            UserEnvElems allElems;
+            DrvInfos allElems;
             loadDerivations(state, instSource.nixExprPath,
                 instSource.systemFilter, allElems);
 
@@ -394,7 +285,7 @@ static void queryInstSources(EvalState & state,
             {
                 Expr e2 = parseExprFromString(state, *i, absPath("."));
                 Expr call = makeCall(e2, e1);
-                parseDerivations(state, call, elems);
+                getDerivations(state, call, elems);
             }
             
             break;
@@ -410,7 +301,7 @@ static void queryInstSources(EvalState & state,
             {
                 assertStorePath(*i);
 
-                UserEnvElem elem;
+                DrvInfo elem;
                 string name = baseNameOf(*i);
                 unsigned int dash = name.find('-');
                 if (dash != string::npos)
@@ -426,8 +317,6 @@ static void queryInstSources(EvalState & state,
                 else elem.setOutPath(*i);
 
                 elem.name = name;
-
-                elems[elemCounter++] = elem;
             }
             
             break;
@@ -451,30 +340,30 @@ static void installDerivations(Globals & globals,
     debug(format("installing derivations"));
 
     /* Get the set of user environment elements to be installed. */
-    UserEnvElems newElems;
+    DrvInfos newElems;
     queryInstSources(globals.state, globals.instSource, args, newElems);
 
     StringSet newNames;
-    for (UserEnvElems::iterator i = newElems.begin(); i != newElems.end(); ++i) {
+    for (DrvInfos::iterator i = newElems.begin(); i != newElems.end(); ++i) {
         printMsg(lvlInfo,
-            format("installing `%1%'") % i->second.name);
-        newNames.insert(DrvName(i->second.name).name);
+            format("installing `%1%'") % i->name);
+        newNames.insert(DrvName(i->name).name);
     }
 
     /* Add in the already installed derivations, unless they have the
        same name as a to-be-installed element. */
-    UserEnvElems installedElems = queryInstalled(globals.state, profile);
+    DrvInfos installedElems = queryInstalled(globals.state, profile);
 
-    for (UserEnvElems::iterator i = installedElems.begin();
+    for (DrvInfos::iterator i = installedElems.begin();
          i != installedElems.end(); ++i)
     {
-        DrvName drvName(i->second.name);
+        DrvName drvName(i->name);
         if (!globals.preserveInstalled &&
             newNames.find(drvName.name) != newNames.end())
             printMsg(lvlInfo,
-                format("uninstalling `%1%'") % i->second.name);
+                format("uninstalling `%1%'") % i->name);
         else
-            newElems.insert(*i);
+            newElems.push_back(*i);
     }
 
     if (globals.dryRun) return;
@@ -509,29 +398,29 @@ static void upgradeDerivations(Globals & globals,
        name and a higher version number. */
 
     /* Load the currently installed derivations. */
-    UserEnvElems installedElems = queryInstalled(globals.state, profile);
+    DrvInfos installedElems = queryInstalled(globals.state, profile);
 
     /* Fetch all derivations from the input file. */
-    UserEnvElems availElems;
+    DrvInfos availElems;
     queryInstSources(globals.state, globals.instSource, args, availElems);
 
     /* Go through all installed derivations. */
-    UserEnvElems newElems;
-    for (UserEnvElems::iterator i = installedElems.begin();
+    DrvInfos newElems;
+    for (DrvInfos::iterator i = installedElems.begin();
          i != installedElems.end(); ++i)
     {
-        DrvName drvName(i->second.name);
+        DrvName drvName(i->name);
 
         /* Find the derivation in the input Nix expression with the
            same name and satisfying the version constraints specified
            by upgradeType.  If there are multiple matches, take the
            one with highest version. */
-        UserEnvElems::iterator bestElem = availElems.end();
+        DrvInfos::iterator bestElem = availElems.end();
         DrvName bestName;
-        for (UserEnvElems::iterator j = availElems.begin();
+        for (DrvInfos::iterator j = availElems.begin();
              j != availElems.end(); ++j)
         {
-            DrvName newName(j->second.name);
+            DrvName newName(j->name);
             if (newName.name == drvName.name) {
                 int d = compareVersions(drvName.version, newName.version);
                 if (upgradeType == utLt && d < 0 ||
@@ -550,14 +439,14 @@ static void upgradeDerivations(Globals & globals,
         }
 
         if (bestElem != availElems.end() &&
-            i->second.queryOutPath(globals.state) !=
-                bestElem->second.queryOutPath(globals.state))
+            i->queryOutPath(globals.state) !=
+                bestElem->queryOutPath(globals.state))
         {
             printMsg(lvlInfo,
                 format("upgrading `%1%' to `%2%'")
-                % i->second.name % bestElem->second.name);
-            newElems.insert(*bestElem);
-        } else newElems.insert(*i);
+                % i->name % bestElem->name);
+            newElems.push_back(*bestElem);
+        } else newElems.push_back(*i);
     }
     
     if (globals.dryRun) return;
@@ -585,23 +474,23 @@ static void opUpgrade(Globals & globals,
 static void uninstallDerivations(Globals & globals, DrvNames & selectors,
     Path & profile)
 {
-    UserEnvElems installedElems = queryInstalled(globals.state, profile);
-    UserEnvElems newElems;
+    DrvInfos installedElems = queryInstalled(globals.state, profile);
+    DrvInfos newElems;
 
-    for (UserEnvElems::iterator i = installedElems.begin();
+    for (DrvInfos::iterator i = installedElems.begin();
          i != installedElems.end(); ++i)
     {
-        DrvName drvName(i->second.name);
+        DrvName drvName(i->name);
         bool found = false;
         for (DrvNames::iterator j = selectors.begin();
              j != selectors.end(); ++j)
             if (j->matches(drvName)) {
                 printMsg(lvlInfo,
-                    format("uninstalling `%1%'") % i->second.name);
+                    format("uninstalling `%1%'") % i->name);
                 found = true;
                 break;
             }
-        if (!found) newElems.insert(*i);
+        if (!found) newElems.push_back(*i);
     }
 
     if (globals.dryRun) return;
@@ -630,7 +519,7 @@ static bool cmpChars(char a, char b)
 }
 
 
-static bool cmpElemByName(const UserEnvElem & a, const UserEnvElem & b)
+static bool cmpElemByName(const DrvInfo & a, const DrvInfo & b)
 {
     return lexicographical_compare(
         a.name.begin(), a.name.end(),
@@ -680,15 +569,15 @@ void printTable(Table & table)
 typedef enum { cvLess, cvEqual, cvGreater, cvUnavail } VersionDiff;
 
 static VersionDiff compareVersionAgainstSet(
-    const UserEnvElem & elem, const UserEnvElems & elems, string & version)
+    const DrvInfo & elem, const DrvInfos & elems, string & version)
 {
     DrvName name(elem.name);
     
     VersionDiff diff = cvUnavail;
     version = "?";
     
-    for (UserEnvElems::const_iterator i = elems.begin(); i != elems.end(); ++i) {
-        DrvName name2(i->second.name);
+    for (DrvInfos::const_iterator i = elems.begin(); i != elems.end(); ++i) {
+        DrvName name2(i->name);
         if (name.name == name2.name) {
             int d = compareVersions(name.version, name2.version);
             if (d < 0) {
@@ -748,7 +637,7 @@ static void opQuery(Globals & globals,
 
     
     /* Obtain derivation information from the specified source. */
-    UserEnvElems availElems, installedElems;
+    DrvInfos availElems, installedElems;
 
     if (source == sInstalled || compareVersions || printStatus) {
         installedElems = queryInstalled(globals.state, globals.profile);
@@ -759,14 +648,15 @@ static void opQuery(Globals & globals,
             globals.instSource.systemFilter, availElems);
     }
 
-    UserEnvElems & elems(source == sInstalled ? installedElems : availElems);
-    UserEnvElems & otherElems(source == sInstalled ? availElems : installedElems);
+    DrvInfos & elems(source == sInstalled ? installedElems : availElems);
+    DrvInfos & otherElems(source == sInstalled ? availElems : installedElems);
 
     
     /* Sort them by name. */
-    vector<UserEnvElem> elems2;
-    for (UserEnvElems::iterator i = elems.begin(); i != elems.end(); ++i)
-        elems2.push_back(i->second);
+    /* !!! */
+    vector<DrvInfo> elems2;
+    for (DrvInfos::iterator i = elems.begin(); i != elems.end(); ++i)
+        elems2.push_back(*i);
     sort(elems2.begin(), elems2.end(), cmpElemByName);
 
     
@@ -775,16 +665,16 @@ static void opQuery(Globals & globals,
     PathSet installed; /* installed paths */
     
     if (printStatus) {
-        for (UserEnvElems::iterator i = installedElems.begin();
+        for (DrvInfos::iterator i = installedElems.begin();
              i != installedElems.end(); ++i)
-            installed.insert(i->second.queryOutPath(globals.state));
+            installed.insert(i->queryOutPath(globals.state));
     }
 
     
     /* Print the desired columns. */
     Table table;
     
-    for (vector<UserEnvElem>::iterator i = elems2.begin();
+    for (vector<DrvInfo>::iterator i = elems2.begin();
          i != elems2.end(); ++i)
     {
         Strings columns;