about summary refs log tree commit diff
path: root/src/libexpr/get-drvs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/get-drvs.cc')
-rw-r--r--src/libexpr/get-drvs.cc86
1 files changed, 58 insertions, 28 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 1c9fa02a366a..b06c539de0fb 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -30,7 +30,7 @@ string DrvInfo::queryOutPath()
 }
 
 
-DrvInfo::Outputs DrvInfo::queryOutputs()
+DrvInfo::Outputs DrvInfo::queryOutputs(bool onlyOutputsToInstall)
 {
     if (outputs.empty()) {
         /* Get the ‘outputs’ list. */
@@ -39,9 +39,9 @@ DrvInfo::Outputs DrvInfo::queryOutputs()
             state->forceList(*i->value, *i->pos);
 
             /* For each output... */
-            for (unsigned int j = 0; j < i->value->list.length; ++j) {
+            for (unsigned int j = 0; j < i->value->listSize(); ++j) {
                 /* Evaluate the corresponding set. */
-                string name = state->forceStringNoCtx(*i->value->list.elems[j], *i->pos);
+                string name = state->forceStringNoCtx(*i->value->listElems()[j], *i->pos);
                 Bindings::iterator out = attrs->find(state->symbols.create(name));
                 if (out == attrs->end()) continue; // FIXME: throw error?
                 state->forceAttrs(*out->value);
@@ -55,7 +55,23 @@ DrvInfo::Outputs DrvInfo::queryOutputs()
         } else
             outputs["out"] = queryOutPath();
     }
-    return outputs;
+    if (!onlyOutputsToInstall || !attrs)
+        return outputs;
+
+    /* Check for `meta.outputsToInstall` and return `outputs` reduced to that. */
+    const Value * outTI = queryMeta("outputsToInstall");
+    if (!outTI) return outputs;
+    const auto errMsg = Error("this derivation has bad ‘meta.outputsToInstall’");
+        /* ^ this shows during `nix-env -i` right under the bad derivation */
+    if (!outTI->isList()) throw errMsg;
+    Outputs result;
+    for (auto i = outTI->listElems(); i != outTI->listElems() + outTI->listSize(); ++i) {
+        if ((*i)->type != tString) throw errMsg;
+        auto out = outputs.find((*i)->string.s);
+        if (out == outputs.end()) throw errMsg;
+        result.insert(*out);
+    }
+    return result;
 }
 
 
@@ -85,8 +101,8 @@ StringSet DrvInfo::queryMetaNames()
 {
     StringSet res;
     if (!getMeta()) return res;
-    foreach (Bindings::iterator, i, *meta)
-        res.insert(i->name);
+    for (auto & i : *meta)
+        res.insert(i.name);
     return res;
 }
 
@@ -94,19 +110,20 @@ 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;
+    if (v.isList()) {
+        for (unsigned int n = 0; n < v.listSize(); ++n)
+            if (!checkMeta(*v.listElems()[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;
+        for (auto & i : *v.attrs)
+            if (!checkMeta(*i.value)) return false;
         return true;
     }
-    else return v.type == tInt || v.type == tBool || v.type == tString;
+    else return v.type == tInt || v.type == tBool || v.type == tString ||
+                v.type == tFloat;
 }
 
 
@@ -127,7 +144,7 @@ string DrvInfo::queryMetaString(const string & name)
 }
 
 
-int DrvInfo::queryMetaInt(const string & name, int def)
+NixInt DrvInfo::queryMetaInt(const string & name, NixInt def)
 {
     Value * v = queryMeta(name);
     if (!v) return def;
@@ -135,12 +152,26 @@ int DrvInfo::queryMetaInt(const string & name, int def)
     if (v->type == tString) {
         /* Backwards compatibility with before we had support for
            integer meta fields. */
-        int n;
+        NixInt n;
         if (string2Int(v->string.s, n)) return n;
     }
     return def;
 }
 
+NixFloat DrvInfo::queryMetaFloat(const string & name, NixFloat def)
+{
+    Value * v = queryMeta(name);
+    if (!v) return def;
+    if (v->type == tFloat) return v->fpoint;
+    if (v->type == tString) {
+        /* Backwards compatibility with before we had support for
+           float meta fields. */
+        NixFloat n;
+        if (string2Float(v->string.s, n)) return n;
+    }
+    return def;
+}
+
 
 bool DrvInfo::queryMetaBool(const string & name, bool def)
 {
@@ -177,8 +208,8 @@ typedef set<Bindings *> Done;
 
 
 /* Evaluate value `v'.  If it evaluates to a set of type `derivation',
-   then put information about it in `drvs' (unless it's already in
-   `doneExprs').  The result boolean indicates whether it makes sense
+   then put information about it in `drvs' (unless it's already in `done').
+   The result boolean indicates whether it makes sense
    for the caller to recursively search for derivations in `v'. */
 static bool getDerivation(EvalState & state, Value & v,
     const string & attrPath, DrvInfos & drvs, Done & done,
@@ -255,13 +286,13 @@ static void getDerivations(EvalState & state, Value & vIn,
            precedence). */
         typedef std::map<string, Symbol> SortedSymbols;
         SortedSymbols attrs;
-        foreach (Bindings::iterator, i, *v.attrs)
-            attrs.insert(std::pair<string, Symbol>(i->name, i->name));
+        for (auto & i : *v.attrs)
+            attrs.insert(std::pair<string, Symbol>(i.name, i.name));
 
-        foreach (SortedSymbols::iterator, i, attrs) {
-            startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i->first);
-            string pathPrefix2 = addToPath(pathPrefix, i->first);
-            Value & v2(*v.attrs->find(i->second)->value);
+        for (auto & i : attrs) {
+            Activity act(*logger, lvlDebug, format("evaluating attribute ‘%1%’") % i.first);
+            string pathPrefix2 = addToPath(pathPrefix, i.first);
+            Value & v2(*v.attrs->find(i.second)->value);
             if (combineChannels)
                 getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
             else if (getDerivation(state, v2, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
@@ -277,13 +308,12 @@ static void getDerivations(EvalState & state, Value & vIn,
         }
     }
 
-    else if (v.type == tList) {
-        for (unsigned int n = 0; n < v.list.length; ++n) {
-            startNest(nest, lvlDebug,
-                format("evaluating list element"));
+    else if (v.isList()) {
+        for (unsigned int n = 0; n < v.listSize(); ++n) {
+            Activity act(*logger, lvlDebug, "evaluating list element");
             string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
-            if (getDerivation(state, *v.list.elems[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
-                getDerivations(state, *v.list.elems[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
+            if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, ignoreAssertionFailures))
+                getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
         }
     }