Generalise meta attributes

This commit is contained in:
Eelco Dolstra 2013-11-19 14:09:03 +01:00
parent 990126cde0
commit 0f24400d90
5 changed files with 208 additions and 208 deletions

View file

@ -2,116 +2,155 @@
#include "util.hh" #include "util.hh"
#include "eval-inline.hh" #include "eval-inline.hh"
#include <cstring>
namespace nix { namespace nix {
string DrvInfo::queryDrvPath(EvalState & state) const string DrvInfo::queryDrvPath()
{ {
if (drvPath == "" && attrs) { if (drvPath == "" && attrs) {
Bindings::iterator i = attrs->find(state.sDrvPath); Bindings::iterator i = attrs->find(state->sDrvPath);
PathSet context; PathSet context;
(string &) drvPath = i != attrs->end() ? state.coerceToPath(*i->value, context) : ""; drvPath = i != attrs->end() ? state->coerceToPath(*i->value, context) : "";
} }
return drvPath; return drvPath;
} }
string DrvInfo::queryOutPath(EvalState & state) const string DrvInfo::queryOutPath()
{ {
if (outPath == "" && attrs) { if (outPath == "" && attrs) {
Bindings::iterator i = attrs->find(state.sOutPath); Bindings::iterator i = attrs->find(state->sOutPath);
PathSet context; PathSet context;
(string &) outPath = i != attrs->end() ? state.coerceToPath(*i->value, context) : ""; outPath = i != attrs->end() ? state->coerceToPath(*i->value, context) : "";
} }
return outPath; return outPath;
} }
DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state) DrvInfo::Outputs DrvInfo::queryOutputs()
{ {
if (outputs.empty()) { if (outputs.empty()) {
/* Get the outputs list. */ /* Get the outputs list. */
Bindings::iterator i = attrs->find(state.sOutputs); Bindings::iterator i;
if (attrs && (i = attrs->find(state->sOutputs)) != attrs->end()) {
if (i == attrs->end()) state->forceList(*i->value);
outputs["out"] = queryOutPath(state);
else {
state.forceList(*i->value);
/* For each output... */ /* For each output... */
for (unsigned int j = 0; j < i->value->list.length; ++j) { for (unsigned int j = 0; j < i->value->list.length; ++j) {
/* Evaluate the corresponding set. */ /* Evaluate the corresponding set. */
string name = state.forceStringNoCtx(*i->value->list.elems[j]); string name = state->forceStringNoCtx(*i->value->list.elems[j]);
Bindings::iterator out = attrs->find(state.symbols.create(name)); Bindings::iterator out = attrs->find(state->symbols.create(name));
if (out == attrs->end()) continue; // FIXME: throw error? if (out == attrs->end()) continue; // FIXME: throw error?
state.forceAttrs(*out->value); state->forceAttrs(*out->value);
/* And evaluate its outPath attribute. */ /* And evaluate its outPath attribute. */
Bindings::iterator outPath = out->value->attrs->find(state.sOutPath); Bindings::iterator outPath = out->value->attrs->find(state->sOutPath);
if (outPath == out->value->attrs->end()) continue; // FIXME: throw error? if (outPath == out->value->attrs->end()) continue; // FIXME: throw error?
PathSet context; PathSet context;
outputs[name] = state.coerceToPath(*outPath->value, context); outputs[name] = state->coerceToPath(*outPath->value, context);
}
} }
} else
outputs["out"] = queryOutPath();
} }
return outputs; return outputs;
} }
string DrvInfo::queryOutputName(EvalState & state) const string DrvInfo::queryOutputName()
{ {
if (outputName == "" && attrs) { if (outputName == "" && attrs) {
Bindings::iterator i = attrs->find(state.sOutputName); Bindings::iterator i = attrs->find(state->sOutputName);
(string &) outputName = i != attrs->end() ? state.forceStringNoCtx(*i->value) : ""; outputName = i != attrs->end() ? state->forceStringNoCtx(*i->value) : "";
} }
return outputName; return outputName;
} }
MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const Bindings * DrvInfo::getMeta()
{ {
if (metaInfoRead) return meta; if (meta) return meta;
if (!attrs) return 0;
(bool &) metaInfoRead = true; Bindings::iterator a = attrs->find(state->sMeta);
if (a == attrs->end()) return 0;
Bindings::iterator a = attrs->find(state.sMeta); state->forceAttrs(*a->value);
if (a == attrs->end()) return meta; /* fine, empty meta information */ meta = a->value->attrs;
state.forceAttrs(*a->value);
foreach (Bindings::iterator, i, *a->value->attrs) {
MetaValue value;
state.forceValue(*i->value);
if (i->value->type == tString) {
value.type = MetaValue::tpString;
value.stringValue = i->value->string.s;
} else if (i->value->type == tInt) {
value.type = MetaValue::tpInt;
value.intValue = i->value->integer;
} else if (i->value->type == tList) {
value.type = MetaValue::tpStrings;
for (unsigned int j = 0; j < i->value->list.length; ++j)
value.stringValues.push_back(state.forceStringNoCtx(*i->value->list.elems[j]));
} else continue;
((MetaInfo &) meta)[i->name] = value;
}
return meta; return meta;
} }
MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const StringSet DrvInfo::queryMetaNames()
{ {
/* !!! evaluates all meta attributes => inefficient */ StringSet res;
return queryMetaInfo(state)[name]; if (!getMeta()) return res;
foreach (Bindings::iterator, i, *meta)
res.insert(i->name);
return res;
} }
void DrvInfo::setMetaInfo(const MetaInfo & meta) Value * DrvInfo::queryMeta(const string & name)
{ {
metaInfoRead = true; if (!getMeta()) return 0;
this->meta = meta; Bindings::iterator a = meta->find(state->symbols.create(name));
if (a == meta->end()) return 0;
state->forceValue(*a->value);
return a->value;
}
string DrvInfo::queryMetaString(const string & name)
{
Value * v = queryMeta(name);
if (!v || v->type != tString) return "";
return v->string.s;
}
int DrvInfo::queryMetaInt(const string & name, int def)
{
Value * v = queryMeta(name);
if (!v) return def;
if (v->type == tInt) return v->integer;
if (v->type == tString) {
/* Backwards compatibility with before we had support for
integer meta fields. */
int n;
if (string2Int(v->string.s, n)) return n;
}
return def;
}
bool DrvInfo::queryMetaBool(const string & name, bool def)
{
Value * v = queryMeta(name);
if (!v) return def;
if (v->type == tBool) return v->boolean;
if (v->type == tString) {
/* Backwards compatibility with before we had support for
Boolean meta fields. */
if (strcmp(v->string.s, "true") == 0) return true;
if (strcmp(v->string.s, "false") == 0) return false;
}
return def;
}
void DrvInfo::setMeta(const string & name, Value * v)
{
getMeta();
Bindings * old = meta;
meta = new Bindings();
Symbol sym = state->symbols.create(name);
if (old)
foreach (Bindings::iterator, i, *old)
if (i->name != sym)
meta->push_back(*i);
if (v) meta->push_back(Attr(sym, v));
meta->sort();
} }
@ -136,22 +175,18 @@ static bool getDerivation(EvalState & state, Value & v,
if (done.find(v.attrs) != done.end()) return false; if (done.find(v.attrs) != done.end()) return false;
done.insert(v.attrs); done.insert(v.attrs);
DrvInfo drv;
Bindings::iterator i = v.attrs->find(state.sName); Bindings::iterator i = v.attrs->find(state.sName);
/* !!! We really would like to have a decent back trace here. */ /* !!! We really would like to have a decent back trace here. */
if (i == v.attrs->end()) throw TypeError("derivation name missing"); if (i == v.attrs->end()) throw TypeError("derivation name missing");
drv.name = state.forceStringNoCtx(*i->value);
Bindings::iterator i2 = v.attrs->find(state.sSystem); Bindings::iterator i2 = v.attrs->find(state.sSystem);
if (i2 == v.attrs->end())
drv.system = "unknown";
else
drv.system = state.forceStringNoCtx(*i2->value);
drv.attrs = v.attrs; DrvInfo drv(
state,
drv.attrPath = attrPath; state.forceStringNoCtx(*i->value),
attrPath,
i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value),
v.attrs);
drvs.push_back(drv); drvs.push_back(drv);
return false; return false;
@ -190,8 +225,6 @@ static void getDerivations(EvalState & state, Value & vIn,
state.autoCallFunction(autoArgs, vIn, v); state.autoCallFunction(autoArgs, vIn, v);
/* Process the expression. */ /* Process the expression. */
DrvInfo drv;
if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ; if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ;
else if (v.type == tAttrs) { else if (v.type == tAttrs) {

View file

@ -11,50 +11,50 @@
namespace nix { namespace nix {
struct MetaValue
{
enum { tpNone, tpString, tpStrings, tpInt } type;
string stringValue;
Strings stringValues;
int intValue;
};
typedef std::map<string, MetaValue> MetaInfo;
struct DrvInfo struct DrvInfo
{ {
public: public:
typedef std::map<string, Path> Outputs; typedef std::map<string, Path> Outputs;
private: private:
EvalState * state;
string drvPath; string drvPath;
string outPath; string outPath;
string outputName; string outputName;
Outputs outputs; Outputs outputs;
bool metaInfoRead;
MetaInfo meta;
bool failed; // set if we get an AssertionError bool failed; // set if we get an AssertionError
Bindings * attrs, * meta;
Bindings * getMeta();
public: public:
string name; string name;
string attrPath; /* path towards the derivation */ string attrPath; /* path towards the derivation */
string system; string system;
/* !!! make this private */ DrvInfo(EvalState & state) : state(&state), failed(false), attrs(0), meta(0) { };
Bindings * attrs; DrvInfo(EvalState & state, const string & name, const string & attrPath, const string & system, Bindings * attrs)
: state(&state), failed(false), attrs(attrs), meta(0), name(name), attrPath(attrPath), system(system) { };
DrvInfo() : metaInfoRead(false), failed(false), attrs(0) { }; string queryDrvPath();
string queryOutPath();
string queryOutputName();
Outputs queryOutputs();
string queryDrvPath(EvalState & state) const; StringSet queryMetaNames();
string queryOutPath(EvalState & state) const; Value * queryMeta(const string & name);
string queryOutputName(EvalState & state) const; string queryMetaString(const string & name);
Outputs queryOutputs(EvalState & state); int queryMetaInt(const string & name, int def);
bool queryMetaBool(const string & name, bool def);
void setMeta(const string & name, Value * v);
/*
MetaInfo queryMetaInfo(EvalState & state) const; MetaInfo queryMetaInfo(EvalState & state) const;
MetaValue queryMetaInfo(EvalState & state, const string & name) const; MetaValue queryMetaInfo(EvalState & state, const string & name) const;
*/
void setDrvPath(const string & s) void setDrvPath(const string & s)
{ {
@ -66,8 +66,6 @@ public:
outPath = s; outPath = s;
} }
void setMetaInfo(const MetaInfo & meta);
void setFailed() { failed = true; }; void setFailed() { failed = true; };
bool hasFailed() { return failed; }; bool hasFailed() { return failed; };
}; };

View file

@ -210,21 +210,13 @@ static Path getDefNixExprPath()
} }
static int getPriority(EvalState & state, const DrvInfo & drv) static int getPriority(EvalState & state, DrvInfo & drv)
{ {
MetaValue value = drv.queryMetaInfo(state, "priority"); return drv.queryMetaInt("priority", 0);
int prio = 0;
if (value.type == MetaValue::tpInt) prio = value.intValue;
else if (value.type == MetaValue::tpString)
/* Backwards compatibility. Priorities used to be strings
before we had support for integer meta field. */
string2Int(value.stringValue, prio);
return prio;
} }
static int comparePriorities(EvalState & state, static int comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2)
const DrvInfo & drv1, const DrvInfo & drv2)
{ {
return getPriority(state, drv2) - getPriority(state, drv1); return getPriority(state, drv2) - getPriority(state, drv1);
} }
@ -232,9 +224,9 @@ static int comparePriorities(EvalState & state,
// FIXME: this function is rather slow since it checks a single path // FIXME: this function is rather slow since it checks a single path
// at a time. // at a time.
static bool isPrebuilt(EvalState & state, const DrvInfo & elem) static bool isPrebuilt(EvalState & state, DrvInfo & elem)
{ {
Path path = elem.queryOutPath(state); Path path = elem.queryOutPath();
if (store->isValidPath(path)) return true; if (store->isValidPath(path)) return true;
PathSet ps = store->querySubstitutablePaths(singleton<PathSet>(path)); PathSet ps = store->querySubstitutablePaths(singleton<PathSet>(path));
return ps.find(path) != ps.end(); return ps.find(path) != ps.end();
@ -296,7 +288,8 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
} }
if (d > 0) { if (d > 0) {
newest[drvName.name] = *j; newest.erase(drvName.name);
newest.insert(Newest::value_type(drvName.name, *j));
multiple.erase(j->first.name); multiple.erase(j->first.name);
} else if (d == 0) { } else if (d == 0) {
multiple.insert(j->first.name); multiple.insert(j->first.name);
@ -392,18 +385,16 @@ static void queryInstSources(EvalState & state,
derivations). */ derivations). */
case srcStorePaths: { case srcStorePaths: {
for (Strings::const_iterator i = args.begin(); foreach (Strings::const_iterator, i, args) {
i != args.end(); ++i)
{
Path path = followLinksToStorePath(*i); Path path = followLinksToStorePath(*i);
DrvInfo elem;
elem.attrs = new Bindings;
string name = baseNameOf(path); string name = baseNameOf(path);
string::size_type dash = name.find('-'); string::size_type dash = name.find('-');
if (dash != string::npos) if (dash != string::npos)
name = string(name, dash + 1); name = string(name, dash + 1);
DrvInfo elem(state, name, "", "", 0);
if (isDerivation(path)) { if (isDerivation(path)) {
elem.setDrvPath(path); elem.setDrvPath(path);
elem.setOutPath(findOutput(derivationFromPath(*store, path), "out")); elem.setOutPath(findOutput(derivationFromPath(*store, path), "out"));
@ -413,8 +404,6 @@ static void queryInstSources(EvalState & state,
} }
else elem.setOutPath(path); else elem.setOutPath(path);
elem.name = name;
elems.push_back(elem); elems.push_back(elem);
} }
@ -444,25 +433,24 @@ static void queryInstSources(EvalState & state,
} }
static void printMissing(EvalState & state, const DrvInfos & elems) static void printMissing(EvalState & state, DrvInfos & elems)
{ {
PathSet targets; PathSet targets;
foreach (DrvInfos::const_iterator, i, elems) { foreach (DrvInfos::iterator, i, elems) {
Path drvPath = i->queryDrvPath(state); Path drvPath = i->queryDrvPath();
if (drvPath != "") if (drvPath != "")
targets.insert(drvPath); targets.insert(drvPath);
else else
targets.insert(i->queryOutPath(state)); targets.insert(i->queryOutPath());
} }
printMissing(*store, targets); printMissing(*store, targets);
} }
static bool keep(MetaInfo & meta) static bool keep(DrvInfo & drv)
{ {
MetaValue value = meta["keep"]; return drv.queryMetaBool("keep", false);
return value.type == MetaValue::tpString && value.stringValue == "true";
} }
@ -504,10 +492,9 @@ static void installDerivations(Globals & globals,
foreach (DrvInfos::iterator, i, installedElems) { foreach (DrvInfos::iterator, i, installedElems) {
DrvName drvName(i->name); DrvName drvName(i->name);
MetaInfo meta = i->queryMetaInfo(globals.state);
if (!globals.preserveInstalled && if (!globals.preserveInstalled &&
newNames.find(drvName.name) != newNames.end() && newNames.find(drvName.name) != newNames.end() &&
!keep(meta)) !keep(*i))
printMsg(lvlInfo, format("replacing old `%1%'") % i->name); printMsg(lvlInfo, format("replacing old `%1%'") % i->name);
else else
allElems.push_back(*i); allElems.push_back(*i);
@ -573,8 +560,7 @@ static void upgradeDerivations(Globals & globals,
try { try {
MetaInfo meta = i->queryMetaInfo(globals.state); if (keep(*i)) {
if (keep(meta)) {
newElems.push_back(*i); newElems.push_back(*i);
continue; continue;
} }
@ -611,8 +597,8 @@ static void upgradeDerivations(Globals & globals,
} }
if (bestElem != availElems.end() && if (bestElem != availElems.end() &&
i->queryOutPath(globals.state) != i->queryOutPath() !=
bestElem->queryOutPath(globals.state)) bestElem->queryOutPath())
{ {
printMsg(lvlInfo, printMsg(lvlInfo,
format("upgrading `%1%' to `%2%'") format("upgrading `%1%' to `%2%'")
@ -657,12 +643,9 @@ static void opUpgrade(Globals & globals,
static void setMetaFlag(EvalState & state, DrvInfo & drv, static void setMetaFlag(EvalState & state, DrvInfo & drv,
const string & name, const string & value) const string & name, const string & value)
{ {
MetaInfo meta = drv.queryMetaInfo(state); Value * v = state.allocValue();
MetaValue v; mkString(*v, value.c_str());
v.type = MetaValue::tpString; drv.setMeta(name, v);
v.stringValue = value;
meta[name] = v;
drv.setMetaInfo(meta);
} }
@ -689,8 +672,7 @@ static void opSetFlag(Globals & globals,
DrvName drvName(i->name); DrvName drvName(i->name);
foreach (DrvNames::iterator, j, selectors) foreach (DrvNames::iterator, j, selectors)
if (j->matches(drvName)) { if (j->matches(drvName)) {
printMsg(lvlInfo, printMsg(lvlInfo, format("setting flag on `%1%'") % i->name);
format("setting flag on `%1%'") % i->name);
setMetaFlag(globals.state, *i, flagName, flagValue); setMetaFlag(globals.state, *i, flagName, flagValue);
break; break;
} }
@ -720,20 +702,20 @@ static void opSet(Globals & globals,
DrvInfo & drv(elems.front()); DrvInfo & drv(elems.front());
if (drv.queryDrvPath(globals.state) != "") { if (drv.queryDrvPath() != "") {
PathSet paths = singleton<PathSet>(drv.queryDrvPath(globals.state)); PathSet paths = singleton<PathSet>(drv.queryDrvPath());
printMissing(*store, paths); printMissing(*store, paths);
if (globals.dryRun) return; if (globals.dryRun) return;
store->buildPaths(paths, globals.state.repair); store->buildPaths(paths, globals.state.repair);
} }
else { else {
printMissing(*store, singleton<PathSet>(drv.queryOutPath(globals.state))); printMissing(*store, singleton<PathSet>(drv.queryOutPath()));
if (globals.dryRun) return; if (globals.dryRun) return;
store->ensurePath(drv.queryOutPath(globals.state)); store->ensurePath(drv.queryOutPath());
} }
debug(format("switching to new user environment")); debug(format("switching to new user environment"));
Path generation = createGeneration(globals.profile, drv.queryOutPath(globals.state)); Path generation = createGeneration(globals.profile, drv.queryOutPath());
switchLink(globals.profile, generation); switchLink(globals.profile, generation);
} }
@ -753,7 +735,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
foreach (Strings::iterator, j, selectors) foreach (Strings::iterator, j, selectors)
/* !!! the repeated calls to followLinksToStorePath() /* !!! the repeated calls to followLinksToStorePath()
are expensive, should pre-compute them. */ are expensive, should pre-compute them. */
if ((isPath(*j) && i->queryOutPath(globals.state) == followLinksToStorePath(*j)) if ((isPath(*j) && i->queryOutPath() == followLinksToStorePath(*j))
|| DrvName(*j).matches(drvName)) || DrvName(*j).matches(drvName))
{ {
printMsg(lvlInfo, format("uninstalling `%1%'") % i->name); printMsg(lvlInfo, format("uninstalling `%1%'") % i->name);
@ -887,18 +869,12 @@ static void queryJSON(Globals & globals, vector<DrvInfo> & elems)
pkgObj.attr("meta"); pkgObj.attr("meta");
JSONObject metaObj(cout); JSONObject metaObj(cout);
MetaInfo meta = i->queryMetaInfo(globals.state); StringSet metaNames = i->queryMetaNames();
foreach (MetaInfo::iterator, j, meta) { foreach (StringSet::iterator, j, metaNames) {
metaObj.attr(j->first); metaObj.attr(*j);
if (j->second.type == MetaValue::tpString) { Value * v = i->queryMeta(*j);
escapeJSON(cout, j->second.stringValue); PathSet context;
} else if (j->second.type == MetaValue::tpInt) { printValueAsJSON(globals.state, true, *v, cout, context);
cout << j->second.intValue;
} else if (j->second.type == MetaValue::tpStrings) {
JSONList l(cout);
foreach (Strings::iterator, k, j->second.stringValues)
l.elem(*k);
}
} }
} }
} }
@ -983,7 +959,7 @@ static void opQuery(Globals & globals,
if (printStatus) { if (printStatus) {
for (DrvInfos::iterator i = installedElems.begin(); for (DrvInfos::iterator i = installedElems.begin();
i != installedElems.end(); ++i) i != installedElems.end(); ++i)
installed.insert(i->queryOutPath(globals.state)); installed.insert(i->queryOutPath());
} }
@ -993,7 +969,7 @@ static void opQuery(Globals & globals,
PathSet paths; PathSet paths;
foreach (vector<DrvInfo>::iterator, i, elems) foreach (vector<DrvInfo>::iterator, i, elems)
try { try {
paths.insert(i->queryOutPath(globals.state)); paths.insert(i->queryOutPath());
} catch (AssertionError & e) { } catch (AssertionError & e) {
printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name); printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name);
i->setFailed(); i->setFailed();
@ -1021,8 +997,8 @@ static void opQuery(Globals & globals,
startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath); startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath);
if (globals.prebuiltOnly && if (globals.prebuiltOnly &&
validPaths.find(i->queryOutPath(globals.state)) == validPaths.end() && validPaths.find(i->queryOutPath()) == validPaths.end() &&
substitutablePaths.find(i->queryOutPath(globals.state)) == substitutablePaths.end()) substitutablePaths.find(i->queryOutPath()) == substitutablePaths.end())
continue; continue;
/* For table output. */ /* For table output. */
@ -1032,7 +1008,7 @@ static void opQuery(Globals & globals,
XMLAttrs attrs; XMLAttrs attrs;
if (printStatus) { if (printStatus) {
Path outPath = i->queryOutPath(globals.state); Path outPath = i->queryOutPath();
bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end(); bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end();
bool isInstalled = installed.find(outPath) != installed.end(); bool isInstalled = installed.find(outPath) != installed.end();
bool isValid = validPaths.find(outPath) != validPaths.end(); bool isValid = validPaths.find(outPath) != validPaths.end();
@ -1093,7 +1069,7 @@ static void opQuery(Globals & globals,
columns.push_back(i->system); columns.push_back(i->system);
if (printDrvPath) { if (printDrvPath) {
string drvPath = i->queryDrvPath(globals.state); string drvPath = i->queryDrvPath();
if (xmlOutput) { if (xmlOutput) {
if (drvPath != "") attrs["drvPath"] = drvPath; if (drvPath != "") attrs["drvPath"] = drvPath;
} else } else
@ -1101,7 +1077,7 @@ static void opQuery(Globals & globals,
} }
if (printOutPath && !xmlOutput) { if (printOutPath && !xmlOutput) {
DrvInfo::Outputs outputs = i->queryOutputs(globals.state); DrvInfo::Outputs outputs = i->queryOutputs();
string s; string s;
foreach (DrvInfo::Outputs::iterator, j, outputs) { foreach (DrvInfo::Outputs::iterator, j, outputs) {
if (!s.empty()) s += ';'; if (!s.empty()) s += ';';
@ -1112,9 +1088,7 @@ static void opQuery(Globals & globals,
} }
if (printDescription) { if (printDescription) {
MetaInfo meta = i->queryMetaInfo(globals.state); string descr = i->queryMetaString("description");
MetaValue value = meta["description"];
string descr = value.type == MetaValue::tpString ? value.stringValue : "";
if (xmlOutput) { if (xmlOutput) {
if (descr != "") attrs["description"] = descr; if (descr != "") attrs["description"] = descr;
} else } else
@ -1125,7 +1099,7 @@ static void opQuery(Globals & globals,
if (printOutPath || printMeta) { if (printOutPath || printMeta) {
XMLOpenElement item(xml, "item", attrs); XMLOpenElement item(xml, "item", attrs);
if (printOutPath) { if (printOutPath) {
DrvInfo::Outputs outputs = i->queryOutputs(globals.state); DrvInfo::Outputs outputs = i->queryOutputs();
foreach (DrvInfo::Outputs::iterator, j, outputs) { foreach (DrvInfo::Outputs::iterator, j, outputs) {
XMLAttrs attrs2; XMLAttrs attrs2;
attrs2["name"] = j->first; attrs2["name"] = j->first;
@ -1134,24 +1108,30 @@ static void opQuery(Globals & globals,
} }
} }
if (printMeta) { if (printMeta) {
MetaInfo meta = i->queryMetaInfo(globals.state); StringSet metaNames = i->queryMetaNames();
foreach (MetaInfo::iterator, j, meta) { foreach (StringSet::iterator, j, metaNames) {
XMLAttrs attrs2; XMLAttrs attrs2;
attrs2["name"] = j->first; attrs2["name"] = *j;
if (j->second.type == MetaValue::tpString) { Value & v(*i->queryMeta(*j));
if (v.type == tString) {
attrs2["type"] = "string"; attrs2["type"] = "string";
attrs2["value"] = j->second.stringValue; attrs2["value"] = v.string.s;
xml.writeEmptyElement("meta", attrs2); xml.writeEmptyElement("meta", attrs2);
} else if (j->second.type == MetaValue::tpInt) { } else if (v.type == tInt) {
attrs2["type"] = "int"; attrs2["type"] = "int";
attrs2["value"] = (format("%1%") % j->second.intValue).str(); attrs2["value"] = (format("%1%") % v.integer).str();
xml.writeEmptyElement("meta", attrs2); xml.writeEmptyElement("meta", attrs2);
} else if (j->second.type == MetaValue::tpStrings) { } else if (v.type == tBool) {
attrs2["type"] = "bool";
attrs2["value"] = v.boolean ? "true" : "false";
xml.writeEmptyElement("meta", attrs2);
} else if (v.type == tList) {
attrs2["type"] = "strings"; attrs2["type"] = "strings";
XMLOpenElement m(xml, "meta", attrs2); XMLOpenElement m(xml, "meta", attrs2);
foreach (Strings::iterator, k, j->second.stringValues) { for (unsigned int j = 0; j < v.list.length; ++j) {
string s = globals.state.forceStringNoCtx(*v.list.elems[j]);
XMLAttrs attrs3; XMLAttrs attrs3;
attrs3["value"] = *k; attrs3["value"] = s;
xml.writeEmptyElement("string", attrs3); xml.writeEmptyElement("string", attrs3);
} }
} }
@ -1166,6 +1146,9 @@ static void opQuery(Globals & globals,
} catch (AssertionError & e) { } catch (AssertionError & e) {
printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name); printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name);
} catch (Error & e) {
e.addPrefix(format("while querying the derivation named `%1%':\n") % i->name);
throw;
} }
} }

View file

@ -5,6 +5,7 @@
#include "globals.hh" #include "globals.hh"
#include "shared.hh" #include "shared.hh"
#include "eval.hh" #include "eval.hh"
#include "eval-inline.hh"
#include "profiles.hh" #include "profiles.hh"
@ -32,9 +33,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Build the components in the user environment, if they don't /* Build the components in the user environment, if they don't
exist already. */ exist already. */
PathSet drvsToBuild; PathSet drvsToBuild;
foreach (DrvInfos::const_iterator, i, elems) foreach (DrvInfos::iterator, i, elems)
if (i->queryDrvPath(state) != "") if (i->queryDrvPath() != "")
drvsToBuild.insert(i->queryDrvPath(state)); drvsToBuild.insert(i->queryDrvPath());
debug(format("building user environment dependencies")); debug(format("building user environment dependencies"));
store->buildPaths(drvsToBuild, state.repair); store->buildPaths(drvsToBuild, state.repair);
@ -48,7 +49,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Create a pseudo-derivation containing the name, system, /* Create a pseudo-derivation containing the name, system,
output paths, and optionally the derivation path, as well output paths, and optionally the derivation path, as well
as the meta attributes. */ as the meta attributes. */
Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; Path drvPath = keepDerivations ? i->queryDrvPath() : "";
Value & v(*state.allocValue()); Value & v(*state.allocValue());
manifest.list.elems[n++] = &v; manifest.list.elems[n++] = &v;
@ -58,12 +59,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
mkString(*state.allocAttr(v, state.sName), i->name); mkString(*state.allocAttr(v, state.sName), i->name);
if (!i->system.empty()) if (!i->system.empty())
mkString(*state.allocAttr(v, state.sSystem), i->system); mkString(*state.allocAttr(v, state.sSystem), i->system);
mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath(state)); mkString(*state.allocAttr(v, state.sOutPath), i->queryOutPath());
if (drvPath != "") if (drvPath != "")
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state)); mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath());
// Copy each output. // Copy each output.
DrvInfo::Outputs outputs = i->queryOutputs(state); DrvInfo::Outputs outputs = i->queryOutputs();
Value & vOutputs = *state.allocAttr(v, state.sOutputs); Value & vOutputs = *state.allocAttr(v, state.sOutputs);
state.mkList(vOutputs, outputs.size()); state.mkList(vOutputs, outputs.size());
unsigned int m = 0; unsigned int m = 0;
@ -84,28 +85,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
// Copy the meta attributes. // Copy the meta attributes.
Value & vMeta = *state.allocAttr(v, state.sMeta); Value & vMeta = *state.allocAttr(v, state.sMeta);
state.mkAttrs(vMeta, 16); state.mkAttrs(vMeta, 16);
StringSet metaNames = i->queryMetaNames();
MetaInfo meta = i->queryMetaInfo(state); foreach (StringSet::iterator, j, metaNames) {
Value * v = i->queryMeta(*j);
foreach (MetaInfo::const_iterator, j, meta) { state.strictForceValue(*v); // FIXME
Value & v2(*state.allocAttr(vMeta, state.symbols.create(j->first))); vMeta.attrs->push_back(Attr(state.symbols.create(*j), v));
switch (j->second.type) {
case MetaValue::tpInt: mkInt(v2, j->second.intValue); break;
case MetaValue::tpString: mkString(v2, j->second.stringValue); break;
case MetaValue::tpStrings: {
state.mkList(v2, j->second.stringValues.size());
unsigned int m = 0;
foreach (Strings::const_iterator, k, j->second.stringValues) {
v2.list.elems[m] = state.allocValue();
mkString(*v2.list.elems[m++], *k);
} }
break;
}
default: abort();
}
}
vMeta.attrs->sort();
v.attrs->sort(); v.attrs->sort();
if (drvPath != "") references.insert(drvPath); if (drvPath != "") references.insert(drvPath);
@ -133,13 +118,14 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Evaluate it. */ /* Evaluate it. */
debug("evaluating user environment builder"); debug("evaluating user environment builder");
DrvInfo topLevelDrv; state.forceValue(topLevel);
if (!getDerivation(state, topLevel, topLevelDrv, false)) PathSet context;
abort(); Path topLevelDrv = state.coerceToPath(*topLevel.attrs->find(state.sDrvPath)->value, context);
Path topLevelOut = state.coerceToPath(*topLevel.attrs->find(state.sOutPath)->value, context);
/* Realise the resulting store expression. */ /* Realise the resulting store expression. */
debug("building user environment"); debug("building user environment");
store->buildPaths(singleton<PathSet>(topLevelDrv.queryDrvPath(state)), state.repair); store->buildPaths(singleton<PathSet>(topLevelDrv), state.repair);
/* Switch the current user environment to the output path. */ /* Switch the current user environment to the output path. */
PathLocks lock; PathLocks lock;
@ -152,7 +138,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
} }
debug(format("switching to new user environment")); debug(format("switching to new user environment"));
Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state)); Path generation = createGeneration(profile, topLevelOut);
switchLink(profile, generation); switchLink(profile, generation);
return true; return true;

View file

@ -63,10 +63,10 @@ void processExpr(EvalState & state, const Strings & attrPaths,
DrvInfos drvs; DrvInfos drvs;
getDerivations(state, v, "", autoArgs, drvs, false); getDerivations(state, v, "", autoArgs, drvs, false);
foreach (DrvInfos::iterator, i, drvs) { foreach (DrvInfos::iterator, i, drvs) {
Path drvPath = i->queryDrvPath(state); Path drvPath = i->queryDrvPath();
/* What output do we want? */ /* What output do we want? */
string outputName = i->queryOutputName(state); string outputName = i->queryOutputName();
if (outputName == "") if (outputName == "")
throw Error(format("derivation `%1%' lacks an `outputName' attribute ") % drvPath); throw Error(format("derivation `%1%' lacks an `outputName' attribute ") % drvPath);