about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-04-19T12·10+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-04-19T12·10+0000
commit55b5ddd3ca1ff4dfe4cfbfab92a4025d88ef6443 (patch)
treed9377895a711709f73ceabb10b511b91b0d3b4e5
parentb7ff69eb7c3f97c33ec18c51ab87b7f3dd967052 (diff)
* Added parsing of manifests in ATerm format.
-rw-r--r--src/libexpr/get-drvs.cc16
-rw-r--r--src/libexpr/get-drvs.hh5
-rw-r--r--src/nix-env/user-env.cc157
3 files changed, 165 insertions, 13 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 8af011d54987..e9f1063d955f 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -7,7 +7,7 @@ namespace nix {
 
 string DrvInfo::queryDrvPath(EvalState & state) const
 {
-    if (drvPath == "") {
+    if (drvPath == "" && attrs) {
         Bindings::iterator i = attrs->find(state.sDrvPath);
         PathSet context;
         (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second, context) : "";
@@ -18,7 +18,7 @@ string DrvInfo::queryDrvPath(EvalState & state) const
 
 string DrvInfo::queryOutPath(EvalState & state) const
 {
-    if (outPath == "") {
+    if (outPath == "" && attrs) {
         Bindings::iterator i = attrs->find(state.sOutPath);
         PathSet context;
         (string &) outPath = i != attrs->end() ? state.coerceToPath(i->second, context) : "";
@@ -29,7 +29,9 @@ string DrvInfo::queryOutPath(EvalState & state) const
 
 MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
 {
-    MetaInfo meta;
+    if (metaInfoRead) return meta;
+    
+    (bool &) metaInfoRead = true;
     
     Bindings::iterator a = attrs->find(state.sMeta);
     if (a == attrs->end()) return meta; /* fine, empty meta information */
@@ -50,7 +52,7 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
             for (unsigned int j = 0; j < i->second.list.length; ++j)
                 value.stringValues.push_back(state.forceStringNoCtx(*i->second.list.elems[j]));
         } else continue;
-        meta[i->first] = value;
+        ((MetaInfo &) meta)[i->first] = value;
     }
 
     return meta;
@@ -66,9 +68,11 @@ MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
 
 void DrvInfo::setMetaInfo(const MetaInfo & meta)
 {
-    throw Error("not implemented");
+    metaInfoRead = true;
+    this->meta = meta;
+    
 #if 0
-    ATermMap metaAttrs;
+    Value * metaAttrs = state.allocValues(1);
     foreach (MetaInfo::const_iterator, i, meta) {
         Expr e;
         switch (i->second.type) {
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index f7d1987ea3b7..6f3c381f8e34 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -29,6 +29,9 @@ struct DrvInfo
 private:
     string drvPath;
     string outPath;
+
+    bool metaInfoRead;
+    MetaInfo meta;
     
 public:
     string name;
@@ -38,6 +41,8 @@ public:
     /* !!! make this private */
     Bindings * attrs;
 
+    DrvInfo() : metaInfoRead(false) { };
+
     string queryDrvPath(EvalState & state) const;
     string queryOutPath(EvalState & state) const;
     MetaInfo queryMetaInfo(EvalState & state) const;
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 0e1fce650ca4..8bb760094dab 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -5,22 +5,165 @@
 namespace nix {
 
 
+static void readLegacyManifest(const Path & path, DrvInfos & elems);
+
+
 DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
 {
+    DrvInfos elems;
+    
     Path path = userEnv + "/manifest";
 
     if (!pathExists(path))
         return DrvInfos(); /* not an error, assume nothing installed */
 
-    throw Error("not implemented");
-#if 0
-    Expr e = ATreadFromNamedFile(path.c_str());
-    if (!e) throw Error(format("cannot read Nix expression from `%1%'") % path);
+    readLegacyManifest(path, elems);
 
-    DrvInfos elems;
-    // !!! getDerivations(state, e, "", ATermMap(1), elems);
     return elems;
-#endif
+}
+
+
+/* Code for parsing manifests in the old textual ATerm format. */
+
+static void expect(std::istream & str, const string & s)
+{
+    char s2[s.size()];
+    str.read(s2, s.size());
+    if (string(s2, s.size()) != s)
+        throw Error(format("expected string `%1%'") % s);
+}
+
+
+static string parseString(std::istream & str)
+{
+    string res;
+    expect(str, "\"");
+    int c;
+    while ((c = str.get()) != '"')
+        if (c == '\\') {
+            c = str.get();
+            if (c == 'n') res += '\n';
+            else if (c == 'r') res += '\r';
+            else if (c == 't') res += '\t';
+            else res += c;
+        }
+        else res += c;
+    return res;
+}
+
+
+static string parseStr(std::istream & str)
+{
+    expect(str, "Str(");
+    string s = parseString(str);
+    expect(str, ",[])");
+    return s;
+}
+
+
+static string parseWord(std::istream & str)
+{
+    string res;
+    while (isalpha(str.peek()))
+        res += str.get();
+    return res;
+}
+
+
+static bool endOfList(std::istream & str)
+{
+    if (str.peek() == ',') {
+        str.get();
+        return false;
+    }
+    if (str.peek() == ']') {
+        str.get();
+        return true;
+    }
+    return false;
+}
+
+
+static MetaInfo parseMeta(std::istream & str)
+{
+    MetaInfo meta;
+
+    expect(str, "Attrs([");
+    while (!endOfList(str)) {
+        expect(str, "Bind(");
+
+        MetaValue value;
+        
+        string name = parseString(str);
+        expect(str, ",");
+
+        string type = parseWord(str);
+
+        if (type == "Str") {
+            expect(str, "(");
+            value.type = MetaValue::tpString;
+            value.stringValue = parseString(str);
+            expect(str, ",[])");
+        }
+
+        else if (type == "List") {
+            expect(str, "([");
+            value.type = MetaValue::tpStrings;
+            while (!endOfList(str))
+                value.stringValues.push_back(parseStr(str));
+            expect(str, ")");
+        }
+
+        else throw Error(format("unexpected token `%1%'") % type);
+
+        expect(str, ",NoPos)");
+        meta[name] = value;
+    }
+    
+    expect(str, ")");
+
+    return meta;
+}
+
+
+static void readLegacyManifest(const Path & path, DrvInfos & elems)
+{
+    string manifest = readFile(path);
+    std::istringstream str(manifest);
+    expect(str, "List([");
+
+    unsigned int n = 0;
+    
+    while (!endOfList(str)) {
+        DrvInfo elem;
+        expect(str, "Attrs([");
+
+        while (!endOfList(str)) {
+            expect(str, "Bind(");
+            string name = parseString(str);
+            expect(str, ",");
+            
+            if (name == "meta") elem.setMetaInfo(parseMeta(str));
+            else {
+                string value = parseStr(str);
+                if (name == "name") elem.name = value;
+                else if (name == "outPath") elem.setOutPath(value);
+                else if (name == "drvPath") elem.setDrvPath(value);
+                else if (name == "system") elem.system = value;
+            }
+
+            expect(str, ",NoPos)");
+        }
+
+        expect(str, ")");
+
+        if (elem.name != "") {
+            elem.attrPath = int2String(n++);
+            elems.push_back(elem);
+        }
+    }
+
+    expect(str, ")");
 }