forked from lix-project/lix
Require flake.nix to be an attrset (not a non-trivial thunk)
This commit is contained in:
parent
c87840ae14
commit
f97d3753a1
|
@ -179,6 +179,18 @@ string showType(const Value & v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Value::isTrivial() const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
type != tApp
|
||||||
|
&& type != tPrimOpApp
|
||||||
|
&& (type != tThunk
|
||||||
|
|| (dynamic_cast<ExprAttrs *>(thunk.expr)
|
||||||
|
&& ((ExprAttrs *) thunk.expr)->dynamicAttrs.empty())
|
||||||
|
|| dynamic_cast<ExprLambda *>(thunk.expr));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
/* Called when the Boehm GC runs out of memory. */
|
/* Called when the Boehm GC runs out of memory. */
|
||||||
static void * oomHandler(size_t requested)
|
static void * oomHandler(size_t requested)
|
||||||
|
@ -749,7 +761,7 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EvalState::evalFile(const Path & path_, Value & v)
|
void EvalState::evalFile(const Path & path_, Value & v, bool mustBeTrivial)
|
||||||
{
|
{
|
||||||
auto path = checkSourcePath(path_);
|
auto path = checkSourcePath(path_);
|
||||||
|
|
||||||
|
@ -778,6 +790,11 @@ void EvalState::evalFile(const Path & path_, Value & v)
|
||||||
fileParseCache[path2] = e;
|
fileParseCache[path2] = e;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Enforce that 'flake.nix' is a direct attrset, not a
|
||||||
|
// computation.
|
||||||
|
if (mustBeTrivial &&
|
||||||
|
!(dynamic_cast<ExprAttrs *>(e)))
|
||||||
|
throw Error("file '%s' must be an attribute set", path);
|
||||||
eval(e, v);
|
eval(e, v);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
addErrorPrefix(e, "while evaluating the file '%1%':\n", path2);
|
addErrorPrefix(e, "while evaluating the file '%1%':\n", path2);
|
||||||
|
|
|
@ -157,8 +157,9 @@ public:
|
||||||
Expr * parseStdin();
|
Expr * parseStdin();
|
||||||
|
|
||||||
/* Evaluate an expression read from the given file to normal
|
/* Evaluate an expression read from the given file to normal
|
||||||
form. */
|
form. Optionally enforce that the top-level expression is
|
||||||
void evalFile(const Path & path, Value & v);
|
trivial (i.e. doesn't require arbitrary computation). */
|
||||||
|
void evalFile(const Path & path, Value & v, bool mustBeTrivial = false);
|
||||||
|
|
||||||
void resetFileCache();
|
void resetFileCache();
|
||||||
|
|
||||||
|
|
|
@ -198,9 +198,7 @@ static SourceInfo fetchFlake(EvalState & state, const FlakeRef & resolvedRef)
|
||||||
static void expectType(EvalState & state, ValueType type,
|
static void expectType(EvalState & state, ValueType type,
|
||||||
Value & value, const Pos & pos)
|
Value & value, const Pos & pos)
|
||||||
{
|
{
|
||||||
if (value.type == tThunk &&
|
if (value.type == tThunk && value.isTrivial())
|
||||||
((type == tAttrs && dynamic_cast<ExprAttrs *>(value.thunk.expr)) ||
|
|
||||||
(type == tLambda && dynamic_cast<ExprLambda *>(value.thunk.expr))))
|
|
||||||
state.forceValue(value, pos);
|
state.forceValue(value, pos);
|
||||||
if (value.type != type)
|
if (value.type != type)
|
||||||
throw Error("expected %s but got %s at %s",
|
throw Error("expected %s but got %s at %s",
|
||||||
|
@ -231,8 +229,7 @@ Flake getFlake(EvalState & state, const FlakeRef & flakeRef)
|
||||||
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", resolvedRef, resolvedRef.subdir);
|
throw Error("source tree referenced by '%s' does not contain a '%s/flake.nix' file", resolvedRef, resolvedRef.subdir);
|
||||||
|
|
||||||
Value vInfo;
|
Value vInfo;
|
||||||
// FIXME: don't evaluate vInfo.
|
state.evalFile(realFlakeFile, vInfo, true); // FIXME: symlink attack
|
||||||
state.evalFile(realFlakeFile, vInfo); // FIXME: symlink attack
|
|
||||||
|
|
||||||
expectType(state, tAttrs, vInfo, Pos(state.symbols.create(realFlakeFile), 0, 0));
|
expectType(state, tAttrs, vInfo, Pos(state.symbols.create(realFlakeFile), 0, 0));
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,11 @@ struct Value
|
||||||
{
|
{
|
||||||
return type == tList1 ? 1 : type == tList2 ? 2 : bigList.size;
|
return type == tList1 ? 1 : type == tList2 ? 2 : bigList.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether forcing this value requires a trivial amount of
|
||||||
|
computation. In particular, function applications are
|
||||||
|
non-trivial. */
|
||||||
|
bool isTrivial() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue