From a8fb575c98726f195d0cf5c7e6b7e51c75a0a9b3 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Fri, 30 May 2014 15:04:17 -0400 Subject: [PATCH] Share code between scopedImport and import In addition to reducing duplication, this fixes both import from derivation and import of derivation for scopedImport --- src/libexpr/primops.cc | 88 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index feb0227ac..f270ca302 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -39,31 +39,34 @@ std::pair decodeContext(const string & s) /* Load and evaluate an expression from path specified by the argument. */ -static void prim_import(EvalState & state, const Pos & pos, Value * * args, Value & v) +static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args, Value & v) { PathSet context; - Path path = state.coerceToPath(pos, *args[0], context); + Path path = state.coerceToPath(pos, *args[1], context); - foreach (PathSet::iterator, i, context) { - Path ctx = decodeContext(*i).first; + PathSet drvs; + for (auto & i : context) { + std::pair decoded = decodeContext(i); + Path ctx = decoded.first; assert(isStorePath(ctx)); if (!store->isValidPath(ctx)) throw EvalError(format("cannot import `%1%', since path `%2%' is not valid, at %3%") % path % ctx % pos); if (isDerivation(ctx)) - try { - /* For performance, prefetch all substitute info. */ - PathSet willBuild, willSubstitute, unknown; - unsigned long long downloadSize, narSize; - queryMissing(*store, singleton(ctx), - willBuild, willSubstitute, unknown, downloadSize, narSize); + drvs.insert(decoded.first + "!" + decoded.second); + } + if (!drvs.empty()) { + try { + /* For performance, prefetch all substitute info. */ + PathSet willBuild, willSubstitute, unknown; + unsigned long long downloadSize, narSize; + queryMissing(*store, drvs, + willBuild, willSubstitute, unknown, downloadSize, narSize); - /* !!! If using a substitute, we only need to fetch - the selected output of this derivation. */ - store->buildPaths(singleton(ctx)); - } catch (Error & e) { - throw ImportError(e.msg()); - } + store->buildPaths(drvs); + } catch (Error & e) { + throw ImportError(e.msg()); + } } if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) { @@ -88,35 +91,30 @@ static void prim_import(EvalState & state, const Pos & pos, Value * * args, Valu mkApp(v, fun, w); state.forceAttrs(v, pos); } else { - state.evalFile(path, v); + state.forceAttrs(*args[0]); + if (args[0]->attrs->empty()) + state.evalFile(path, v); + else { + Env * env = &state.allocEnv(args[0]->attrs->size()); + env->up = &state.baseEnv; + + StaticEnv staticEnv(false, &state.staticBaseEnv); + + unsigned int displ = 0; + for (auto & attr : *args[0]->attrs) { + staticEnv.vars[attr.name] = displ; + env->values[displ++] = attr.value; + } + + startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); + Expr * e = state.parseExprFromFile(resolveExprPath(path), staticEnv); + + e->eval(state, *env, v); + } } } -static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args, Value & v) -{ - PathSet context; - state.forceAttrs(*args[0]); - Path path = resolveExprPath(state.coerceToPath(pos, *args[1], context)); - - Env * env = &state.allocEnv(args[0]->attrs->size()); - env->up = &state.baseEnv; - - StaticEnv staticEnv(false, &state.staticBaseEnv); - - unsigned int displ = 0; - for (auto & attr : *args[0]->attrs) { - staticEnv.vars[attr.name] = displ; - env->values[displ++] = attr.value; - } - - startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); - Expr * e = state.parseExprFromFile(path, staticEnv); - - e->eval(state, *env, v); -} - - /* Return a string representing the type of the expression. */ static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v) { @@ -1301,8 +1299,12 @@ void EvalState::createBaseEnv() addConstant("__langVersion", v); // Miscellaneous - addPrimOp("import", 1, prim_import); addPrimOp("scopedImport", 2, prim_scopedImport); + Value * v2 = allocValue(); + mkAttrs(*v2, 0); + mkApp(v, *baseEnv.values[baseEnvDispl - 1], *v2); + forceValue(v); + addConstant("import", v); addPrimOp("__typeOf", 1, prim_typeOf); addPrimOp("isNull", 1, prim_isNull); addPrimOp("__isFunction", 1, prim_isFunction); @@ -1388,7 +1390,7 @@ void EvalState::createBaseEnv() mkList(v, searchPath.size()); int n = 0; for (auto & i : searchPath) { - Value * v2 = v.list.elems[n++] = allocValue(); + v2 = v.list.elems[n++] = allocValue(); mkAttrs(*v2, 2); mkString(*allocAttr(*v2, symbols.create("path")), i.second); mkString(*allocAttr(*v2, symbols.create("prefix")), i.first);