Generalise meta attributes
This commit is contained in:
		
							parent
							
								
									990126cde0
								
							
						
					
					
						commit
						0f24400d90
					
				
					 5 changed files with 208 additions and 208 deletions
				
			
		|  | @ -2,116 +2,155 @@ | |||
| #include "util.hh" | ||||
| #include "eval-inline.hh" | ||||
| 
 | ||||
| #include <cstring> | ||||
| 
 | ||||
| 
 | ||||
| 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) { | ||||
|  |  | |||
|  | @ -11,50 +11,50 @@ | |||
| namespace nix { | ||||
| 
 | ||||
| 
 | ||||
| struct MetaValue | ||||
| { | ||||
|     enum { tpNone, tpString, tpStrings, tpInt } type; | ||||
|     string stringValue; | ||||
|     Strings stringValues; | ||||
|     int intValue; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| typedef std::map<string, MetaValue> MetaInfo; | ||||
| 
 | ||||
| 
 | ||||
| struct DrvInfo | ||||
| { | ||||
| public: | ||||
|     typedef std::map<string, Path> 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; }; | ||||
| }; | ||||
|  |  | |||
|  | @ -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<PathSet>(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<PathSet>(drv.queryDrvPath(globals.state)); | ||||
|     if (drv.queryDrvPath() != "") { | ||||
|         PathSet paths = singleton<PathSet>(drv.queryDrvPath()); | ||||
|         printMissing(*store, paths); | ||||
|         if (globals.dryRun) return; | ||||
|         store->buildPaths(paths, globals.state.repair); | ||||
|     } | ||||
|     else { | ||||
|         printMissing(*store, singleton<PathSet>(drv.queryOutPath(globals.state))); | ||||
|         printMissing(*store, singleton<PathSet>(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<DrvInfo> & 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<DrvInfo>::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,24 +1108,30 @@ 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; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|         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)); | ||||
|         } | ||||
|                     break; | ||||
|                 } | ||||
|                 default: abort(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         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<PathSet>(topLevelDrv.queryDrvPath(state)), state.repair); | ||||
|     store->buildPaths(singleton<PathSet>(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; | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue