From 0f24400d90daf65cf20142a662f8245008437e2c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 19 Nov 2013 14:09:03 +0100 Subject: Generalise meta attributes --- src/nix-env/nix-env.cc | 147 +++++++++++++++++++++--------------------------- src/nix-env/user-env.cc | 52 +++++++---------- 2 files changed, 84 insertions(+), 115 deletions(-) (limited to 'src/nix-env') diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index f0c833c0b22c..2d548ba1abd1 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 (v.type == tBool) { + attrs2["type"] = "bool"; + attrs2["value"] = v.boolean ? "true" : "false"; xml.writeEmptyElement("meta", attrs2); - } else if (j->second.type == MetaValue::tpStrings) { + } 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 64ddaadb99cf..0ef28a12e73f 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; -- cgit 1.4.1