diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2010-03-31 15:38:03 +0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2010-03-31 15:38:03 +0000 |
commit | 3d94be61ea562dea2098b6570f711386179913ef (patch) | |
tree | 9afd60cf782d5824efc4bafba98af1ee6af937f4 /src/libexpr/get-drvs.cc | |
parent | 51876789131e81dca9807c00773158160c3824c2 (diff) |
* Implemented derivations.
Diffstat (limited to 'src/libexpr/get-drvs.cc')
-rw-r--r-- | src/libexpr/get-drvs.cc | 143 |
1 files changed, 58 insertions, 85 deletions
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 26ce6e71c..5ff77ff65 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -6,25 +6,18 @@ namespace nix { -#if 0 string DrvInfo::queryDrvPath(EvalState & state) const { if (drvPath == "") { - Expr a = attrs->get(toATerm("drvPath")); - - /* Backwards compatibility hack with user environments made by - Nix <= 0.10: these contain illegal Path("") expressions. */ - ATerm t; - if (a && matchPath(evalExpr(state, a), t)) - return aterm2String(t); - + Bindings::iterator i = attrs->find(toATerm("drvPath")); PathSet context; - (string &) drvPath = a ? coerceToPath(state, a, context) : ""; + (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; } return drvPath; } +#if 0 string DrvInfo::queryOutPath(EvalState & state) const { if (outPath == "") { @@ -102,54 +95,47 @@ void DrvInfo::setMetaInfo(const MetaInfo & meta) } attrs->set(toATerm("meta"), makeAttrs(metaAttrs)); } +#endif -/* Cache for already evaluated derivations. Usually putting ATerms in - a STL container is unsafe (they're not scanning for GC roots), but - here it doesn't matter; everything in this set is reachable from - the stack as well. */ -typedef set<Expr> Exprs; +/* Cache for already considered values. */ +typedef set<Value *> Values; -/* Evaluate expression `e'. If it evaluates to an attribute 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 for the caller to recursively search for derivations - in `e'. */ -static bool getDerivation(EvalState & state, Expr e, - const string & attrPath, DrvInfos & drvs, Exprs & doneExprs) +/* Evaluate value `v'. If it evaluates to an attribute 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 for the caller to recursively search for derivations in + `v'. */ +static bool getDerivation(EvalState & state, Value & v, + const string & attrPath, DrvInfos & drvs, Values & doneValues) { try { - - ATermList es; - e = evalExpr(state, e); - if (!matchAttrs(e, es)) return true; + state.forceValue(v); + if (v.type != tAttrs) return true; - boost::shared_ptr<ATermMap> attrs(new ATermMap()); - queryAllAttrs(e, *attrs, false); - - Expr a = attrs->get(toATerm("type")); - if (!a || evalStringNoCtx(state, a) != "derivation") return true; + Bindings::iterator i = v.attrs->find(toATerm("type")); + if (i == v.attrs->end() || state.forceStringNoCtx(i->second) != "derivation") return true; /* Remove spurious duplicates (e.g., an attribute set like `rec { x = derivation {...}; y = x;}'. */ - if (doneExprs.find(e) != doneExprs.end()) return false; - doneExprs.insert(e); + if (doneValues.find(&v) != doneValues.end()) return false; + doneValues.insert(&v); DrvInfo drv; - a = attrs->get(toATerm("name")); + i = v.attrs->find(toATerm("name")); /* !!! We really would like to have a decent back trace here. */ - if (!a) throw TypeError("derivation name missing"); - drv.name = evalStringNoCtx(state, a); + if (i == v.attrs->end()) throw TypeError("derivation name missing"); + drv.name = state.forceStringNoCtx(i->second); - a = attrs->get(toATerm("system")); - if (!a) + i = v.attrs->find(toATerm("system")); + if (i == v.attrs->end()) drv.system = "unknown"; else - drv.system = evalStringNoCtx(state, a); + drv.system = state.forceStringNoCtx(i->second); - drv.attrs = attrs; + drv.attrs = v.attrs; drv.attrPath = attrPath; @@ -162,11 +148,11 @@ static bool getDerivation(EvalState & state, Expr e, } -bool getDerivation(EvalState & state, Expr e, DrvInfo & drv) +bool getDerivation(EvalState & state, Value & v, DrvInfo & drv) { - Exprs doneExprs; + Values doneValues; DrvInfos drvs; - getDerivation(state, e, "", drvs, doneExprs); + getDerivation(state, v, "", drvs, doneValues); if (drvs.size() != 1) return false; drv = drvs.front(); return true; @@ -179,85 +165,72 @@ static string addToPath(const string & s1, const string & s2) } -static void getDerivations(EvalState & state, Expr e, +static void getDerivations(EvalState & state, Value & v, const string & pathPrefix, const ATermMap & autoArgs, - DrvInfos & drvs, Exprs & doneExprs) + DrvInfos & drvs, Values & doneValues) { - e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs)); - + // !!! autoCallFunction(evalExpr(state, e), autoArgs) + /* Process the expression. */ - ATermList es; DrvInfo drv; - if (!getDerivation(state, e, pathPrefix, drvs, doneExprs)) - return; + if (!getDerivation(state, v, pathPrefix, drvs, doneValues)) ; - if (matchAttrs(e, es)) { - ATermMap drvMap(ATgetLength(es)); - queryAllAttrs(e, drvMap); + else if (v.type == tAttrs) { /* !!! undocumented hackery to support combining channels in nix-env.cc. */ - bool combineChannels = drvMap.get(toATerm("_combineChannels")); + bool combineChannels = v.attrs->find(toATerm("_combineChannels")) != v.attrs->end(); /* Consider the attributes in sorted order to get more deterministic behaviour in nix-env operations (e.g. when there are names clashes between derivations, the derivation bound to the attribute with the "lower" name should take precedence). */ - typedef std::map<string, Expr> AttrsSorted; - AttrsSorted attrsSorted; - foreach (ATermMap::const_iterator, i, drvMap) - attrsSorted[aterm2String(i->key)] = i->value; - - foreach (AttrsSorted::iterator, i, attrsSorted) { - startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first); - string pathPrefix2 = addToPath(pathPrefix, i->first); + StringSet attrs; + foreach (Bindings::iterator, i, *v.attrs) + attrs.insert(aterm2String(i->first)); + + foreach (StringSet::iterator, i, attrs) { + startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i); + string pathPrefix2 = addToPath(pathPrefix, *i); + Value & v2((*v.attrs)[toATerm(*i)]); if (combineChannels) - getDerivations(state, i->second, pathPrefix2, autoArgs, drvs, doneExprs); - else if (getDerivation(state, i->second, pathPrefix2, drvs, doneExprs)) { + getDerivations(state, v2, pathPrefix2, autoArgs, drvs, doneValues); + else if (getDerivation(state, v2, pathPrefix2, drvs, doneValues)) { /* If the value of this attribute is itself an attribute set, should we recurse into it? => Only if it has a `recurseForDerivations = true' attribute. */ - ATermList es; - Expr e = evalExpr(state, i->second), e2; - if (matchAttrs(e, es)) { - ATermMap attrs(ATgetLength(es)); - queryAllAttrs(e, attrs, false); - if (((e2 = attrs.get(toATerm("recurseForDerivations"))) - && evalBool(state, e2))) - getDerivations(state, e, pathPrefix2, autoArgs, drvs, doneExprs); + if (v2.type == tAttrs) { + Bindings::iterator j = v2.attrs->find(toATerm("recurseForDerivations")); + if (j != v2.attrs->end() && state.forceBool(j->second)) + getDerivations(state, v2, pathPrefix2, autoArgs, drvs, doneValues); } } } - - return; } - if (matchList(e, es)) { - int n = 0; - for (ATermIterator i(es); i; ++i, ++n) { + else if (v.type == tList) { + for (unsigned int n = 0; n < v.list.length; ++n) { startNest(nest, lvlDebug, format("evaluating list element")); string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str()); - if (getDerivation(state, *i, pathPrefix2, drvs, doneExprs)) - getDerivations(state, *i, pathPrefix2, autoArgs, drvs, doneExprs); + if (getDerivation(state, v.list.elems[n], pathPrefix2, drvs, doneValues)) + getDerivations(state, v.list.elems[n], pathPrefix2, autoArgs, drvs, doneValues); } - return; } - throw TypeError("expression does not evaluate to a derivation (or a set or list of those)"); + else throw TypeError("expression does not evaluate to a derivation (or a set or list of those)"); } -void getDerivations(EvalState & state, Expr e, const string & pathPrefix, +void getDerivations(EvalState & state, Value & v, const string & pathPrefix, const ATermMap & autoArgs, DrvInfos & drvs) { - Exprs doneExprs; - getDerivations(state, e, pathPrefix, autoArgs, drvs, doneExprs); + Values doneValues; + getDerivations(state, v, pathPrefix, autoArgs, drvs, doneValues); } -#endif } |