about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nix-env/nix-env.cc53
1 files changed, 45 insertions, 8 deletions
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index c30c88092818..f0c833c0b22c 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -11,6 +11,7 @@
 #include "store-api.hh"
 #include "user-env.hh"
 #include "util.hh"
+#include "value-to-json.hh"
 
 #include <cerrno>
 #include <ctime>
@@ -874,6 +875,35 @@ static string colorString(const string & s)
 }
 
 
+static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
+{
+    JSONObject topObj(cout);
+    foreach (vector<DrvInfo>::iterator, i, elems) {
+        topObj.attr(i->attrPath);
+        JSONObject pkgObj(cout);
+
+        pkgObj.attr("name", i->name);
+        pkgObj.attr("system", i->system);
+
+        pkgObj.attr("meta");
+        JSONObject metaObj(cout);
+        MetaInfo meta = i->queryMetaInfo(globals.state);
+        foreach (MetaInfo::iterator, j, meta) {
+            metaObj.attr(j->first);
+            if (j->second.type == MetaValue::tpString) {
+                escapeJSON(cout, j->second.stringValue);
+            } else if (j->second.type == MetaValue::tpInt) {
+                cout << j->second.intValue;
+            } else if (j->second.type == MetaValue::tpStrings) {
+                JSONList l(cout);
+                foreach (Strings::iterator, k, j->second.stringValues)
+                    l.elem(*k);
+            }
+        }
+    }
+}
+
+
 static void opQuery(Globals & globals,
     Strings args, Strings opFlags, Strings opArgs)
 {
@@ -891,6 +921,7 @@ static void opQuery(Globals & globals,
     bool printMeta = false;
     bool compareVersions = false;
     bool xmlOutput = false;
+    bool jsonOutput = false;
 
     enum { sInstalled, sAvailable } source = sInstalled;
 
@@ -909,6 +940,7 @@ static void opQuery(Globals & globals,
         else if (arg == "--installed") source = sInstalled;
         else if (arg == "--available" || arg == "-a") source = sAvailable;
         else if (arg == "--xml") xmlOutput = true;
+        else if (arg == "--json") jsonOutput = true;
         else if (arg == "--attr-path" || arg == "-P") printAttrPath = true;
         else if (arg == "--attr" || arg == "-A")
             attrPath = needArg(i, args, arg);
@@ -929,7 +961,7 @@ static void opQuery(Globals & globals,
             globals.instSource.systemFilter, globals.instSource.autoArgs,
             attrPath, availElems);
 
-    DrvInfos elems = filterBySelector(globals.state,
+    DrvInfos elems_ = filterBySelector(globals.state,
         source == sInstalled ? installedElems : availElems,
         remaining, false);
 
@@ -938,10 +970,10 @@ static void opQuery(Globals & globals,
 
     /* Sort them by name. */
     /* !!! */
-    vector<DrvInfo> elems2;
-    for (DrvInfos::iterator i = elems.begin(); i != elems.end(); ++i)
-        elems2.push_back(*i);
-    sort(elems2.begin(), elems2.end(), cmpElemByName);
+    vector<DrvInfo> elems;
+    for (DrvInfos::iterator i = elems_.begin(); i != elems_.end(); ++i)
+        elems.push_back(*i);
+    sort(elems.begin(), elems.end(), cmpElemByName);
 
 
     /* We only need to know the installed paths when we are querying
@@ -959,7 +991,7 @@ static void opQuery(Globals & globals,
     PathSet validPaths, substitutablePaths;
     if (printStatus || globals.prebuiltOnly) {
         PathSet paths;
-        foreach (vector<DrvInfo>::iterator, i, elems2)
+        foreach (vector<DrvInfo>::iterator, i, elems)
             try {
                 paths.insert(i->queryOutPath(globals.state));
             } catch (AssertionError & e) {
@@ -972,12 +1004,17 @@ static void opQuery(Globals & globals,
 
 
     /* Print the desired columns, or XML output. */
+    if (jsonOutput) {
+        queryJSON(globals, elems);
+        return;
+    }
+
     Table table;
     std::ostringstream dummy;
     XMLWriter xml(true, *(xmlOutput ? &cout : &dummy));
     XMLOpenElement xmlRoot(xml, "items");
 
-    foreach (vector<DrvInfo>::iterator, i, elems2) {
+    foreach (vector<DrvInfo>::iterator, i, elems) {
         try {
             if (i->hasFailed()) continue;
 
@@ -1098,7 +1135,7 @@ static void opQuery(Globals & globals,
                     }
                     if (printMeta) {
                         MetaInfo meta = i->queryMetaInfo(globals.state);
-                        for (MetaInfo::iterator j = meta.begin(); j != meta.end(); ++j) {
+                        foreach (MetaInfo::iterator, j, meta) {
                             XMLAttrs attrs2;
                             attrs2["name"] = j->first;
                             if (j->second.type == MetaValue::tpString) {