No global eval settings in libnixexpr

Progress on #5638

There is still a global eval settings, but it pushed down into
`libnixcmd`, which is a lot less bad a place for this sort of thing.
This commit is contained in:
John Ericson 2024-06-14 12:41:09 -04:00
parent cb0c868da4
commit 52bfccf8d8
24 changed files with 102 additions and 71 deletions

View file

@ -4,20 +4,20 @@
# Top-most EditorConfig file # Top-most EditorConfig file
root = true root = true
# Unix-style newlines with a newline ending every file, utf-8 charset # Unix-style newlines with a newline ending every file, UTF-8 charset
[*] [*]
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
charset = utf-8 charset = utf-8
# Match nix files, set indent to spaces with width of two # Match Nix files, set indent to spaces with width of two
[*.nix] [*.nix]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
# Match c++/shell/perl, set indent to spaces with width of four # Match C++/C/shell/Perl, set indent to spaces with width of four
[*.{hpp,cc,hh,sh,pl,xs}] [*.{hpp,cc,hh,c,h,sh,pl,xs}]
indent_style = space indent_style = space
indent_size = 4 indent_size = 4

View file

@ -126,13 +126,11 @@ ref<EvalState> EvalCommand::getEvalState()
{ {
if (!evalState) { if (!evalState) {
evalState = evalState =
std::allocate_shared<EvalState>(
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
std::allocate_shared<EvalState>(traceable_allocator<EvalState>(), traceable_allocator<EvalState>(),
lookupPath, getEvalStore(), getStore())
#else
std::make_shared<EvalState>(
lookupPath, getEvalStore(), getStore())
#endif #endif
lookupPath, getEvalStore(), evalSettings, getStore())
; ;
evalState->repair = repair; evalState->repair = repair;

View file

@ -1,6 +1,7 @@
#include "eval-settings.hh" #include "eval-settings.hh"
#include "common-eval-args.hh" #include "common-eval-args.hh"
#include "shared.hh" #include "shared.hh"
#include "config-global.hh"
#include "filetransfer.hh" #include "filetransfer.hh"
#include "eval.hh" #include "eval.hh"
#include "fetchers.hh" #include "fetchers.hh"
@ -13,6 +14,12 @@
namespace nix { namespace nix {
EvalSettings evalSettings {
settings.readOnlyMode
};
static GlobalConfig::Register rEvalSettings(&evalSettings);
MixEvalArgs::MixEvalArgs() MixEvalArgs::MixEvalArgs()
{ {
addFlag({ addFlag({

View file

@ -12,9 +12,15 @@ namespace nix {
class Store; class Store;
class EvalState; class EvalState;
struct EvalSettings;
class Bindings; class Bindings;
struct SourcePath; struct SourcePath;
/**
* @todo Get rid of global setttings variables
*/
extern EvalSettings evalSettings;
struct MixEvalArgs : virtual Args, virtual MixRepair struct MixEvalArgs : virtual Args, virtual MixRepair
{ {
static constexpr auto category = "Common evaluation options"; static constexpr auto category = "Common evaluation options";

View file

@ -7,6 +7,7 @@
#include "eval.hh" #include "eval.hh"
#include "globals.hh" #include "globals.hh"
#include "util.hh" #include "util.hh"
#include "eval-settings.hh"
#include "nix_api_expr.h" #include "nix_api_expr.h"
#include "nix_api_expr_internal.h" #include "nix_api_expr_internal.h"
@ -106,7 +107,21 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
for (size_t i = 0; lookupPath_c[i] != nullptr; i++) for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
lookupPath.push_back(lookupPath_c[i]); lookupPath.push_back(lookupPath_c[i]);
return new EvalState{nix::EvalState(nix::LookupPath::parse(lookupPath), store->ptr)}; void * p = ::operator new(
sizeof(EvalState),
static_cast<std::align_val_t>(alignof(EvalState)));
auto * p2 = static_cast<EvalState *>(p);
new (p) EvalState {
.settings = nix::EvalSettings{
nix::settings.readOnlyMode,
},
.state = nix::EvalState(
nix::LookupPath::parse(lookupPath),
store->ptr,
p2->settings),
};
loadConfFile(p2->settings);
return p2;
} }
NIXC_CATCH_ERRS_NULL NIXC_CATCH_ERRS_NULL
} }

View file

@ -2,11 +2,13 @@
#define NIX_API_EXPR_INTERNAL_H #define NIX_API_EXPR_INTERNAL_H
#include "eval.hh" #include "eval.hh"
#include "eval-settings.hh"
#include "attr-set.hh" #include "attr-set.hh"
#include "nix_api_value.h" #include "nix_api_value.h"
struct EvalState struct EvalState
{ {
nix::EvalSettings settings;
nix::EvalState state; nix::EvalState state;
}; };

View file

@ -45,7 +45,8 @@ static Strings parseNixPath(const std::string & s)
return res; return res;
} }
EvalSettings::EvalSettings() EvalSettings::EvalSettings(bool & readOnlyMode)
: readOnlyMode{readOnlyMode}
{ {
auto var = getEnv("NIX_PATH"); auto var = getEnv("NIX_PATH");
if (var) nixPath = parseNixPath(*var); if (var) nixPath = parseNixPath(*var);
@ -55,7 +56,7 @@ EvalSettings::EvalSettings()
builtinsAbortOnWarn = true; builtinsAbortOnWarn = true;
} }
Strings EvalSettings::getDefaultNixPath() Strings EvalSettings::getDefaultNixPath() const
{ {
Strings res; Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) { auto add = [&](const Path & p, const std::string & s = std::string()) {
@ -68,7 +69,7 @@ Strings EvalSettings::getDefaultNixPath()
} }
}; };
if (!evalSettings.restrictEval && !evalSettings.pureEval) { if (!restrictEval && !pureEval) {
add(getNixDefExpr() + "/channels"); add(getNixDefExpr() + "/channels");
add(rootChannelsDir() + "/nixpkgs", "nixpkgs"); add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
add(rootChannelsDir()); add(rootChannelsDir());
@ -94,16 +95,12 @@ std::string EvalSettings::resolvePseudoUrl(std::string_view url)
return std::string(url); return std::string(url);
} }
const std::string & EvalSettings::getCurrentSystem() const std::string & EvalSettings::getCurrentSystem() const
{ {
const auto & evalSystem = currentSystem.get(); const auto & evalSystem = currentSystem.get();
return evalSystem != "" ? evalSystem : settings.thisSystem.get(); return evalSystem != "" ? evalSystem : settings.thisSystem.get();
} }
EvalSettings evalSettings;
static GlobalConfig::Register rEvalSettings(&evalSettings);
Path getNixDefExpr() Path getNixDefExpr()
{ {
return settings.useXDGBaseDirectories return settings.useXDGBaseDirectories

View file

@ -7,9 +7,11 @@ namespace nix {
struct EvalSettings : Config struct EvalSettings : Config
{ {
EvalSettings(); EvalSettings(bool & readOnlyMode);
static Strings getDefaultNixPath(); bool & readOnlyMode;
Strings getDefaultNixPath() const;
static bool isPseudoUrl(std::string_view s); static bool isPseudoUrl(std::string_view s);
@ -74,7 +76,7 @@ struct EvalSettings : Config
* Implements the `eval-system` vs `system` defaulting logic * Implements the `eval-system` vs `system` defaulting logic
* described for `eval-system`. * described for `eval-system`.
*/ */
const std::string & getCurrentSystem(); const std::string & getCurrentSystem() const;
Setting<bool> restrictEval{ Setting<bool> restrictEval{
this, false, "restrict-eval", this, false, "restrict-eval",
@ -193,8 +195,6 @@ struct EvalSettings : Config
)"}; )"};
}; };
extern EvalSettings evalSettings;
/** /**
* Conventionally part of the default nix path in impure mode. * Conventionally part of the default nix path in impure mode.
*/ */

View file

@ -9,7 +9,6 @@
#include "store-api.hh" #include "store-api.hh"
#include "derivations.hh" #include "derivations.hh"
#include "downstream-placeholder.hh" #include "downstream-placeholder.hh"
#include "globals.hh"
#include "eval-inline.hh" #include "eval-inline.hh"
#include "filetransfer.hh" #include "filetransfer.hh"
#include "function-trace.hh" #include "function-trace.hh"
@ -219,8 +218,10 @@ static constexpr size_t BASE_ENV_SIZE = 128;
EvalState::EvalState( EvalState::EvalState(
const LookupPath & _lookupPath, const LookupPath & _lookupPath,
ref<Store> store, ref<Store> store,
const EvalSettings & settings,
std::shared_ptr<Store> buildStore) std::shared_ptr<Store> buildStore)
: sWith(symbols.create("<with>")) : settings{settings}
, sWith(symbols.create("<with>"))
, sOutPath(symbols.create("outPath")) , sOutPath(symbols.create("outPath"))
, sDrvPath(symbols.create("drvPath")) , sDrvPath(symbols.create("drvPath"))
, sType(symbols.create("type")) , sType(symbols.create("type"))
@ -276,10 +277,10 @@ EvalState::EvalState(
, repair(NoRepair) , repair(NoRepair)
, emptyBindings(0) , emptyBindings(0)
, rootFS( , rootFS(
evalSettings.restrictEval || evalSettings.pureEval settings.restrictEval || settings.pureEval
? ref<SourceAccessor>(AllowListSourceAccessor::create(getFSSourceAccessor(), {}, ? ref<SourceAccessor>(AllowListSourceAccessor::create(getFSSourceAccessor(), {},
[](const CanonPath & path) -> RestrictedPathError { [&settings](const CanonPath & path) -> RestrictedPathError {
auto modeInformation = evalSettings.pureEval auto modeInformation = settings.pureEval
? "in pure evaluation mode (use '--impure' to override)" ? "in pure evaluation mode (use '--impure' to override)"
: "in restricted mode"; : "in restricted mode";
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation); throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
@ -330,10 +331,10 @@ EvalState::EvalState(
vStringUnknown.mkString("unknown"); vStringUnknown.mkString("unknown");
/* Initialise the Nix expression search path. */ /* Initialise the Nix expression search path. */
if (!evalSettings.pureEval) { if (!settings.pureEval) {
for (auto & i : _lookupPath.elements) for (auto & i : _lookupPath.elements)
lookupPath.elements.emplace_back(LookupPath::Elem {i}); lookupPath.elements.emplace_back(LookupPath::Elem {i});
for (auto & i : evalSettings.nixPath.get()) for (auto & i : settings.nixPath.get())
lookupPath.elements.emplace_back(LookupPath::Elem::parse(i)); lookupPath.elements.emplace_back(LookupPath::Elem::parse(i));
} }
@ -411,9 +412,9 @@ bool isAllowedURI(std::string_view uri, const Strings & allowedUris)
void EvalState::checkURI(const std::string & uri) void EvalState::checkURI(const std::string & uri)
{ {
if (!evalSettings.restrictEval) return; if (!settings.restrictEval) return;
if (isAllowedURI(uri, evalSettings.allowedUris.get())) return; if (isAllowedURI(uri, settings.allowedUris.get())) return;
/* If the URI is a path, then check it against allowedPaths as /* If the URI is a path, then check it against allowedPaths as
well. */ well. */
@ -458,7 +459,7 @@ void EvalState::addConstant(const std::string & name, Value * v, Constant info)
constantInfos.push_back({name2, info}); constantInfos.push_back({name2, info});
if (!(evalSettings.pureEval && info.impureOnly)) { if (!(settings.pureEval && info.impureOnly)) {
/* Check the type, if possible. /* Check the type, if possible.
We might know the type of a thunk in advance, so be allowed We might know the type of a thunk in advance, so be allowed
@ -1413,11 +1414,11 @@ public:
void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos) void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos)
{ {
if (callDepth > evalSettings.maxCallDepth) if (callDepth > settings.maxCallDepth)
error<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow(); error<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
CallDepth _level(callDepth); CallDepth _level(callDepth);
auto trace = evalSettings.traceFunctionCalls auto trace = settings.traceFunctionCalls
? std::make_unique<FunctionCallTrace>(positions[pos]) ? std::make_unique<FunctionCallTrace>(positions[pos])
: nullptr; : nullptr;
@ -2745,7 +2746,7 @@ SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_
return {corepkgsFS, CanonPath(path.substr(3))}; return {corepkgsFS, CanonPath(path.substr(3))};
error<ThrownError>( error<ThrownError>(
evalSettings.pureEval settings.pureEval
? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)" ? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
: "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)", : "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
path path
@ -2825,7 +2826,7 @@ Expr * EvalState::parse(
const SourcePath & basePath, const SourcePath & basePath,
std::shared_ptr<StaticEnv> & staticEnv) std::shared_ptr<StaticEnv> & staticEnv)
{ {
auto result = parseExprFromBuf(text, length, origin, basePath, symbols, positions, rootFS, exprSymbols); auto result = parseExprFromBuf(text, length, origin, basePath, symbols, settings, positions, rootFS, exprSymbols);
result->bindVars(*this, staticEnv); result->bindVars(*this, staticEnv);

View file

@ -30,6 +30,7 @@ namespace nix {
constexpr size_t maxPrimOpArity = 8; constexpr size_t maxPrimOpArity = 8;
class Store; class Store;
struct EvalSettings;
class EvalState; class EvalState;
class StorePath; class StorePath;
struct SingleDerivedPath; struct SingleDerivedPath;
@ -39,7 +40,6 @@ namespace eval_cache {
class EvalCache; class EvalCache;
} }
/** /**
* Function that implements a primop. * Function that implements a primop.
*/ */
@ -162,6 +162,7 @@ struct DebugTrace {
class EvalState : public std::enable_shared_from_this<EvalState> class EvalState : public std::enable_shared_from_this<EvalState>
{ {
public: public:
const EvalSettings & settings;
SymbolTable symbols; SymbolTable symbols;
PosTable positions; PosTable positions;
@ -352,6 +353,7 @@ public:
EvalState( EvalState(
const LookupPath & _lookupPath, const LookupPath & _lookupPath,
ref<Store> store, ref<Store> store,
const EvalSettings & settings,
std::shared_ptr<Store> buildStore = nullptr); std::shared_ptr<Store> buildStore = nullptr);
~EvalState(); ~EvalState();

View file

@ -1,6 +1,5 @@
#include "users.hh" #include "users.hh"
#include "config-global.hh" #include "config-global.hh"
#include "globals.hh"
#include "fetch-settings.hh" #include "fetch-settings.hh"
#include "flake.hh" #include "flake.hh"

View file

@ -803,7 +803,7 @@ static void prim_getFlake(EvalState & state, const PosIdx pos, Value * * args, V
{ {
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake")); std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
auto flakeRef = parseFlakeRef(flakeRefS, {}, true); auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
if (evalSettings.pureEval && !flakeRef.input.isLocked()) if (state.settings.pureEval && !flakeRef.input.isLocked())
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]); throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]);
callFlake(state, callFlake(state,
@ -811,8 +811,8 @@ static void prim_getFlake(EvalState & state, const PosIdx pos, Value * * args, V
LockFlags { LockFlags {
.updateLockFile = false, .updateLockFile = false,
.writeLockFile = false, .writeLockFile = false,
.useRegistries = !evalSettings.pureEval && fetchSettings.useRegistries, .useRegistries = !state.settings.pureEval && fetchSettings.useRegistries,
.allowUnlocked = !evalSettings.pureEval, .allowUnlocked = !state.settings.pureEval,
}), }),
v); v);
} }

View file

@ -46,6 +46,7 @@ struct ParserState
PosTable::Origin origin; PosTable::Origin origin;
const ref<SourceAccessor> rootFS; const ref<SourceAccessor> rootFS;
const Expr::AstSymbols & s; const Expr::AstSymbols & s;
const EvalSettings & settings;
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos); void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos); void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);

View file

@ -25,7 +25,6 @@
#include "nixexpr.hh" #include "nixexpr.hh"
#include "eval.hh" #include "eval.hh"
#include "eval-settings.hh" #include "eval-settings.hh"
#include "globals.hh"
#include "parser-state.hh" #include "parser-state.hh"
#define YYLTYPE ::nix::ParserLocation #define YYLTYPE ::nix::ParserLocation
@ -40,6 +39,7 @@ Expr * parseExprFromBuf(
Pos::Origin origin, Pos::Origin origin,
const SourcePath & basePath, const SourcePath & basePath,
SymbolTable & symbols, SymbolTable & symbols,
const EvalSettings & settings,
PosTable & positions, PosTable & positions,
const ref<SourceAccessor> rootFS, const ref<SourceAccessor> rootFS,
const Expr::AstSymbols & astSymbols); const Expr::AstSymbols & astSymbols);
@ -294,7 +294,7 @@ path_start
$$ = new ExprPath(ref<SourceAccessor>(state->rootFS), std::move(path)); $$ = new ExprPath(ref<SourceAccessor>(state->rootFS), std::move(path));
} }
| HPATH { | HPATH {
if (evalSettings.pureEval) { if (state->settings.pureEval) {
throw Error( throw Error(
"the path '%s' can not be resolved in pure mode", "the path '%s' can not be resolved in pure mode",
std::string_view($1.p, $1.l) std::string_view($1.p, $1.l)
@ -429,6 +429,7 @@ Expr * parseExprFromBuf(
Pos::Origin origin, Pos::Origin origin,
const SourcePath & basePath, const SourcePath & basePath,
SymbolTable & symbols, SymbolTable & symbols,
const EvalSettings & settings,
PosTable & positions, PosTable & positions,
const ref<SourceAccessor> rootFS, const ref<SourceAccessor> rootFS,
const Expr::AstSymbols & astSymbols) const Expr::AstSymbols & astSymbols)
@ -441,6 +442,7 @@ Expr * parseExprFromBuf(
.origin = positions.addOrigin(origin, length), .origin = positions.addOrigin(origin, length),
.rootFS = rootFS, .rootFS = rootFS,
.s = astSymbols, .s = astSymbols,
.settings = settings,
}; };
yylex_init(&scanner); yylex_init(&scanner);

View file

@ -5,7 +5,6 @@
#include "eval.hh" #include "eval.hh"
#include "eval-settings.hh" #include "eval-settings.hh"
#include "gc-small-vector.hh" #include "gc-small-vector.hh"
#include "globals.hh"
#include "json-to-value.hh" #include "json-to-value.hh"
#include "names.hh" #include "names.hh"
#include "path-references.hh" #include "path-references.hh"
@ -78,7 +77,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
if (drvs.empty()) return {}; if (drvs.empty()) return {};
if (isIFD && !evalSettings.enableImportFromDerivation) if (isIFD && !settings.enableImportFromDerivation)
error<EvalError>( error<EvalError>(
"cannot build '%1%' during evaluation because the option 'allow-import-from-derivation' is disabled", "cannot build '%1%' during evaluation because the option 'allow-import-from-derivation' is disabled",
drvs.begin()->to_string(*store) drvs.begin()->to_string(*store)
@ -901,7 +900,7 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
MaintainCount trylevel(state.trylevel); MaintainCount trylevel(state.trylevel);
ReplExitStatus (* savedDebugRepl)(ref<EvalState> es, const ValMap & extraEnv) = nullptr; ReplExitStatus (* savedDebugRepl)(ref<EvalState> es, const ValMap & extraEnv) = nullptr;
if (state.debugRepl && evalSettings.ignoreExceptionsDuringTry) if (state.debugRepl && state.settings.ignoreExceptionsDuringTry)
{ {
/* to prevent starting the repl from exceptions withing a tryEval, null it. */ /* to prevent starting the repl from exceptions withing a tryEval, null it. */
savedDebugRepl = state.debugRepl; savedDebugRepl = state.debugRepl;
@ -950,7 +949,7 @@ static RegisterPrimOp primop_tryEval({
static void prim_getEnv(EvalState & state, const PosIdx pos, Value * * args, Value & v) static void prim_getEnv(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{ {
std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getEnv")); std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getEnv"));
v.mkString(evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or("")); v.mkString(state.settings.restrictEval || state.settings.pureEval ? "" : getEnv(name).value_or(""));
} }
static RegisterPrimOp primop_getEnv({ static RegisterPrimOp primop_getEnv({
@ -1017,7 +1016,7 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
printError("trace: %1%", args[0]->string_view()); printError("trace: %1%", args[0]->string_view());
else else
printError("trace: %1%", ValuePrinter(state, *args[0])); printError("trace: %1%", ValuePrinter(state, *args[0]));
if (evalSettings.builtinsTraceDebugger) { if (state.settings.builtinsTraceDebugger) {
state.runDebugRepl(nullptr); state.runDebugRepl(nullptr);
} }
state.forceValue(*args[1], pos); state.forceValue(*args[1], pos);
@ -1056,11 +1055,11 @@ static void prim_warn(EvalState & state, const PosIdx pos, Value * * args, Value
logWarning(info); logWarning(info);
} }
if (evalSettings.builtinsAbortOnWarn) { if (state.settings.builtinsAbortOnWarn) {
// Not an EvalError or subclass, which would cause the error to be stored in the eval cache. // Not an EvalError or subclass, which would cause the error to be stored in the eval cache.
state.error<EvalBaseError>("aborting to reveal stack trace of warning, as abort-on-warn is set").setIsFromExpr().debugThrow(); state.error<EvalBaseError>("aborting to reveal stack trace of warning, as abort-on-warn is set").setIsFromExpr().debugThrow();
} }
if (evalSettings.builtinsTraceDebugger || evalSettings.builtinsDebuggerOnWarn) { if (state.settings.builtinsTraceDebugger || state.settings.builtinsDebuggerOnWarn) {
state.runDebugRepl(nullptr); state.runDebugRepl(nullptr);
} }
state.forceValue(*args[1], pos); state.forceValue(*args[1], pos);
@ -1578,7 +1577,7 @@ static RegisterPrimOp primop_toPath({
corner cases. */ corner cases. */
static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args, Value & v) static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{ {
if (evalSettings.pureEval) if (state.settings.pureEval)
state.error<EvalError>( state.error<EvalError>(
"'%s' is not allowed in pure evaluation mode", "'%s' is not allowed in pure evaluation mode",
"builtins.storePath" "builtins.storePath"
@ -4562,7 +4561,7 @@ void EvalState::createBaseEnv()
)", )",
}); });
if (!evalSettings.pureEval) { if (!settings.pureEval) {
v.mkInt(time(0)); v.mkInt(time(0));
} }
addConstant("__currentTime", v, { addConstant("__currentTime", v, {
@ -4589,8 +4588,8 @@ void EvalState::createBaseEnv()
.impureOnly = true, .impureOnly = true,
}); });
if (!evalSettings.pureEval) if (!settings.pureEval)
v.mkString(evalSettings.getCurrentSystem()); v.mkString(settings.getCurrentSystem());
addConstant("__currentSystem", v, { addConstant("__currentSystem", v, {
.type = nString, .type = nString,
.doc = R"( .doc = R"(
@ -4670,7 +4669,7 @@ void EvalState::createBaseEnv()
#ifndef _WIN32 // TODO implement on Windows #ifndef _WIN32 // TODO implement on Windows
// Miscellaneous // Miscellaneous
if (evalSettings.enableNativeCode) { if (settings.enableNativeCode) {
addPrimOp({ addPrimOp({
.name = "__importNative", .name = "__importNative",
.arity = 2, .arity = 2,
@ -4693,7 +4692,7 @@ void EvalState::createBaseEnv()
error if `--trace-verbose` is enabled. Then return *e2*. This function error if `--trace-verbose` is enabled. Then return *e2*. This function
is useful for debugging. is useful for debugging.
)", )",
.fun = evalSettings.traceVerbose ? prim_trace : prim_second, .fun = settings.traceVerbose ? prim_trace : prim_second,
}); });
/* Add a value containing the current Nix expression search path. */ /* Add a value containing the current Nix expression search path. */

View file

@ -53,7 +53,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
// whitelist. Ah well. // whitelist. Ah well.
state.checkURI(url); state.checkURI(url);
if (evalSettings.pureEval && !rev) if (state.settings.pureEval && !rev)
throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision"); throw Error("in pure evaluation mode, 'fetchMercurial' requires a Mercurial revision");
fetchers::Attrs attrs; fetchers::Attrs attrs;

View file

@ -171,10 +171,10 @@ static void fetchTree(
} }
} }
if (!evalSettings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes)) if (!state.settings.pureEval && !input.isDirect() && experimentalFeatureSettings.isEnabled(Xp::Flakes))
input = lookupInRegistries(state.store, input).first; input = lookupInRegistries(state.store, input).first;
if (evalSettings.pureEval && !input.isLocked()) { if (state.settings.pureEval && !input.isLocked()) {
auto fetcher = "fetchTree"; auto fetcher = "fetchTree";
if (params.isFetchGit) if (params.isFetchGit)
fetcher = "fetchGit"; fetcher = "fetchGit";
@ -453,14 +453,14 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
url = state.forceStringNoCtx(*args[0], pos, "while evaluating the url we should fetch"); url = state.forceStringNoCtx(*args[0], pos, "while evaluating the url we should fetch");
if (who == "fetchTarball") if (who == "fetchTarball")
url = evalSettings.resolvePseudoUrl(*url); url = state.settings.resolvePseudoUrl(*url);
state.checkURI(*url); state.checkURI(*url);
if (name == "") if (name == "")
name = baseNameOf(*url); name = baseNameOf(*url);
if (evalSettings.pureEval && !expectedHash) if (state.settings.pureEval && !expectedHash)
state.error<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow(); state.error<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow();
// early exit if pinned and already in the store // early exit if pinned and already in the store

View file

@ -259,7 +259,7 @@ static void main_nix_build(int argc, char * * argv)
auto store = openStore(); auto store = openStore();
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store; auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, store); auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, evalSettings, store);
state->repair = myArgs.repair; state->repair = myArgs.repair;
if (myArgs.repair) buildMode = bmRepair; if (myArgs.repair) buildMode = bmRepair;

View file

@ -1525,7 +1525,7 @@ static int main_nix_env(int argc, char * * argv)
auto store = openStore(); auto store = openStore();
globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.lookupPath, store)); globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.lookupPath, store, evalSettings));
globals.state->repair = myArgs.repair; globals.state->repair = myArgs.repair;
globals.instSource.nixExprPath = std::make_shared<SourcePath>( globals.instSource.nixExprPath = std::make_shared<SourcePath>(

View file

@ -157,7 +157,7 @@ static int main_nix_instantiate(int argc, char * * argv)
auto store = openStore(); auto store = openStore();
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store; auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, store); auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, evalSettings, store);
state->repair = myArgs.repair; state->repair = myArgs.repair;
Bindings & autoArgs = *myArgs.getAutoArgs(*state); Bindings & autoArgs = *myArgs.getAutoArgs(*state);

View file

@ -242,7 +242,7 @@ static void showHelp(std::vector<std::string> subcommand, NixArgs & toplevel)
evalSettings.restrictEval = false; evalSettings.restrictEval = false;
evalSettings.pureEval = false; evalSettings.pureEval = false;
EvalState state({}, openStore("dummy://")); EvalState state({}, openStore("dummy://"), evalSettings);
auto vGenerateManpage = state.allocValue(); auto vGenerateManpage = state.allocValue();
state.eval(state.parseExprFromString( state.eval(state.parseExprFromString(
@ -418,7 +418,7 @@ void mainWrapped(int argc, char * * argv)
Xp::FetchTree, Xp::FetchTree,
}; };
evalSettings.pureEval = false; evalSettings.pureEval = false;
EvalState state({}, openStore("dummy://")); EvalState state({}, openStore("dummy://"), evalSettings);
auto res = nlohmann::json::object(); auto res = nlohmann::json::object();
res["builtins"] = ({ res["builtins"] = ({
auto builtinsJson = nlohmann::json::object(); auto builtinsJson = nlohmann::json::object();

View file

@ -193,7 +193,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
startProgressBar(); startProgressBar();
auto store = openStore(); auto store = openStore();
auto state = std::make_unique<EvalState>(myArgs.lookupPath, store); auto state = std::make_unique<EvalState>(myArgs.lookupPath, store, evalSettings);
Bindings & autoArgs = *myArgs.getAutoArgs(*state); Bindings & autoArgs = *myArgs.getAutoArgs(*state);

View file

@ -147,7 +147,7 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
auto req = FileTransferRequest((std::string&) settings.upgradeNixStorePathUrl); auto req = FileTransferRequest((std::string&) settings.upgradeNixStorePathUrl);
auto res = getFileTransfer()->download(req); auto res = getFileTransfer()->download(req);
auto state = std::make_unique<EvalState>(LookupPath{}, store); auto state = std::make_unique<EvalState>(LookupPath{}, store, evalSettings);
auto v = state->allocValue(); auto v = state->allocValue();
state->eval(state->parseExprFromString(res.data, state->rootPath(CanonPath("/no-such-path"))), *v); state->eval(state->parseExprFromString(res.data, state->rootPath(CanonPath("/no-such-path"))), *v);
Bindings & bindings(*state->allocBindings(0)); Bindings & bindings(*state->allocBindings(0));

View file

@ -19,14 +19,14 @@ namespace nix {
static void SetUpTestSuite() { static void SetUpTestSuite() {
LibStoreTest::SetUpTestSuite(); LibStoreTest::SetUpTestSuite();
initGC(); initGC();
evalSettings.nixPath = {};
} }
protected: protected:
LibExprTest() LibExprTest()
: LibStoreTest() : LibStoreTest()
, state({}, store) , state({}, store, evalSettings, nullptr)
{ {
evalSettings.nixPath = {};
} }
Value eval(std::string input, bool forceValue = true) { Value eval(std::string input, bool forceValue = true) {
Value v; Value v;
@ -42,6 +42,8 @@ namespace nix {
return state.symbols.create(value); return state.symbols.create(value);
} }
bool readOnlyMode = true;
EvalSettings evalSettings{readOnlyMode};
EvalState state; EvalState state;
}; };