diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 42776b22ac..0ed644e9bc 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -91,12 +91,30 @@ StringSet DrvInfo::queryMetaNames() } +bool DrvInfo::checkMeta(Value & v) +{ + state->forceValue(v); + if (v.type == tList) { + for (unsigned int n = 0; n < v.list.length; ++n) + if (!checkMeta(*v.list.elems[n])) return false; + return true; + } + else if (v.type == tAttrs) { + Bindings::iterator i = v.attrs->find(state->sOutPath); + if (i != v.attrs->end()) return false; + foreach (Bindings::iterator, i, *v.attrs) + if (!checkMeta(*i->value)) return false; + return true; + } + else return v.type == tInt || v.type == tBool || v.type == tString; +} + + Value * DrvInfo::queryMeta(const string & name) { if (!getMeta()) return 0; Bindings::iterator a = meta->find(state->symbols.create(name)); - if (a == meta->end()) return 0; - state->forceValue(*a->value); + if (a == meta->end() || !checkMeta(*a->value)) return 0; return a->value; } diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index b5aebc1883..aaafff1905 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -30,6 +30,8 @@ private: Bindings * getMeta(); + bool checkMeta(Value & v); + public: string name; string attrPath; /* path towards the derivation */ diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 2d548ba1ab..cf74747dac 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -873,8 +873,12 @@ static void queryJSON(Globals & globals, vector & elems) foreach (StringSet::iterator, j, metaNames) { metaObj.attr(*j); Value * v = i->queryMeta(*j); - PathSet context; - printValueAsJSON(globals.state, true, *v, cout, context); + if (!v) + printMsg(lvlError, format("derivation `%1%' has invalid meta attribute `%2%'") % i->name % *j); + else { + PathSet context; + printValueAsJSON(globals.state, true, *v, cout, context); + } } } } @@ -1112,27 +1116,31 @@ static void opQuery(Globals & globals, foreach (StringSet::iterator, j, metaNames) { XMLAttrs attrs2; attrs2["name"] = *j; - Value & v(*i->queryMeta(*j)); - if (v.type == tString) { - attrs2["type"] = "string"; - attrs2["value"] = v.string.s; - xml.writeEmptyElement("meta", attrs2); - } else if (v.type == tInt) { - attrs2["type"] = "int"; - attrs2["value"] = (format("%1%") % v.integer).str(); - xml.writeEmptyElement("meta", attrs2); - } 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"; - XMLOpenElement m(xml, "meta", attrs2); - for (unsigned int j = 0; j < v.list.length; ++j) { - string s = globals.state.forceStringNoCtx(*v.list.elems[j]); - XMLAttrs attrs3; - attrs3["value"] = s; - xml.writeEmptyElement("string", attrs3); + Value * v = i->queryMeta(*j); + if (!v) + printMsg(lvlError, format("derivation `%1%' has invalid meta attribute `%2%'") % i->name % *j); + else { + if (v->type == tString) { + attrs2["type"] = "string"; + attrs2["value"] = v->string.s; + xml.writeEmptyElement("meta", attrs2); + } else if (v->type == tInt) { + attrs2["type"] = "int"; + attrs2["value"] = (format("%1%") % v->integer).str(); + xml.writeEmptyElement("meta", attrs2); + } 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"; + XMLOpenElement m(xml, "meta", attrs2); + for (unsigned int j = 0; j < v->list.length; ++j) { + if (v->list.elems[j]->type != tString) continue; + XMLAttrs attrs3; + attrs3["value"] = v->list.elems[j]->string.s; + xml.writeEmptyElement("string", attrs3); + } } } } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 0ef28a12e7..c2dab4f0c7 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -88,7 +88,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, StringSet metaNames = i->queryMetaNames(); foreach (StringSet::iterator, j, metaNames) { Value * v = i->queryMeta(*j); - state.strictForceValue(*v); // FIXME + if (!v) continue; vMeta.attrs->push_back(Attr(state.symbols.create(*j), v)); } v.attrs->sort();