From 0f24400d90daf65cf20142a662f8245008437e2c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2013 14:09:03 +0100 Subject: [PATCH] Generalise meta attributes --- src/libexpr/get-drvs.cc | 167 +++++++++++++++---------- src/libexpr/get-drvs.hh | 46 ++++--- src/nix-env/nix-env.cc | 147 ++++++++++------------ src/nix-env/user-env.cc | 52 +++----- src/nix-instantiate/nix-instantiate.cc | 4 +- 5 files changed, 208 insertions(+), 208 deletions(-) diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index f5d7c189ce..42776b22ac 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -2,116 +2,155 @@ #include "util.hh" #include "eval-inline.hh" +#include + namespace nix { -string DrvInfo::queryDrvPath(EvalState & state) const +string DrvInfo::queryDrvPath() { if (drvPath == "" && attrs) { - Bindings::iterator i = attrs->find(state.sDrvPath); + Bindings::iterator i = attrs->find(state->sDrvPath); PathSet context; - (string &) drvPath = i != attrs->end() ? state.coerceToPath(*i->value, context) : ""; + drvPath = i != attrs->end() ? state->coerceToPath(*i->value, context) : ""; } return drvPath; } -string DrvInfo::queryOutPath(EvalState & state) const +string DrvInfo::queryOutPath() { if (outPath == "" && attrs) { - Bindings::iterator i = attrs->find(state.sOutPath); + Bindings::iterator i = attrs->find(state->sOutPath); PathSet context; - (string &) outPath = i != attrs->end() ? state.coerceToPath(*i->value, context) : ""; + outPath = i != attrs->end() ? state->coerceToPath(*i->value, context) : ""; } return outPath; } -DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state) +DrvInfo::Outputs DrvInfo::queryOutputs() { if (outputs.empty()) { /* Get the ‘outputs’ list. */ - Bindings::iterator i = attrs->find(state.sOutputs); - - if (i == attrs->end()) - outputs["out"] = queryOutPath(state); - else { - state.forceList(*i->value); + Bindings::iterator i; + if (attrs && (i = attrs->find(state->sOutputs)) != attrs->end()) { + state->forceList(*i->value); /* For each output... */ for (unsigned int j = 0; j < i->value->list.length; ++j) { /* Evaluate the corresponding set. */ - string name = state.forceStringNoCtx(*i->value->list.elems[j]); - Bindings::iterator out = attrs->find(state.symbols.create(name)); + string name = state->forceStringNoCtx(*i->value->list.elems[j]); + Bindings::iterator out = attrs->find(state->symbols.create(name)); if (out == attrs->end()) continue; // FIXME: throw error? - state.forceAttrs(*out->value); + state->forceAttrs(*out->value); /* 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? PathSet context; - outputs[name] = state.coerceToPath(*outPath->value, context); + outputs[name] = state->coerceToPath(*outPath->value, context); } - } + } else + outputs["out"] = queryOutPath(); } return outputs; } -string DrvInfo::queryOutputName(EvalState & state) const +string DrvInfo::queryOutputName() { if (outputName == "" && attrs) { - Bindings::iterator i = attrs->find(state.sOutputName); - (string &) outputName = i != attrs->end() ? state.forceStringNoCtx(*i->value) : ""; + Bindings::iterator i = attrs->find(state->sOutputName); + outputName = i != attrs->end() ? state->forceStringNoCtx(*i->value) : ""; } return outputName; } -MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const +Bindings * DrvInfo::getMeta() { - if (metaInfoRead) return meta; - - (bool &) metaInfoRead = true; - - Bindings::iterator a = attrs->find(state.sMeta); - if (a == attrs->end()) return meta; /* fine, empty meta information */ - - 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; - } - + if (meta) return meta; + if (!attrs) return 0; + Bindings::iterator a = attrs->find(state->sMeta); + if (a == attrs->end()) return 0; + state->forceAttrs(*a->value); + meta = a->value->attrs; return meta; } -MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const +StringSet DrvInfo::queryMetaNames() { - /* !!! evaluates all meta attributes => inefficient */ - return queryMetaInfo(state)[name]; + StringSet res; + 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; - this->meta = meta; + if (!getMeta()) return 0; + 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; done.insert(v.attrs); - DrvInfo drv; - Bindings::iterator i = v.attrs->find(state.sName); /* !!! We really would like to have a decent back trace here. */ if (i == v.attrs->end()) throw TypeError("derivation name missing"); - drv.name = state.forceStringNoCtx(*i->value); 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; - - drv.attrPath = attrPath; + DrvInfo drv( + state, + state.forceStringNoCtx(*i->value), + attrPath, + i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value), + v.attrs); drvs.push_back(drv); return false; @@ -190,8 +225,6 @@ static void getDerivations(EvalState & state, Value & vIn, state.autoCallFunction(autoArgs, vIn, v); /* Process the expression. */ - DrvInfo drv; - if (!getDerivation(state, v, pathPrefix, drvs, done, ignoreAssertionFailures)) ; else if (v.type == tAttrs) { diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index af3998e400..b5aebc1883 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -11,50 +11,50 @@ namespace nix { -struct MetaValue -{ - enum { tpNone, tpString, tpStrings, tpInt } type; - string stringValue; - Strings stringValues; - int intValue; -}; - - -typedef std::map MetaInfo; - - struct DrvInfo { public: typedef std::map Outputs; private: + EvalState * state; + string drvPath; string outPath; string outputName; Outputs outputs; - bool metaInfoRead; - MetaInfo meta; - bool failed; // set if we get an AssertionError + Bindings * attrs, * meta; + + Bindings * getMeta(); + public: string name; string attrPath; /* path towards the derivation */ string system; - /* !!! make this private */ - Bindings * attrs; + DrvInfo(EvalState & state) : state(&state), failed(false), attrs(0), meta(0) { }; + 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; - string queryOutPath(EvalState & state) const; - string queryOutputName(EvalState & state) const; - Outputs queryOutputs(EvalState & state); + StringSet queryMetaNames(); + Value * queryMeta(const string & name); + string queryMetaString(const string & name); + 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; MetaValue queryMetaInfo(EvalState & state, const string & name) const; + */ void setDrvPath(const string & s) { @@ -66,8 +66,6 @@ public: outPath = s; } - void setMetaInfo(const MetaInfo & meta); - void setFailed() { failed = true; }; bool hasFailed() { return failed; }; }; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index f0c833c0b2..2d548ba1ab 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -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"); - 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; + return drv.queryMetaInt("priority", 0); } -static int comparePriorities(EvalState & state, - const DrvInfo & drv1, const DrvInfo & drv2) +static int comparePriorities(EvalState & state, DrvInfo & drv1, DrvInfo & drv2) { 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 // 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; PathSet ps = store->querySubstitutablePaths(singleton(path)); return ps.find(path) != ps.end(); @@ -296,7 +288,8 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, } if (d > 0) { - newest[drvName.name] = *j; + newest.erase(drvName.name); + newest.insert(Newest::value_type(drvName.name, *j)); multiple.erase(j->first.name); } else if (d == 0) { multiple.insert(j->first.name); @@ -392,18 +385,16 @@ static void queryInstSources(EvalState & state, derivations). */ case srcStorePaths: { - for (Strings::const_iterator i = args.begin(); - i != args.end(); ++i) - { + foreach (Strings::const_iterator, i, args) { Path path = followLinksToStorePath(*i); - DrvInfo elem; - elem.attrs = new Bindings; string name = baseNameOf(path); string::size_type dash = name.find('-'); if (dash != string::npos) name = string(name, dash + 1); + DrvInfo elem(state, name, "", "", 0); + if (isDerivation(path)) { elem.setDrvPath(path); elem.setOutPath(findOutput(derivationFromPath(*store, path), "out")); @@ -413,8 +404,6 @@ static void queryInstSources(EvalState & state, } else elem.setOutPath(path); - elem.name = name; - 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; - foreach (DrvInfos::const_iterator, i, elems) { - Path drvPath = i->queryDrvPath(state); + foreach (DrvInfos::iterator, i, elems) { + Path drvPath = i->queryDrvPath(); if (drvPath != "") targets.insert(drvPath); else - targets.insert(i->queryOutPath(state)); + targets.insert(i->queryOutPath()); } printMissing(*store, targets); } -static bool keep(MetaInfo & meta) +static bool keep(DrvInfo & drv) { - MetaValue value = meta["keep"]; - return value.type == MetaValue::tpString && value.stringValue == "true"; + return drv.queryMetaBool("keep", false); } @@ -504,10 +492,9 @@ static void installDerivations(Globals & globals, foreach (DrvInfos::iterator, i, installedElems) { DrvName drvName(i->name); - MetaInfo meta = i->queryMetaInfo(globals.state); if (!globals.preserveInstalled && newNames.find(drvName.name) != newNames.end() && - !keep(meta)) + !keep(*i)) printMsg(lvlInfo, format("replacing old `%1%'") % i->name); else allElems.push_back(*i); @@ -573,8 +560,7 @@ static void upgradeDerivations(Globals & globals, try { - MetaInfo meta = i->queryMetaInfo(globals.state); - if (keep(meta)) { + if (keep(*i)) { newElems.push_back(*i); continue; } @@ -611,8 +597,8 @@ static void upgradeDerivations(Globals & globals, } if (bestElem != availElems.end() && - i->queryOutPath(globals.state) != - bestElem->queryOutPath(globals.state)) + i->queryOutPath() != + bestElem->queryOutPath()) { printMsg(lvlInfo, format("upgrading `%1%' to `%2%'") @@ -657,12 +643,9 @@ static void opUpgrade(Globals & globals, static void setMetaFlag(EvalState & state, DrvInfo & drv, const string & name, const string & value) { - MetaInfo meta = drv.queryMetaInfo(state); - MetaValue v; - v.type = MetaValue::tpString; - v.stringValue = value; - meta[name] = v; - drv.setMetaInfo(meta); + Value * v = state.allocValue(); + mkString(*v, value.c_str()); + drv.setMeta(name, v); } @@ -689,8 +672,7 @@ static void opSetFlag(Globals & globals, DrvName drvName(i->name); foreach (DrvNames::iterator, j, selectors) if (j->matches(drvName)) { - printMsg(lvlInfo, - format("setting flag on `%1%'") % i->name); + printMsg(lvlInfo, format("setting flag on `%1%'") % i->name); setMetaFlag(globals.state, *i, flagName, flagValue); break; } @@ -720,20 +702,20 @@ static void opSet(Globals & globals, DrvInfo & drv(elems.front()); - if (drv.queryDrvPath(globals.state) != "") { - PathSet paths = singleton(drv.queryDrvPath(globals.state)); + if (drv.queryDrvPath() != "") { + PathSet paths = singleton(drv.queryDrvPath()); printMissing(*store, paths); if (globals.dryRun) return; store->buildPaths(paths, globals.state.repair); } else { - printMissing(*store, singleton(drv.queryOutPath(globals.state))); + printMissing(*store, singleton(drv.queryOutPath())); if (globals.dryRun) return; - store->ensurePath(drv.queryOutPath(globals.state)); + store->ensurePath(drv.queryOutPath()); } 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); } @@ -753,7 +735,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors, foreach (Strings::iterator, j, selectors) /* !!! the repeated calls to followLinksToStorePath() 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)) { printMsg(lvlInfo, format("uninstalling `%1%'") % i->name); @@ -887,18 +869,12 @@ static void queryJSON(Globals & globals, vector & elems) 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); - } + StringSet metaNames = i->queryMetaNames(); + foreach (StringSet::iterator, j, metaNames) { + metaObj.attr(*j); + Value * v = i->queryMeta(*j); + PathSet context; + printValueAsJSON(globals.state, true, *v, cout, context); } } } @@ -983,7 +959,7 @@ static void opQuery(Globals & globals, if (printStatus) { for (DrvInfos::iterator i = installedElems.begin(); 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; foreach (vector::iterator, i, elems) try { - paths.insert(i->queryOutPath(globals.state)); + paths.insert(i->queryOutPath()); } catch (AssertionError & e) { printMsg(lvlTalkative, format("skipping derivation named `%1%' which gives an assertion failure") % i->name); i->setFailed(); @@ -1021,8 +997,8 @@ static void opQuery(Globals & globals, startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath); if (globals.prebuiltOnly && - validPaths.find(i->queryOutPath(globals.state)) == validPaths.end() && - substitutablePaths.find(i->queryOutPath(globals.state)) == substitutablePaths.end()) + validPaths.find(i->queryOutPath()) == validPaths.end() && + substitutablePaths.find(i->queryOutPath()) == substitutablePaths.end()) continue; /* For table output. */ @@ -1032,7 +1008,7 @@ static void opQuery(Globals & globals, XMLAttrs attrs; if (printStatus) { - Path outPath = i->queryOutPath(globals.state); + Path outPath = i->queryOutPath(); bool hasSubs = substitutablePaths.find(outPath) != substitutablePaths.end(); bool isInstalled = installed.find(outPath) != installed.end(); bool isValid = validPaths.find(outPath) != validPaths.end(); @@ -1093,7 +1069,7 @@ static void opQuery(Globals & globals, columns.push_back(i->system); if (printDrvPath) { - string drvPath = i->queryDrvPath(globals.state); + string drvPath = i->queryDrvPath(); if (xmlOutput) { if (drvPath != "") attrs["drvPath"] = drvPath; } else @@ -1101,7 +1077,7 @@ static void opQuery(Globals & globals, } if (printOutPath && !xmlOutput) { - DrvInfo::Outputs outputs = i->queryOutputs(globals.state); + DrvInfo::Outputs outputs = i->queryOutputs(); string s; foreach (DrvInfo::Outputs::iterator, j, outputs) { if (!s.empty()) s += ';'; @@ -1112,9 +1088,7 @@ static void opQuery(Globals & globals, } if (printDescription) { - MetaInfo meta = i->queryMetaInfo(globals.state); - MetaValue value = meta["description"]; - string descr = value.type == MetaValue::tpString ? value.stringValue : ""; + string descr = i->queryMetaString("description"); if (xmlOutput) { if (descr != "") attrs["description"] = descr; } else @@ -1125,7 +1099,7 @@ static void opQuery(Globals & globals, if (printOutPath || printMeta) { XMLOpenElement item(xml, "item", attrs); if (printOutPath) { - DrvInfo::Outputs outputs = i->queryOutputs(globals.state); + DrvInfo::Outputs outputs = i->queryOutputs(); foreach (DrvInfo::Outputs::iterator, j, outputs) { XMLAttrs attrs2; attrs2["name"] = j->first; @@ -1134,26 +1108,32 @@ static void opQuery(Globals & globals, } } if (printMeta) { - MetaInfo meta = i->queryMetaInfo(globals.state); - foreach (MetaInfo::iterator, j, meta) { + StringSet metaNames = i->queryMetaNames(); + foreach (StringSet::iterator, j, metaNames) { XMLAttrs attrs2; - attrs2["name"] = j->first; - if (j->second.type == MetaValue::tpString) { + attrs2["name"] = *j; + Value & v(*i->queryMeta(*j)); + if (v.type == tString) { attrs2["type"] = "string"; - attrs2["value"] = j->second.stringValue; + attrs2["value"] = v.string.s; xml.writeEmptyElement("meta", attrs2); - } else if (j->second.type == MetaValue::tpInt) { + } else if (v.type == tInt) { attrs2["type"] = "int"; - attrs2["value"] = (format("%1%") % j->second.intValue).str(); + attrs2["value"] = (format("%1%") % v.integer).str(); 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"; 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; - attrs3["value"] = *k; + attrs3["value"] = s; xml.writeEmptyElement("string", attrs3); - } + } } } } @@ -1166,6 +1146,9 @@ static void opQuery(Globals & globals, } catch (AssertionError & e) { 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; } } diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc index 64ddaadb99..0ef28a12e7 100644 --- a/src/nix-env/user-env.cc +++ b/src/nix-env/user-env.cc @@ -5,6 +5,7 @@ #include "globals.hh" #include "shared.hh" #include "eval.hh" +#include "eval-inline.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 exist already. */ PathSet drvsToBuild; - foreach (DrvInfos::const_iterator, i, elems) - if (i->queryDrvPath(state) != "") - drvsToBuild.insert(i->queryDrvPath(state)); + foreach (DrvInfos::iterator, i, elems) + if (i->queryDrvPath() != "") + drvsToBuild.insert(i->queryDrvPath()); debug(format("building user environment dependencies")); store->buildPaths(drvsToBuild, state.repair); @@ -48,7 +49,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, /* Create a pseudo-derivation containing the name, system, output paths, and optionally the derivation path, as well as the meta attributes. */ - Path drvPath = keepDerivations ? i->queryDrvPath(state) : ""; + Path drvPath = keepDerivations ? i->queryDrvPath() : ""; Value & v(*state.allocValue()); manifest.list.elems[n++] = &v; @@ -58,12 +59,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, mkString(*state.allocAttr(v, state.sName), i->name); if (!i->system.empty()) 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 != "") - mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state)); + mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath()); // Copy each output. - DrvInfo::Outputs outputs = i->queryOutputs(state); + DrvInfo::Outputs outputs = i->queryOutputs(); Value & vOutputs = *state.allocAttr(v, state.sOutputs); state.mkList(vOutputs, outputs.size()); unsigned int m = 0; @@ -84,28 +85,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, // Copy the meta attributes. Value & vMeta = *state.allocAttr(v, state.sMeta); state.mkAttrs(vMeta, 16); - - MetaInfo meta = i->queryMetaInfo(state); - - foreach (MetaInfo::const_iterator, j, meta) { - Value & v2(*state.allocAttr(vMeta, state.symbols.create(j->first))); - 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(); - } + StringSet metaNames = i->queryMetaNames(); + foreach (StringSet::iterator, j, metaNames) { + Value * v = i->queryMeta(*j); + state.strictForceValue(*v); // FIXME + vMeta.attrs->push_back(Attr(state.symbols.create(*j), v)); } - - vMeta.attrs->sort(); v.attrs->sort(); if (drvPath != "") references.insert(drvPath); @@ -133,13 +118,14 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, /* Evaluate it. */ debug("evaluating user environment builder"); - DrvInfo topLevelDrv; - if (!getDerivation(state, topLevel, topLevelDrv, false)) - abort(); + state.forceValue(topLevel); + PathSet context; + 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. */ debug("building user environment"); - store->buildPaths(singleton(topLevelDrv.queryDrvPath(state)), state.repair); + store->buildPaths(singleton(topLevelDrv), state.repair); /* Switch the current user environment to the output path. */ PathLocks lock; @@ -152,7 +138,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, } debug(format("switching to new user environment")); - Path generation = createGeneration(profile, topLevelDrv.queryOutPath(state)); + Path generation = createGeneration(profile, topLevelOut); switchLink(profile, generation); return true; diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index fd2c04eae4..b7f944062c 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -63,10 +63,10 @@ void processExpr(EvalState & state, const Strings & attrPaths, DrvInfos drvs; getDerivations(state, v, "", autoArgs, drvs, false); foreach (DrvInfos::iterator, i, drvs) { - Path drvPath = i->queryDrvPath(state); + Path drvPath = i->queryDrvPath(); /* What output do we want? */ - string outputName = i->queryOutputName(state); + string outputName = i->queryOutputName(); if (outputName == "") throw Error(format("derivation `%1%' lacks an `outputName' attribute ") % drvPath);