Share code between scopedImport and import

In addition to reducing duplication, this fixes both import from
derivation and import of derivation for scopedImport
This commit is contained in:
Shea Levy 2014-05-30 15:04:17 -04:00 committed by Eelco Dolstra
parent 61c464f252
commit a8fb575c98

View file

@ -39,28 +39,31 @@ std::pair<string, string> decodeContext(const string & s)
/* Load and evaluate an expression from path specified by the /* Load and evaluate an expression from path specified by the
argument. */ 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; PathSet context;
Path path = state.coerceToPath(pos, *args[0], context); Path path = state.coerceToPath(pos, *args[1], context);
foreach (PathSet::iterator, i, context) { PathSet drvs;
Path ctx = decodeContext(*i).first; for (auto & i : context) {
std::pair<string, string> decoded = decodeContext(i);
Path ctx = decoded.first;
assert(isStorePath(ctx)); assert(isStorePath(ctx));
if (!store->isValidPath(ctx)) if (!store->isValidPath(ctx))
throw EvalError(format("cannot import `%1%', since path `%2%' is not valid, at %3%") throw EvalError(format("cannot import `%1%', since path `%2%' is not valid, at %3%")
% path % ctx % pos); % path % ctx % pos);
if (isDerivation(ctx)) if (isDerivation(ctx))
drvs.insert(decoded.first + "!" + decoded.second);
}
if (!drvs.empty()) {
try { try {
/* For performance, prefetch all substitute info. */ /* For performance, prefetch all substitute info. */
PathSet willBuild, willSubstitute, unknown; PathSet willBuild, willSubstitute, unknown;
unsigned long long downloadSize, narSize; unsigned long long downloadSize, narSize;
queryMissing(*store, singleton<PathSet>(ctx), queryMissing(*store, drvs,
willBuild, willSubstitute, unknown, downloadSize, narSize); willBuild, willSubstitute, unknown, downloadSize, narSize);
/* !!! If using a substitute, we only need to fetch store->buildPaths(drvs);
the selected output of this derivation. */
store->buildPaths(singleton<PathSet>(ctx));
} catch (Error & e) { } catch (Error & e) {
throw ImportError(e.msg()); throw ImportError(e.msg());
} }
@ -88,17 +91,10 @@ static void prim_import(EvalState & state, const Pos & pos, Value * * args, Valu
mkApp(v, fun, w); mkApp(v, fun, w);
state.forceAttrs(v, pos); state.forceAttrs(v, pos);
} else { } else {
state.evalFile(path, v);
}
}
static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
PathSet context;
state.forceAttrs(*args[0]); state.forceAttrs(*args[0]);
Path path = resolveExprPath(state.coerceToPath(pos, *args[1], context)); if (args[0]->attrs->empty())
state.evalFile(path, v);
else {
Env * env = &state.allocEnv(args[0]->attrs->size()); Env * env = &state.allocEnv(args[0]->attrs->size());
env->up = &state.baseEnv; env->up = &state.baseEnv;
@ -111,9 +107,11 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
} }
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
Expr * e = state.parseExprFromFile(path, staticEnv); Expr * e = state.parseExprFromFile(resolveExprPath(path), staticEnv);
e->eval(state, *env, v); e->eval(state, *env, v);
}
}
} }
@ -1301,8 +1299,12 @@ void EvalState::createBaseEnv()
addConstant("__langVersion", v); addConstant("__langVersion", v);
// Miscellaneous // Miscellaneous
addPrimOp("import", 1, prim_import);
addPrimOp("scopedImport", 2, prim_scopedImport); 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("__typeOf", 1, prim_typeOf);
addPrimOp("isNull", 1, prim_isNull); addPrimOp("isNull", 1, prim_isNull);
addPrimOp("__isFunction", 1, prim_isFunction); addPrimOp("__isFunction", 1, prim_isFunction);
@ -1388,7 +1390,7 @@ void EvalState::createBaseEnv()
mkList(v, searchPath.size()); mkList(v, searchPath.size());
int n = 0; int n = 0;
for (auto & i : searchPath) { for (auto & i : searchPath) {
Value * v2 = v.list.elems[n++] = allocValue(); v2 = v.list.elems[n++] = allocValue();
mkAttrs(*v2, 2); mkAttrs(*v2, 2);
mkString(*allocAttr(*v2, symbols.create("path")), i.second); mkString(*allocAttr(*v2, symbols.create("path")), i.second);
mkString(*allocAttr(*v2, symbols.create("prefix")), i.first); mkString(*allocAttr(*v2, symbols.create("prefix")), i.first);