aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-11-19 14:09:03 +0100
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-11-19 14:09:14 +0100
commit0f24400d90daf65cf20142a662f8245008437e2c (patch)
tree0daf395a2ff226203b9560edc74ebe1efd89862c /src/libexpr
parent990126cde03428509191bed132f38050034d342e (diff)
Generalise meta attributes
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/get-drvs.cc159
-rw-r--r--src/libexpr/get-drvs.hh46
2 files changed, 118 insertions, 87 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index f5d7c189c..42776b22a 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 <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;
+ 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;
+}
- (bool &) metaInfoRead = true;
- Bindings::iterator a = attrs->find(state.sMeta);
- if (a == attrs->end()) return meta; /* fine, empty meta information */
+StringSet DrvInfo::queryMetaNames()
+{
+ StringSet res;
+ if (!getMeta()) return res;
+ foreach (Bindings::iterator, i, *meta)
+ res.insert(i->name);
+ return res;
+}
- 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;
- }
+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);
+ return a->value;
+}
- return meta;
+
+string DrvInfo::queryMetaString(const string & name)
+{
+ Value * v = queryMeta(name);
+ if (!v || v->type != tString) return "";
+ return v->string.s;
}
-MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
+int DrvInfo::queryMetaInt(const string & name, int def)
{
- /* !!! evaluates all meta attributes => inefficient */
- return queryMetaInfo(state)[name];
+ 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;
}
-void DrvInfo::setMetaInfo(const MetaInfo & meta)
+bool DrvInfo::queryMetaBool(const string & name, bool def)
{
- metaInfoRead = true;
- this->meta = meta;
+ 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 af3998e40..b5aebc188 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<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) { };
+
+ string queryDrvPath();
+ string queryOutPath();
+ string queryOutputName();
+ Outputs queryOutputs();
- DrvInfo() : metaInfoRead(false), failed(false), attrs(0) { };
+ 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);
- string queryDrvPath(EvalState & state) const;
- string queryOutPath(EvalState & state) const;
- string queryOutputName(EvalState & state) const;
- Outputs queryOutputs(EvalState & state);
+ /*
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; };
};