diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 723d3a6bc7..eaab867a6f 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -2,7 +2,11 @@ #include "nixexpr-ast.hh" -bool getDerivation(EvalState & state, Expr e, DrvInfo & drv) +typedef set Exprs; + + +static bool getDerivation(EvalState & state, Expr e, + DrvInfos & drvs, Exprs & doneExprs) { ATermList es; e = evalExpr(state, e); @@ -14,6 +18,13 @@ bool getDerivation(EvalState & state, Expr e, DrvInfo & drv) Expr a = attrs.get("type"); if (!a || evalString(state, a) != "derivation") return false; + /* Remove spurious duplicates (e.g., an attribute set like `rec { + x = derivation {...}; y = x;}'. */ + if (doneExprs.find(e) != doneExprs.end()) return true; + doneExprs.insert(e); + + DrvInfo drv; + a = attrs.get("name"); if (!a) throw badTerm("derivation name missing", e); drv.name = evalString(state, a); @@ -26,11 +37,23 @@ bool getDerivation(EvalState & state, Expr e, DrvInfo & drv) drv.attrs = attrs; + drvs.push_back(drv); return true; } -void getDerivations(EvalState & state, Expr e, DrvInfos & drvs) +bool getDerivation(EvalState & state, Expr e, DrvInfo & drv) +{ + Exprs doneExprs; + DrvInfos drvs; + bool result = getDerivation(state, e, drvs, doneExprs); + if (result) drv = drvs.front(); + return result; +} + + +static void getDerivations(EvalState & state, Expr e, + DrvInfos & drvs, Exprs & doneExprs) { ATermList es; DrvInfo drv; @@ -47,11 +70,7 @@ void getDerivations(EvalState & state, Expr e, DrvInfos & drvs) queryAllAttrs(e, drvMap); for (ATermIterator i(drvMap.keys()); i; ++i) { debug(format("evaluating attribute `%1%'") % aterm2String(*i)); - if (getDerivation(state, drvMap.get(*i), drv)) - drvs.push_back(drv); - else - ; - // parseDerivations(state, drvMap.get(*i), drvs); + getDerivation(state, drvMap.get(*i), drvs, doneExprs); } return; } @@ -59,10 +78,8 @@ void getDerivations(EvalState & state, Expr e, DrvInfos & drvs) if (matchList(e, es)) { for (ATermIterator i(es); i; ++i) { debug(format("evaluating list element")); - if (getDerivation(state, *i, drv)) - drvs.push_back(drv); - else - getDerivations(state, *i, drvs); + if (!getDerivation(state, *i, drvs, doneExprs)) + getDerivations(state, *i, drvs, doneExprs); } return; } @@ -78,9 +95,16 @@ void getDerivations(EvalState & state, Expr e, DrvInfos & drvs) else if (!matchDefFormal(*i, name, def)) abort(); /* can't happen */ } - getDerivations(state, makeCall(e, makeAttrs(ATermMap())), drvs); + getDerivations(state, makeCall(e, makeAttrs(ATermMap())), drvs, doneExprs); return; } throw Error("expression does not evaluate to a derivation (or a set or list of those)"); } + + +void getDerivations(EvalState & state, Expr e, DrvInfos & drvs) +{ + Exprs doneExprs; + getDerivations(state, e, drvs, doneExprs); +}