From 02c1dac90934e1b833c4d6bd9280bda27c146d80 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 16 Apr 2010 13:44:02 +0000 Subject: [PATCH] * In an nested `with' where the inner with is a variable (`with ...; with someVar; ...'), the contents of the variable would be clobbered. (The attributes in the outer `with' were added to the variable.) --- src/libexpr/eval.cc | 8 +++++++- src/libexpr/get-drvs.cc | 13 +++++++------ src/nix-env/nix-env.cc | 1 + 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 69e7bd8b3c..ac475c8931 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -649,6 +649,11 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) Env * env3 = &env; for (unsigned int l = prevWith; l; --l, env3 = env3->up) ; + /* Because the first `with' may be a shallow copy of another + attribute set (through a tCopy node), we need to clone its + `attrs' before modifying them. */ + env2.values[0].attrs = new Bindings(*env2.values[0].attrs); + foreach (Bindings::iterator, i, *env3->values[0].attrs) { Bindings::iterator j = env2.values[0].attrs->find(i->first); if (j == env2.values[0].attrs->end()) @@ -1042,7 +1047,8 @@ void EvalState::printStats() printMsg(v, format(" expressions evaluated: %1%") % nrEvaluated); printMsg(v, format(" stack space used: %1% bytes") % (&x - deepestStack)); printMsg(v, format(" max eval() nesting depth: %1%") % maxRecursionDepth); - printMsg(v, format(" stack space per eval() level: %1% bytes") % ((&x - deepestStack) / (float) maxRecursionDepth)); + printMsg(v, format(" stack space per eval() level: %1% bytes") + % ((&x - deepestStack) / (float) maxRecursionDepth)); printMsg(v, format(" environments allocated: %1% (%2% bytes)") % nrEnvs % (nrEnvs * sizeof(Env))); printMsg(v, format(" values allocated in environments: %1% (%2% bytes)") diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 6964e3e3b7..8af011d549 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -177,14 +177,15 @@ static void getDerivations(EvalState & state, Value & vIn, there are names clashes between derivations, the derivation bound to the attribute with the "lower" name should take precedence). */ - StringSet attrs; + typedef std::map SortedSymbols; + SortedSymbols attrs; foreach (Bindings::iterator, i, *v.attrs) - attrs.insert(i->first); + attrs.insert(std::pair(i->first, i->first)); - foreach (StringSet::iterator, i, attrs) { - startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i); - string pathPrefix2 = addToPath(pathPrefix, *i); - Value & v2((*v.attrs)[state.symbols.create(*i)]); + foreach (SortedSymbols::iterator, i, attrs) { + startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first); + string pathPrefix2 = addToPath(pathPrefix, i->first); + Value & v2((*v.attrs)[i->second]); if (combineChannels) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); else if (getDerivation(state, v2, pathPrefix2, drvs, done)) { diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index d44517ba67..f9f828fe91 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1089,6 +1089,7 @@ static void opQuery(Globals & globals, foreach (vector::iterator, i, elems2) { try { + startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath); /* For table output. */ Strings columns;