* `nix-env -q --xml': show query result in XML format for easier

automated processing.
This commit is contained in:
Eelco Dolstra 2006-08-03 15:52:09 +00:00
parent 0e267e2625
commit 339e6f0e1d
3 changed files with 82 additions and 25 deletions

View File

@ -45,7 +45,7 @@ void XMLWriter::closeElement()
} }
void XMLWriter::writeShortElement(const string & name, void XMLWriter::writeEmptyElement(const string & name,
const XMLAttrs & attrs) const XMLAttrs & attrs)
{ {
assert(!closed); assert(!closed);

View File

@ -33,7 +33,7 @@ public:
const XMLAttrs & attrs = XMLAttrs()); const XMLAttrs & attrs = XMLAttrs());
void closeElement(); void closeElement();
void writeShortElement(const string & name, void writeEmptyElement(const string & name,
const XMLAttrs & attrs = XMLAttrs()); const XMLAttrs & attrs = XMLAttrs());
void writeCharData(const string & data); void writeCharData(const string & data);

View File

@ -12,11 +12,13 @@
#include "get-drvs.hh" #include "get-drvs.hh"
#include "attr-path.hh" #include "attr-path.hh"
#include "pathlocks.hh" #include "pathlocks.hh"
#include "xml-writer.hh"
#include <cerrno> #include <cerrno>
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <sstream>
#include <unistd.h> #include <unistd.h>
@ -724,6 +726,8 @@ static string colorString(const string & s)
static void opQuery(Globals & globals, static void opQuery(Globals & globals,
Strings opFlags, Strings opArgs) Strings opFlags, Strings opArgs)
{ {
typedef vector< map<string, string> > ResultSet;
bool printStatus = false; bool printStatus = false;
bool printName = true; bool printName = true;
bool printAttrPath = false; bool printAttrPath = false;
@ -732,6 +736,7 @@ static void opQuery(Globals & globals,
bool printOutPath = false; bool printOutPath = false;
bool printDescription = false; bool printDescription = false;
bool compareVersions = false; bool compareVersions = false;
bool xmlOutput = false;
enum { sInstalled, sAvailable } source = sInstalled; enum { sInstalled, sAvailable } source = sInstalled;
@ -748,6 +753,7 @@ static void opQuery(Globals & globals,
else if (*i == "--out-path") printOutPath = true; else if (*i == "--out-path") printOutPath = true;
else if (*i == "--installed") source = sInstalled; else if (*i == "--installed") source = sInstalled;
else if (*i == "--available" || *i == "-a") source = sAvailable; else if (*i == "--available" || *i == "-a") source = sAvailable;
else if (*i == "--xml") xmlOutput = true;
else throw UsageError(format("unknown flag `%1%'") % *i); else throw UsageError(format("unknown flag `%1%'") % *i);
if (globals.instSource.type == srcAttrPath) printAttrPath = true; /* hack */ if (globals.instSource.type == srcAttrPath) printAttrPath = true; /* hack */
@ -795,28 +801,47 @@ static void opQuery(Globals & globals,
} }
/* Print the desired columns. */ /* Print the desired columns, or XML output. */
Table table; Table table;
ostringstream dummy;
XMLWriter xml(xmlOutput ? cout : dummy);
XMLOpenElement xmlRoot(xml, "items");
for (vector<DrvInfo>::iterator i = elems2.begin(); for (vector<DrvInfo>::iterator i = elems2.begin();
i != elems2.end(); ++i) i != elems2.end(); ++i)
{ {
try { try {
/* For table output. */
Strings columns; Strings columns;
/* For XML output. */
XMLAttrs attrs;
if (printStatus) { if (printStatus) {
Substitutes subs = querySubstitutes(noTxn, i->queryOutPath(globals.state)); Substitutes subs = querySubstitutes(noTxn, i->queryOutPath(globals.state));
columns.push_back( bool isInstalled = installed.find(i->queryOutPath(globals.state)) != installed.end();
(string) (installed.find(i->queryOutPath(globals.state)) bool isValid = isValidPath(i->queryOutPath(globals.state));
!= installed.end() ? "I" : "-") if (xmlOutput) {
+ (isValidPath(i->queryOutPath(globals.state)) ? "P" : "-") attrs["installed"] = isInstalled ? "1" : "0";
+ (subs.size() > 0 ? "S" : "-")); attrs["valid"] = isValid ? "1" : "0";
attrs["substitutable"] = !subs.empty() ? "1" : "0";
} else
columns.push_back(
(string) (isInstalled ? "I" : "-")
+ (isValid ? "P" : "-")
+ (!subs.empty() ? "S" : "-"));
} }
if (printAttrPath) columns.push_back(i->attrPath); if (xmlOutput)
attrs["attrPath"] = i->attrPath;
else if (printAttrPath)
columns.push_back(i->attrPath);
if (printName) columns.push_back(i->name); if (xmlOutput)
attrs["name"] = i->name;
else if (printName)
columns.push_back(i->name);
if (compareVersions) { if (compareVersions) {
/* Compare this element against the versions of the /* Compare this element against the versions of the
@ -825,6 +850,7 @@ static void opQuery(Globals & globals,
This is O(N * M), should be O(N * lg M). */ This is O(N * M), should be O(N * lg M). */
string version; string version;
VersionDiff diff = compareVersionAgainstSet(*i, otherElems, version); VersionDiff diff = compareVersionAgainstSet(*i, otherElems, version);
char ch; char ch;
switch (diff) { switch (diff) {
case cvLess: ch = '>'; break; case cvLess: ch = '>'; break;
@ -833,31 +859,62 @@ static void opQuery(Globals & globals,
case cvUnavail: ch = '-'; break; case cvUnavail: ch = '-'; break;
default: abort(); default: abort();
} }
string column = (string) "" + ch + " " + version;
if (diff == cvGreater) column = colorString(column); if (xmlOutput) {
columns.push_back(column); if (diff != cvUnavail) {
attrs["versionDiff"] = ch;
attrs["maxComparedVersion"] = version;
}
} else {
string column = (string) "" + ch + " " + version;
if (diff == cvGreater) column = colorString(column);
columns.push_back(column);
}
} }
if (printSystem) columns.push_back(i->system); if (xmlOutput) {
if (i->system != "") attrs["system"] = i->system;
}
else if (printSystem)
columns.push_back(i->system);
if (printDrvPath) columns.push_back( if (printDrvPath) {
i->queryDrvPath(globals.state) == "" string drvPath = i->queryDrvPath(globals.state);
? "-" : i->queryDrvPath(globals.state)); if (xmlOutput) {
if (drvPath != "") attrs["drvPath"] = drvPath;
} else
columns.push_back(drvPath == "" ? "-" : drvPath);
}
if (printOutPath) columns.push_back(i->queryOutPath(globals.state)); if (printOutPath) {
string outPath = i->queryOutPath(globals.state);
if (xmlOutput) {
if (outPath != "") attrs["outPath"] = outPath;
} else
columns.push_back(outPath);
}
if (printDescription) { if (printDescription) {
MetaInfo meta = i->queryMetaInfo(globals.state); MetaInfo meta = i->queryMetaInfo(globals.state);
columns.push_back(meta["description"]); string descr = meta["description"];
if (xmlOutput) {
if (descr != "") attrs["description"] = descr;
} else
columns.push_back(descr);
} }
table.push_back(columns); if (xmlOutput) {
} xml.writeEmptyElement("item", attrs);
catch (AssertionError & e) { xml.writeCharData("\n");
} else
table.push_back(columns);
} catch (AssertionError & e) {
/* !!! hm, maybe we should give some sort of warning here? */
} }
} }
printTable(table); if (!xmlOutput) printTable(table);
} }