about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/expr-to-xml.cc66
1 files changed, 55 insertions, 11 deletions
diff --git a/src/libexpr/expr-to-xml.cc b/src/libexpr/expr-to-xml.cc
index 1a7302df1293..6d27bcffb69c 100644
--- a/src/libexpr/expr-to-xml.cc
+++ b/src/libexpr/expr-to-xml.cc
@@ -16,7 +16,30 @@ static XMLAttrs singletonAttrs(const string & name, const string & value)
 }
 
 
-static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context)
+/* set<Expr> is safe because all the expressions are also reachable
+   from the stack, therefore can't be garbage-collected. */
+typedef set<Expr> ExprSet;
+
+
+static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context,
+    ExprSet & drvsSeen);
+
+
+static void showAttrs(const ATermMap & attrs, XMLWriter & doc,
+    PathSet & context, ExprSet & drvsSeen)
+{
+    StringSet names;
+    for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i)
+        names.insert(aterm2String(i->key));
+    for (StringSet::iterator i = names.begin(); i != names.end(); ++i) {
+        XMLOpenElement _(doc, "attr", singletonAttrs("name", *i));
+        printTermAsXML(attrs.get(toATerm(*i)), doc, context, drvsSeen);
+    }
+}
+
+
+static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context,
+    ExprSet & drvsSeen)
 {
     XMLAttrs attrs;
     string s;
@@ -46,22 +69,42 @@ static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context)
         doc.writeEmptyElement("bool", singletonAttrs("value", "false"));
 
     else if (matchAttrs(e, as)) {
-        XMLOpenElement _(doc, "attrs");
         ATermMap attrs;
         queryAllAttrs(e, attrs);
-        StringSet names;
-        for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i)
-            names.insert(aterm2String(i->key));
-        for (StringSet::iterator i = names.begin(); i != names.end(); ++i) {
-            XMLOpenElement _(doc, "attr", singletonAttrs("name", *i));
-            printTermAsXML(attrs.get(toATerm(*i)), doc, context);
+
+        Expr a = attrs.get(toATerm("type"));
+        if (a && matchStr(a, s, context) && s == "derivation") {
+
+            XMLAttrs xmlAttrs;
+            Path outPath, drvPath;
+            
+            a = attrs.get(toATerm("drvPath"));
+            if (matchStr(a, drvPath, context))
+                xmlAttrs["drvPath"] = drvPath;
+        
+            a = attrs.get(toATerm("outPath"));
+            if (matchStr(a, outPath, context))
+                xmlAttrs["outPath"] = outPath;
+        
+            XMLOpenElement _(doc, "derivation", xmlAttrs);
+
+            if (drvsSeen.find(e) == drvsSeen.end()) {
+                drvsSeen.insert(e);
+                showAttrs(attrs, doc, context, drvsSeen);
+            } else
+                doc.writeEmptyElement("repeated");
+        }
+
+        else {
+            XMLOpenElement _(doc, "attrs");
+            showAttrs(attrs, doc, context, drvsSeen);
         }
     }
 
     else if (matchList(e, es)) {
         XMLOpenElement _(doc, "list");
         for (ATermIterator i(es); i; ++i)
-            printTermAsXML(*i, doc, context);
+            printTermAsXML(*i, doc, context, drvsSeen);
     }
 
     else if (matchFunction(e, formals, body, pos)) {
@@ -76,7 +119,7 @@ static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context)
             if (matchValidValues(valids, valids2)) {
                 for (ATermIterator j(valids2); j; ++j) {
                     XMLOpenElement _(doc, "value");
-                    printTermAsXML(*j, doc, context);
+                    printTermAsXML(*j, doc, context, drvsSeen);
                 }
             }
         }
@@ -91,7 +134,8 @@ void printTermAsXML(Expr e, std::ostream & out, PathSet & context)
 {
     XMLWriter doc(true, out);
     XMLOpenElement root(doc, "expr");
-    printTermAsXML(e, doc, context);
+    ExprSet drvsSeen;    
+    printTermAsXML(e, doc, context, drvsSeen);
 }