Skip to content

Commit

Permalink
No global eval settings in libnixexpr
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Ericson2314 committed Jun 14, 2024
1 parent 2f5fdab commit fab536d
Show file tree
Hide file tree
Showing 27 changed files with 108 additions and 86 deletions.
8 changes: 3 additions & 5 deletions src/libcmd/command.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,11 @@ ref<EvalState> EvalCommand::getEvalState()
{
if (!evalState) {
evalState =
std::allocate_shared<EvalState>(
#if HAVE_BOEHMGC
std::allocate_shared<EvalState>(traceable_allocator<EvalState>(),
lookupPath, getEvalStore(), getStore())
#else
std::make_shared<EvalState>(
lookupPath, getEvalStore(), getStore())
traceable_allocator<EvalState>(),
#endif
lookupPath, getEvalStore(), globalEvalSettings, getStore())
;

evalState->repair = repair;
Expand Down
8 changes: 7 additions & 1 deletion src/libcmd/common-eval-args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@

namespace nix {

EvalSettings globalEvalSettings {
settings.readOnlyMode
};

static GlobalConfig::Register rEvalSettings(&globalEvalSettings);

MixEvalArgs::MixEvalArgs()
{
addFlag({
Expand Down Expand Up @@ -134,7 +140,7 @@ MixEvalArgs::MixEvalArgs()
.description = "Allow access to mutable paths and repositories.",
.category = category,
.handler = {[&]() {
evalSettings.pureEval = false;
globalEvalSettings.pureEval = false;
}},
});

Expand Down
6 changes: 6 additions & 0 deletions src/libcmd/common-eval-args.hh
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ namespace nix {

class Store;
class EvalState;
struct EvalSettings;
class Bindings;
struct SourcePath;

/**
* @todo Get rid of global setttings variables
*/
extern EvalSettings globalEvalSettings;

struct MixEvalArgs : virtual Args, virtual MixRepair
{
static constexpr auto category = "Common evaluation options";
Expand Down
6 changes: 3 additions & 3 deletions src/libcmd/installables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s
if (file) {
completions.setType(AddCompletions::Type::Attrs);

evalSettings.pureEval = false;
globalEvalSettings.pureEval = false;
auto state = getEvalState();
auto e =
state->parseExprFromFile(
Expand Down Expand Up @@ -442,7 +442,7 @@ ref<eval_cache::EvalCache> openEvalCache(
EvalState & state,
std::shared_ptr<flake::LockedFlake> lockedFlake)
{
auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval
auto fingerprint = globalEvalSettings.useEvalCache && globalEvalSettings.pureEval
? lockedFlake->getFingerprint(state.store)
: std::nullopt;
auto rootLoader = [&state, lockedFlake]()
Expand Down Expand Up @@ -484,7 +484,7 @@ Installables SourceExprCommand::parseInstallables(
throw UsageError("'--file' and '--expr' are exclusive");

// FIXME: backward compatibility hack
if (file) evalSettings.pureEval = false;
if (file) globalEvalSettings.pureEval = false;

auto state = getEvalState();
auto vFile = state->allocValue();
Expand Down
6 changes: 3 additions & 3 deletions src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");

auto flakeRef = parseFlakeRef(flakeRefS, absPath("."), true);
if (evalSettings.pureEval && !flakeRef.input.isLocked())
if (globalEvalSettings.pureEval && !flakeRef.input.isLocked())
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);

Value v;
Expand All @@ -699,8 +699,8 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
flake::lockFlake(*state, flakeRef,
flake::LockFlags {
.updateLockFile = false,
.useRegistries = !evalSettings.pureEval,
.allowUnlocked = !evalSettings.pureEval,
.useRegistries = !globalEvalSettings.pureEval,
.allowUnlocked = !globalEvalSettings.pureEval,
}),
v);
addAttrsToScope(v);
Expand Down
11 changes: 10 additions & 1 deletion src/libexpr-c/nix_api_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "eval.hh"
#include "globals.hh"
#include "util.hh"
#include "eval-settings.hh"

#include "nix_api_expr.h"
#include "nix_api_expr_internal.h"
Expand Down Expand Up @@ -106,7 +107,15 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
lookupPath.push_back(lookupPath_c[i]);

return new EvalState{nix::EvalState(nix::LookupPath::parse(lookupPath), store->ptr)};
// FIXME leak
auto * evalSettings = new nix::EvalSettings{nix::settings.readOnlyMode};

return new EvalState{
nix::EvalState(
nix::LookupPath::parse(lookupPath),
store->ptr,
*evalSettings)
};
}
NIXC_CATCH_ERRS_NULL
}
Expand Down
13 changes: 5 additions & 8 deletions src/libexpr/eval-settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ static Strings parseNixPath(const std::string & s)
return res;
}

EvalSettings::EvalSettings()
EvalSettings::EvalSettings(bool & readOnlyMode)
: readOnlyMode{readOnlyMode}
{
auto var = getEnv("NIX_PATH");
if (var) nixPath = parseNixPath(*var);
Expand All @@ -54,7 +55,7 @@ EvalSettings::EvalSettings()
builtinsAbortOnWarn = true;
}

Strings EvalSettings::getDefaultNixPath()
Strings EvalSettings::getDefaultNixPath() const
{
Strings res;
auto add = [&](const Path & p, const std::string & s = std::string()) {
Expand All @@ -67,7 +68,7 @@ Strings EvalSettings::getDefaultNixPath()
}
};

if (!evalSettings.restrictEval && !evalSettings.pureEval) {
if (!restrictEval && !pureEval) {
add(getNixDefExpr() + "/channels");
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
add(rootChannelsDir());
Expand All @@ -93,16 +94,12 @@ std::string EvalSettings::resolvePseudoUrl(std::string_view url)
return std::string(url);
}

const std::string & EvalSettings::getCurrentSystem()
const std::string & EvalSettings::getCurrentSystem() const
{
const auto & evalSystem = currentSystem.get();
return evalSystem != "" ? evalSystem : settings.thisSystem.get();
}

EvalSettings evalSettings;

static GlobalConfig::Register rEvalSettings(&evalSettings);

Path getNixDefExpr()
{
return settings.useXDGBaseDirectories
Expand Down
10 changes: 5 additions & 5 deletions src/libexpr/eval-settings.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ namespace nix {

struct EvalSettings : Config
{
EvalSettings();
EvalSettings(bool & readOnlyMode);

static Strings getDefaultNixPath();
bool & readOnlyMode;

Strings getDefaultNixPath() const;

static bool isPseudoUrl(std::string_view s);

Expand Down Expand Up @@ -74,7 +76,7 @@ struct EvalSettings : Config
* Implements the `eval-system` vs `system` defaulting logic
* described for `eval-system`.
*/
const std::string & getCurrentSystem();
const std::string & getCurrentSystem() const;

Setting<bool> restrictEval{
this, false, "restrict-eval",
Expand Down Expand Up @@ -193,8 +195,6 @@ struct EvalSettings : Config
)"};
};

extern EvalSettings evalSettings;

/**
* Conventionally part of the default nix path in impure mode.
*/
Expand Down
29 changes: 15 additions & 14 deletions src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "store-api.hh"
#include "derivations.hh"
#include "downstream-placeholder.hh"
#include "globals.hh"
#include "eval-inline.hh"
#include "filetransfer.hh"
#include "function-trace.hh"
Expand Down Expand Up @@ -219,8 +218,10 @@ static constexpr size_t BASE_ENV_SIZE = 128;
EvalState::EvalState(
const LookupPath & _lookupPath,
ref<Store> store,
const EvalSettings & settings,
std::shared_ptr<Store> buildStore)
: sWith(symbols.create("<with>"))
: settings{settings}
, sWith(symbols.create("<with>"))
, sOutPath(symbols.create("outPath"))
, sDrvPath(symbols.create("drvPath"))
, sType(symbols.create("type"))
Expand Down Expand Up @@ -270,10 +271,10 @@ EvalState::EvalState(
, repair(NoRepair)
, emptyBindings(0)
, rootFS(
evalSettings.restrictEval || evalSettings.pureEval
settings.restrictEval || settings.pureEval
? ref<SourceAccessor>(AllowListSourceAccessor::create(getFSSourceAccessor(), {},
[](const CanonPath & path) -> RestrictedPathError {
auto modeInformation = evalSettings.pureEval
[&settings](const CanonPath & path) -> RestrictedPathError {
auto modeInformation = settings.pureEval
? "in pure evaluation mode (use '--impure' to override)"
: "in restricted mode";
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
Expand Down Expand Up @@ -324,10 +325,10 @@ EvalState::EvalState(
vStringUnknown.mkString("unknown");

/* Initialise the Nix expression search path. */
if (!evalSettings.pureEval) {
if (!settings.pureEval) {
for (auto & i : _lookupPath.elements)
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));
}

Expand Down Expand Up @@ -405,9 +406,9 @@ bool isAllowedURI(std::string_view uri, const Strings & allowedUris)

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
well. */
Expand Down Expand Up @@ -452,7 +453,7 @@ void EvalState::addConstant(const std::string & name, Value * v, Constant info)

constantInfos.push_back({name2, info});

if (!(evalSettings.pureEval && info.impureOnly)) {
if (!(settings.pureEval && info.impureOnly)) {
/* Check the type, if possible.
We might know the type of a thunk in advance, so be allowed
Expand Down Expand Up @@ -1407,11 +1408,11 @@ class CallDepth {

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();
CallDepth _level(callDepth);

auto trace = evalSettings.traceFunctionCalls
auto trace = settings.traceFunctionCalls
? std::make_unique<FunctionCallTrace>(positions[pos])
: nullptr;

Expand Down Expand Up @@ -2739,7 +2740,7 @@ SourcePath EvalState::findFile(const LookupPath & lookupPath, const std::string_
return {corepkgsFS, CanonPath(path.substr(3))};

error<ThrownError>(
evalSettings.pureEval
settings.pureEval
? "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)",
path
Expand Down Expand Up @@ -2819,7 +2820,7 @@ Expr * EvalState::parse(
const SourcePath & basePath,
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);

Expand Down
4 changes: 3 additions & 1 deletion src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace nix {
constexpr size_t maxPrimOpArity = 8;

class Store;
struct EvalSettings;
class EvalState;
class StorePath;
struct SingleDerivedPath;
Expand All @@ -39,7 +40,6 @@ namespace eval_cache {
class EvalCache;
}


/**
* Function that implements a primop.
*/
Expand Down Expand Up @@ -162,6 +162,7 @@ struct DebugTrace {
class EvalState : public std::enable_shared_from_this<EvalState>
{
public:
const EvalSettings & settings;
SymbolTable symbols;
PosTable positions;

Expand Down Expand Up @@ -349,6 +350,7 @@ public:
EvalState(
const LookupPath & _lookupPath,
ref<Store> store,
const EvalSettings & settings,
std::shared_ptr<Store> buildStore = nullptr);
~EvalState();

Expand Down
1 change: 0 additions & 1 deletion src/libexpr/flake/config.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "users.hh"
#include "globals.hh"
#include "fetch-settings.hh"
#include "flake.hh"

Expand Down
6 changes: 3 additions & 3 deletions src/libexpr/flake/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -803,16 +803,16 @@ 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"));
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]);

callFlake(state,
lockFlake(state, flakeRef,
LockFlags {
.updateLockFile = false,
.writeLockFile = false,
.useRegistries = !evalSettings.pureEval && fetchSettings.useRegistries,
.allowUnlocked = !evalSettings.pureEval,
.useRegistries = !state.settings.pureEval && fetchSettings.useRegistries,
.allowUnlocked = !state.settings.pureEval,
}),
v);
}
Expand Down
1 change: 1 addition & 0 deletions src/libexpr/parser-state.hh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct ParserState
PosTable::Origin origin;
const ref<SourceAccessor> rootFS;
const Expr::AstSymbols & s;
const EvalSettings & settings;

void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
Expand Down
Loading

0 comments on commit fab536d

Please sign in to comment.