From ce698198f06847b57afdb0a5b26aeb132be03e17 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Tue, 3 Dec 2024 20:38:41 +0100 Subject: [PATCH] libcmd: pass EvalState& to installables for the same reason the eval caches should not keep them as references, only worse: installables cannot fully lose their reference member since some types of installable (flakes -sigh-) need access to caches held by their member reference. passing that around as well at all times is not feasible; passing in EvalState& all the time is quite bad enough as is. Change-Id: I05d438623b5ef10fc22e7e256b89447e61a0657d --- lix/libcmd/command.cc | 2 +- lix/libcmd/command.hh | 4 +- lix/libcmd/installable-attr-path.cc | 21 +++++---- lix/libcmd/installable-attr-path.hh | 4 +- lix/libcmd/installable-derived-path.cc | 2 +- lix/libcmd/installable-derived-path.hh | 2 +- lix/libcmd/installable-flake.cc | 61 +++++++++++++------------- lix/libcmd/installable-flake.hh | 10 ++--- lix/libcmd/installable-value.cc | 16 ++++--- lix/libcmd/installable-value.hh | 14 +++--- lix/libcmd/installables.cc | 55 +++++++++++++---------- lix/libcmd/installables.hh | 12 ++++- lix/libexpr/eval-cache.cc | 6 +-- lix/libexpr/eval-cache.hh | 4 +- lix/nix/app.cc | 36 +++++++-------- lix/nix/build.cc | 6 ++- lix/nix/bundle.cc | 4 +- lix/nix/derivation-show.cc | 2 +- lix/nix/develop.cc | 12 ++--- lix/nix/diff-closures.cc | 9 ++-- lix/nix/edit.cc | 2 +- lix/nix/eval.cc | 2 +- lix/nix/flake.cc | 2 +- lix/nix/fmt.cc | 4 +- lix/nix/log.cc | 2 +- lix/nix/profile.cc | 6 +-- lix/nix/repl.cc | 6 +-- lix/nix/run.cc | 4 +- lix/nix/search.cc | 2 +- lix/nix/store-copy-log.cc | 2 +- lix/nix/why-depends.cc | 9 ++-- 31 files changed, 172 insertions(+), 151 deletions(-) diff --git a/lix/libcmd/command.cc b/lix/libcmd/command.cc index 4f489b361..5e12cc4dc 100644 --- a/lix/libcmd/command.cc +++ b/lix/libcmd/command.cc @@ -162,7 +162,7 @@ void BuiltPathsCommand::run(ref store, Installables && installables) for (auto & p : store->queryAllValidPaths()) paths.emplace_back(BuiltPath::Opaque{p}); } else { - paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables); + paths = Installable::toBuiltPaths(*getEvalState(), getEvalStore(), store, realiseMode, operateOn, installables); if (recursive) { // XXX: This only computes the store path closure, ignoring // intermediate realisations diff --git a/lix/libcmd/command.hh b/lix/libcmd/command.hh index 0f9ec66e7..478032116 100644 --- a/lix/libcmd/command.hh +++ b/lix/libcmd/command.hh @@ -115,10 +115,10 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions SourceExprCommand(); Installables parseInstallables( - ref store, std::vector ss); + EvalState & state, ref store, std::vector ss); ref parseInstallable( - ref store, const std::string & installable); + EvalState & state, ref store, const std::string & installable); virtual Strings getDefaultFlakeAttrPaths(); diff --git a/lix/libcmd/installable-attr-path.cc b/lix/libcmd/installable-attr-path.cc index 3af22c098..28bcb351b 100644 --- a/lix/libcmd/installable-attr-path.cc +++ b/lix/libcmd/installable-attr-path.cc @@ -24,21 +24,20 @@ InstallableAttrPath::InstallableAttrPath( , extendedOutputsSpec(std::move(extendedOutputsSpec)) { } -std::pair InstallableAttrPath::toValue() +std::pair InstallableAttrPath::toValue(EvalState & state) { - auto [vRes, pos] = findAlongAttrPath(*state, attrPath, *cmd.getAutoArgs(*evaluator), **v); - state->forceValue(*vRes, pos); + auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(*evaluator), **v); + state.forceValue(*vRes, pos); return {vRes, pos}; } -DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths() +DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths(EvalState & state) { - auto [v, pos] = toValue(); + auto [v, pos] = toValue(state); if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths( - *v, - pos, - fmt("while evaluating the attribute '%s'", attrPath))) + state, *v, pos, fmt("while evaluating the attribute '%s'", attrPath) + )) { return { *derivedPathWithInfo }; } @@ -46,21 +45,21 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths() Bindings & autoArgs = *cmd.getAutoArgs(*evaluator); DrvInfos drvInfos; - getDerivations(*state, *v, "", autoArgs, drvInfos, false); + getDerivations(state, *v, "", autoArgs, drvInfos, false); // Backward compatibility hack: group results by drvPath. This // helps keep .all output together. std::map byDrvPath; for (auto & drvInfo : drvInfos) { - auto drvPath = drvInfo.queryDrvPath(*state); + auto drvPath = drvInfo.queryDrvPath(state); if (!drvPath) throw Error("'%s' is not a derivation", what()); auto newOutputs = std::visit(overloaded { [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { std::set outputsToInstall; - for (auto & output : drvInfo.queryOutputs(*state, false, true)) + for (auto & output : drvInfo.queryOutputs(state, false, true)) outputsToInstall.insert(output.first); return OutputsSpec::Names { std::move(outputsToInstall) }; }, diff --git a/lix/libcmd/installable-attr-path.hh b/lix/libcmd/installable-attr-path.hh index 623af4e05..d040c634f 100644 --- a/lix/libcmd/installable-attr-path.hh +++ b/lix/libcmd/installable-attr-path.hh @@ -28,9 +28,9 @@ class InstallableAttrPath : public InstallableValue std::string what() const override { return attrPath; }; - std::pair toValue() override; + std::pair toValue(EvalState & state) override; - DerivedPathsWithInfo toDerivedPaths() override; + DerivedPathsWithInfo toDerivedPaths(EvalState & state) override; public: diff --git a/lix/libcmd/installable-derived-path.cc b/lix/libcmd/installable-derived-path.cc index 5bbf38c10..b2aca0971 100644 --- a/lix/libcmd/installable-derived-path.cc +++ b/lix/libcmd/installable-derived-path.cc @@ -8,7 +8,7 @@ std::string InstallableDerivedPath::what() const return derivedPath.to_string(*store); } -DerivedPathsWithInfo InstallableDerivedPath::toDerivedPaths() +DerivedPathsWithInfo InstallableDerivedPath::toDerivedPaths(EvalState & state) { return {{ .path = derivedPath, diff --git a/lix/libcmd/installable-derived-path.hh b/lix/libcmd/installable-derived-path.hh index 0c590866c..34e44be25 100644 --- a/lix/libcmd/installable-derived-path.hh +++ b/lix/libcmd/installable-derived-path.hh @@ -16,7 +16,7 @@ struct InstallableDerivedPath : Installable std::string what() const override; - DerivedPathsWithInfo toDerivedPaths() override; + DerivedPathsWithInfo toDerivedPaths(EvalState & state) override; std::optional getStorePath() override; diff --git a/lix/libcmd/installable-flake.cc b/lix/libcmd/installable-flake.cc index b5aab60b8..5264af0b9 100644 --- a/lix/libcmd/installable-flake.cc +++ b/lix/libcmd/installable-flake.cc @@ -71,23 +71,22 @@ InstallableFlake::InstallableFlake( throw UsageError("'--arg' and '--argstr' are incompatible with flakes"); } -DerivedPathsWithInfo InstallableFlake::toDerivedPaths() +DerivedPathsWithInfo InstallableFlake::toDerivedPaths(EvalState & state) { Activity act(*logger, lvlTalkative, actUnknown, fmt("evaluating derivation '%s'", what())); - auto attr = getCursor(); + auto attr = getCursor(state); - auto attrPath = attr->getAttrPathStr(*state); + auto attrPath = attr->getAttrPathStr(state); - if (!attr->isDerivation(*state)) { + if (!attr->isDerivation(state)) { // FIXME: use eval cache? - auto v = attr->forceValue(*state); + auto v = attr->forceValue(state); if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths( - v, - noPos, - fmt("while evaluating the flake output attribute '%s'", attrPath))) + state, v, noPos, fmt("while evaluating the flake output attribute '%s'", attrPath) + )) { return { *derivedPathWithInfo }; } else { @@ -95,19 +94,19 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() "expected flake output attribute '%s' to be a derivation or path but found %s: %s", attrPath, showType(v), - ValuePrinter(*this->state, v, errorPrintOptions) + ValuePrinter(state, v, errorPrintOptions) ); } } - auto drvPath = attr->forceDerivation(*state); + auto drvPath = attr->forceDerivation(state); std::optional priority; - if (attr->maybeGetAttr(*state, "outputSpecified")) { - } else if (auto aMeta = attr->maybeGetAttr(*state, "meta")) { - if (auto aPriority = aMeta->maybeGetAttr(*state, "priority")) - priority = aPriority->getInt(*state).value; + if (attr->maybeGetAttr(state, "outputSpecified")) { + } else if (auto aMeta = attr->maybeGetAttr(state, "meta")) { + if (auto aPriority = aMeta->maybeGetAttr(state, "priority")) + priority = aPriority->getInt(state).value; } return {{ @@ -116,14 +115,14 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() .outputs = std::visit(overloaded { [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { std::set outputsToInstall; - if (auto aOutputSpecified = attr->maybeGetAttr(*state, "outputSpecified")) { - if (aOutputSpecified->getBool(*state)) { - if (auto aOutputName = attr->maybeGetAttr(*state, "outputName")) - outputsToInstall = { aOutputName->getString(*state) }; + if (auto aOutputSpecified = attr->maybeGetAttr(state, "outputSpecified")) { + if (aOutputSpecified->getBool(state)) { + if (auto aOutputName = attr->maybeGetAttr(state, "outputName")) + outputsToInstall = { aOutputName->getString(state) }; } - } else if (auto aMeta = attr->maybeGetAttr(*state, "meta")) { - if (auto aOutputsToInstall = aMeta->maybeGetAttr(*state, "outputsToInstall")) - for (auto & s : aOutputsToInstall->getListOfStrings(*state)) + } else if (auto aMeta = attr->maybeGetAttr(state, "meta")) { + if (auto aOutputsToInstall = aMeta->maybeGetAttr(state, "outputsToInstall")) + for (auto & s : aOutputsToInstall->getListOfStrings(state)) outputsToInstall.insert(s); } @@ -145,20 +144,20 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() }, ExtraPathInfoFlake::Flake { .originalRef = flakeRef, - .lockedRef = getLockedFlake()->flake.lockedRef, + .lockedRef = getLockedFlake(state)->flake.lockedRef, }), }}; } -std::pair InstallableFlake::toValue() +std::pair InstallableFlake::toValue(EvalState & state) { - return {&getCursor()->forceValue(*state), noPos}; + return {&getCursor(state)->forceValue(state), noPos}; } std::vector> -InstallableFlake::getCursors() +InstallableFlake::getCursors(EvalState & state) { - auto evalCache = openEvalCache(*evaluator, getLockedFlake()); + auto evalCache = openEvalCache(*evaluator, getLockedFlake(state)); auto root = evalCache->getRoot(); @@ -170,7 +169,7 @@ InstallableFlake::getCursors() for (auto & attrPath : attrPaths) { debug("trying flake output attribute '%s'", attrPath); - auto attr = root->findAlongAttrPath(*state, parseAttrPath(attrPath)); + auto attr = root->findAlongAttrPath(state, parseAttrPath(attrPath)); if (attr) { res.push_back(ref(*attr)); } else { @@ -188,20 +187,20 @@ InstallableFlake::getCursors() return res; } -std::shared_ptr InstallableFlake::getLockedFlake() const +std::shared_ptr InstallableFlake::getLockedFlake(EvalState & state) const { if (!_lockedFlake) { flake::LockFlags lockFlagsApplyConfig = lockFlags; // FIXME why this side effect? lockFlagsApplyConfig.applyNixConfig = true; - _lockedFlake = std::make_shared(lockFlake(*state, flakeRef, lockFlagsApplyConfig)); + _lockedFlake = std::make_shared(lockFlake(state, flakeRef, lockFlagsApplyConfig)); } return _lockedFlake; } -FlakeRef InstallableFlake::nixpkgsFlakeRef() const +FlakeRef InstallableFlake::nixpkgsFlakeRef(EvalState & state) const { - auto lockedFlake = getLockedFlake(); + auto lockedFlake = getLockedFlake(state); if (auto nixpkgsInput = lockedFlake->lockFile.findInput({"nixpkgs"})) { if (auto lockedNode = std::dynamic_pointer_cast(nixpkgsInput)) { diff --git a/lix/libcmd/installable-flake.hh b/lix/libcmd/installable-flake.hh index 555e94394..d7be2d93d 100644 --- a/lix/libcmd/installable-flake.hh +++ b/lix/libcmd/installable-flake.hh @@ -52,19 +52,19 @@ struct InstallableFlake : InstallableValue std::vector getActualAttrPaths(); - DerivedPathsWithInfo toDerivedPaths() override; + DerivedPathsWithInfo toDerivedPaths(EvalState & state) override; - std::pair toValue() override; + std::pair toValue(EvalState & state) override; /** * Get a cursor to every attrpath in getActualAttrPaths() that * exists. However if none exists, throw an exception. */ - std::vector> getCursors() override; + std::vector> getCursors(EvalState & state) override; - std::shared_ptr getLockedFlake() const; + std::shared_ptr getLockedFlake(EvalState & state) const; - FlakeRef nixpkgsFlakeRef() const; + FlakeRef nixpkgsFlakeRef(EvalState & state) const; }; /** diff --git a/lix/libcmd/installable-value.cc b/lix/libcmd/installable-value.cc index d47f6910c..b16e6589a 100644 --- a/lix/libcmd/installable-value.cc +++ b/lix/libcmd/installable-value.cc @@ -5,20 +5,20 @@ namespace nix { std::vector> -InstallableValue::getCursors() +InstallableValue::getCursors(EvalState & state) { auto evalCache = std::make_shared(std::nullopt, - [&]() { return toValue().first; }); + [&](EvalState & state) { return toValue(state).first; }); return {evalCache->getRoot()}; } ref -InstallableValue::getCursor() +InstallableValue::getCursor(EvalState & state) { /* Although getCursors should return at least one element, in case it doesn't, bound check to avoid an undefined behavior for vector[0] */ - return getCursors().at(0); + return getCursors(state).at(0); } static UsageError nonValueInstallable(Installable & installable) @@ -42,10 +42,12 @@ ref InstallableValue::require(ref installable) return ref { castedInstallable }; } -std::optional InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx) +std::optional InstallableValue::trySinglePathToDerivedPaths( + EvalState & state, Value & v, const PosIdx pos, std::string_view errorCtx +) { if (v.type() == nPath) { - auto storePath = fetchToStore(*state->store, v.path()); + auto storePath = fetchToStore(*evaluator->store, v.path()); return {{ .path = DerivedPath::Opaque { .path = std::move(storePath), @@ -57,7 +59,7 @@ std::optional InstallableValue::trySinglePathToDerivedPaths else if (v.type() == nString) { return {{ .path = DerivedPath::fromSingle( - state->coerceToSingleDerivedPath(pos, v, errorCtx)), + state.coerceToSingleDerivedPath(pos, v, errorCtx)), .info = make_ref(), }}; } diff --git a/lix/libcmd/installable-value.hh b/lix/libcmd/installable-value.hh index 3def5adee..66d35ee4e 100644 --- a/lix/libcmd/installable-value.hh +++ b/lix/libcmd/installable-value.hh @@ -20,7 +20,7 @@ struct App struct UnresolvedApp { App unresolved; - App resolve(ref evalStore, ref store); + App resolve(EvalState & state, ref evalStore, ref store); }; /** @@ -81,22 +81,22 @@ struct InstallableValue : Installable virtual ~InstallableValue() { } - virtual std::pair toValue() = 0; + virtual std::pair toValue(EvalState & state) = 0; /** * Get a cursor to each value this Installable could refer to. * However if none exists, throw exception instead of returning * empty vector. */ - virtual std::vector> getCursors(); + virtual std::vector> getCursors(EvalState & state); /** * Get the first and most preferred cursor this Installable could * refer to, or throw an exception if none exists. */ - virtual ref getCursor(); + virtual ref getCursor(EvalState & state); - UnresolvedApp toApp(); + UnresolvedApp toApp(EvalState & state); static InstallableValue & require(Installable & installable); static ref require(ref installable); @@ -117,7 +117,9 @@ protected: * @result A derived path (with empty info, for now) if the value * matched the above criteria. */ - std::optional trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx); + std::optional trySinglePathToDerivedPaths( + EvalState & state, Value & v, const PosIdx pos, std::string_view errorCtx + ); }; } diff --git a/lix/libcmd/installables.cc b/lix/libcmd/installables.cc index 73f85e333..a94b4295c 100644 --- a/lix/libcmd/installables.cc +++ b/lix/libcmd/installables.cc @@ -371,9 +371,9 @@ void completeFlakeRef(AddCompletions & completions, ref store, std::strin } } -DerivedPathWithInfo Installable::toDerivedPath() +DerivedPathWithInfo Installable::toDerivedPath(EvalState & state) { - auto buildables = toDerivedPaths(); + auto buildables = toDerivedPaths(state); if (buildables.size() != 1) throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size()); return std::move(buildables[0]); @@ -398,7 +398,7 @@ ref openEvalCache( auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval ? std::make_optional(lockedFlake->getFingerprint()) : std::nullopt; - auto rootLoader = [&state, lockedFlake]() + auto rootLoader = [lockedFlake](EvalState & state) { /* For testing whether the evaluation cache is complete. */ @@ -424,7 +424,7 @@ ref openEvalCache( } Installables SourceExprCommand::parseInstallables( - ref store, std::vector ss) + EvalState & state, ref store, std::vector ss) { Installables result; @@ -438,18 +438,18 @@ Installables SourceExprCommand::parseInstallables( getEvalState()->paths.allowedPaths.reset(); } - auto state = getEvalState(); - auto vFile = state->mem.allocValue(); + auto evaluator = getEvalState(); + auto vFile = evaluator->mem.allocValue(); if (file == "-") { - auto & e = state->parseStdin(); - state->eval(e, *vFile); + auto & e = evaluator->parseStdin(); + state.eval(e, *vFile); } else if (file) - state->evalFile(lookupFileArg(*state, *file), *vFile); + state.evalFile(lookupFileArg(state, *file), *vFile); else { - auto & e = state->parseExprFromString(*expr, CanonPath::fromCwd()); - state->eval(e, *vFile); + auto & e = state.parseExprFromString(*expr, CanonPath::fromCwd()); + state.eval(e, *vFile); } for (auto & s : ss) { @@ -457,7 +457,7 @@ Installables SourceExprCommand::parseInstallables( result.push_back( make_ref( InstallableAttrPath::parse( - state, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec)))); + evaluator, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec)))); } } else { @@ -506,9 +506,9 @@ Installables SourceExprCommand::parseInstallables( } ref SourceExprCommand::parseInstallable( - ref store, const std::string & installable) + EvalState & state, ref store, const std::string & installable) { - auto installables = parseInstallables(store, {installable}); + auto installables = parseInstallables(state, store, {installable}); assert(installables.size() == 1); return installables.front(); } @@ -538,6 +538,7 @@ static SingleBuiltPath getBuiltPath(ref evalStore, ref store, cons } std::vector Installable::build( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -545,7 +546,7 @@ std::vector Installable::build( BuildMode bMode) { std::vector res; - for (auto & [_, builtPathWithResult] : build2(evalStore, store, mode, installables, bMode)) + for (auto & [_, builtPathWithResult] : build2(state, evalStore, store, mode, installables, bMode)) res.push_back(builtPathWithResult); return res; } @@ -582,6 +583,7 @@ static void throwBuildErrors( } std::vector, BuiltPathWithResult>> Installable::build2( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -601,7 +603,7 @@ std::vector, BuiltPathWithResult>> Installable::build std::map> backmap; for (auto & i : installables) { - for (auto b : i->toDerivedPaths()) { + for (auto b : i->toDerivedPaths(state)) { pathsToBuild.push_back(b.path); backmap[b.path].push_back({.info = b.info, .installable = i}); } @@ -680,6 +682,7 @@ std::vector, BuiltPathWithResult>> Installable::build } BuiltPaths Installable::toBuiltPaths( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -688,7 +691,7 @@ BuiltPaths Installable::toBuiltPaths( { if (operateOn == OperateOn::Output) { BuiltPaths res; - for (auto & p : Installable::build(evalStore, store, mode, installables)) + for (auto & p : Installable::build(state, evalStore, store, mode, installables)) res.push_back(p.path); return res; } else { @@ -696,20 +699,21 @@ BuiltPaths Installable::toBuiltPaths( settings.readOnlyMode = true; BuiltPaths res; - for (auto & drvPath : Installable::toDerivations(store, installables, true)) + for (auto & drvPath : Installable::toDerivations(state, store, installables, true)) res.emplace_back(BuiltPath::Opaque{drvPath}); return res; } } StorePathSet Installable::toStorePathSet( + EvalState & state, ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables) { StorePathSet outPaths; - for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) { + for (auto & path : toBuiltPaths(state, evalStore, store, mode, operateOn, installables)) { auto thisOutPaths = path.outPaths(); outPaths.insert(thisOutPaths.begin(), thisOutPaths.end()); } @@ -717,13 +721,14 @@ StorePathSet Installable::toStorePathSet( } StorePaths Installable::toStorePaths( + EvalState & state, ref evalStore, ref store, Realise mode, OperateOn operateOn, const Installables & installables) { StorePaths outPaths; - for (auto & path : toBuiltPaths(evalStore, store, mode, operateOn, installables)) { + for (auto & path : toBuiltPaths(state, evalStore, store, mode, operateOn, installables)) { auto thisOutPaths = path.outPaths(); outPaths.insert(outPaths.end(), thisOutPaths.begin(), thisOutPaths.end()); } @@ -731,12 +736,13 @@ StorePaths Installable::toStorePaths( } StorePath Installable::toStorePath( + EvalState & state, ref evalStore, ref store, Realise mode, OperateOn operateOn, ref installable) { - auto paths = toStorePathSet(evalStore, store, mode, operateOn, {installable}); + auto paths = toStorePathSet(state, evalStore, store, mode, operateOn, {installable}); if (paths.size() != 1) throw Error("argument '%s' should evaluate to one store path", installable->what()); @@ -745,6 +751,7 @@ StorePath Installable::toStorePath( } StorePathSet Installable::toDerivations( + EvalState & state, ref store, const Installables & installables, bool useDeriver) @@ -752,7 +759,7 @@ StorePathSet Installable::toDerivations( StorePathSet drvPaths; for (const auto & i : installables) - for (const auto & b : i->toDerivedPaths()) + for (const auto & b : i->toDerivedPaths(state)) std::visit(overloaded { [&](const DerivedPath::Opaque & bo) { drvPaths.insert( @@ -829,7 +836,7 @@ std::vector InstallableCommand::getFlakeRefsForCompletion() void InstallablesCommand::run(ref store, std::vector && rawInstallables) { - auto installables = parseInstallables(store, rawInstallables); + auto installables = parseInstallables(*getEvalState(), store, rawInstallables); run(store, std::move(installables)); } @@ -846,7 +853,7 @@ InstallableCommand::InstallableCommand() void InstallableCommand::run(ref store) { - auto installable = parseInstallable(store, _installable); + auto installable = parseInstallable(*getEvalState(), store, _installable); run(store, std::move(installable)); } diff --git a/lix/libcmd/installables.hh b/lix/libcmd/installables.hh index 4237e3923..423ea33d8 100644 --- a/lix/libcmd/installables.hh +++ b/lix/libcmd/installables.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#include "lix/libexpr/eval.hh" #include "lix/libstore/path.hh" #include "lix/libstore/outputs-spec.hh" #include "lix/libstore/derived-path.hh" @@ -127,7 +128,7 @@ struct Installable * * This is the main method of this class */ - virtual DerivedPathsWithInfo toDerivedPaths() = 0; + virtual DerivedPathsWithInfo toDerivedPaths(EvalState & state) = 0; /** * A convenience wrapper of the above for when we expect an @@ -137,7 +138,7 @@ struct Installable * If no or multiple \ref DerivedPath "derived paths" are produced, * and error is raised. */ - DerivedPathWithInfo toDerivedPath(); + DerivedPathWithInfo toDerivedPath(EvalState & state); /** * Return a value only if this installable is a store path or a @@ -152,6 +153,7 @@ struct Installable } static std::vector build( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -159,6 +161,7 @@ struct Installable BuildMode bMode = bmNormal); static std::vector, BuiltPathWithResult>> build2( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -166,6 +169,7 @@ struct Installable BuildMode bMode = bmNormal); static std::set toStorePathSet( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -173,6 +177,7 @@ struct Installable const Installables & installables); static std::vector toStorePaths( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -180,6 +185,7 @@ struct Installable const Installables & installables); static StorePath toStorePath( + EvalState & state, ref evalStore, ref store, Realise mode, @@ -187,11 +193,13 @@ struct Installable ref installable); static std::set toDerivations( + EvalState & state, ref store, const Installables & installables, bool useDeriver = false); static BuiltPaths toBuiltPaths( + EvalState & state, ref evalStore, ref store, Realise mode, diff --git a/lix/libexpr/eval-cache.cc b/lix/libexpr/eval-cache.cc index cdf52723d..587b5dd48 100644 --- a/lix/libexpr/eval-cache.cc +++ b/lix/libexpr/eval-cache.cc @@ -340,11 +340,11 @@ EvalCache::EvalCache( { } -Value * EvalCache::getRootValue() +Value * EvalCache::getRootValue(EvalState & state) { if (!value) { debug("getting root value"); - value = allocRootValue(rootLoader()); + value = allocRootValue(rootLoader(state)); } return *value; } @@ -387,7 +387,7 @@ Value & AttrCursor::getValue(EvalState & state) throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr(state)); _value = allocRootValue(attr->value); } else - _value = allocRootValue(root->getRootValue()); + _value = allocRootValue(root->getRootValue(state)); } return **_value; } diff --git a/lix/libexpr/eval-cache.hh b/lix/libexpr/eval-cache.hh index 6701735d2..b5fdf97ca 100644 --- a/lix/libexpr/eval-cache.hh +++ b/lix/libexpr/eval-cache.hh @@ -13,7 +13,7 @@ namespace nix::eval_cache { struct AttrDb; class AttrCursor; -typedef std::function RootLoader; +typedef std::function RootLoader; /** * EvalState with caching support. Historically this was part of EvalState, @@ -43,7 +43,7 @@ class EvalCache : public std::enable_shared_from_this RootLoader rootLoader; RootValue value; - Value * getRootValue(); + Value * getRootValue(EvalState & state); public: diff --git a/lix/nix/app.cc b/lix/nix/app.cc index 9d2d456a8..5bff0bba9 100644 --- a/lix/nix/app.cc +++ b/lix/nix/app.cc @@ -51,21 +51,21 @@ std::string resolveString( return rewriteStrings(toResolve, rewrites); } -UnresolvedApp InstallableValue::toApp() +UnresolvedApp InstallableValue::toApp(EvalState & state) { - auto cursor = getCursor(); - auto attrPath = cursor->getAttrPath(*state); + auto cursor = getCursor(state); + auto attrPath = cursor->getAttrPath(state); - auto type = cursor->getAttr(*state, "type")->getString(*state); + auto type = cursor->getAttr(state, "type")->getString(state); std::string expected = !attrPath.empty() && (attrPath[0] == "apps" || attrPath[0] == "defaultApp") ? "app" : "derivation"; if (type != expected) - throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(*state), expected); + throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(state), expected); if (type == "app") { - auto [program, context] = cursor->getAttr(*state, "program")->getStringWithContext(*state); + auto [program, context] = cursor->getAttr(state, "program")->getStringWithContext(state); std::vector context2; for (auto & c : context) { @@ -98,18 +98,18 @@ UnresolvedApp InstallableValue::toApp() } else if (type == "derivation") { - auto drvPath = cursor->forceDerivation(*state); - auto outPath = cursor->getAttr(*state, "outPath")->getString(*state); - auto outputName = cursor->getAttr(*state, "outputName")->getString(*state); - auto name = cursor->getAttr(*state, "name")->getString(*state); - auto aPname = cursor->maybeGetAttr(*state, "pname"); - auto aMeta = cursor->maybeGetAttr(*state, "meta"); - auto aMainProgram = aMeta ? aMeta->maybeGetAttr(*state, "mainProgram") : nullptr; + auto drvPath = cursor->forceDerivation(state); + auto outPath = cursor->getAttr(state, "outPath")->getString(state); + auto outputName = cursor->getAttr(state, "outputName")->getString(state); + auto name = cursor->getAttr(state, "name")->getString(state); + auto aPname = cursor->maybeGetAttr(state, "pname"); + auto aMeta = cursor->maybeGetAttr(state, "meta"); + auto aMainProgram = aMeta ? aMeta->maybeGetAttr(state, "mainProgram") : nullptr; auto mainProgram = aMainProgram - ? aMainProgram->getString(*state) + ? aMainProgram->getString(state) : aPname - ? aPname->getString(*state) + ? aPname->getString(state) : DrvName(name).name; auto program = outPath + "/bin/" + mainProgram; return UnresolvedApp { App { @@ -122,11 +122,11 @@ UnresolvedApp InstallableValue::toApp() } else - throw Error("attribute '%s' has unsupported type '%s'", cursor->getAttrPathStr(*state), type); + throw Error("attribute '%s' has unsupported type '%s'", cursor->getAttrPathStr(state), type); } // FIXME: move to libcmd -App UnresolvedApp::resolve(ref evalStore, ref store) +App UnresolvedApp::resolve(EvalState & state, ref evalStore, ref store) { auto res = unresolved; @@ -136,7 +136,7 @@ App UnresolvedApp::resolve(ref evalStore, ref store) installableContext.push_back( make_ref(store, DerivedPath { ctxElt })); - auto builtContext = Installable::build(evalStore, store, Realise::Outputs, installableContext); + auto builtContext = Installable::build(state, evalStore, store, Realise::Outputs, installableContext); res.program = resolveString(*store, unresolved.program, builtContext); if (!store->isInStore(res.program)) throw Error("app program '%s' is not in the Nix store", res.program); diff --git a/lix/nix/build.cc b/lix/nix/build.cc index c77e385de..bd7e1a84b 100644 --- a/lix/nix/build.cc +++ b/lix/nix/build.cc @@ -114,11 +114,13 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile void run(ref store, Installables && installables) override { + auto state = getEvalState(); + if (dryRun) { std::vector pathsToBuild; for (auto & i : installables) - for (auto & b : i->toDerivedPaths()) + for (auto & b : i->toDerivedPaths(*state)) pathsToBuild.push_back(b.path); printMissing(store, pathsToBuild, lvlError); @@ -130,7 +132,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile } auto buildables = Installable::build( - getEvalStore(), store, + *state, getEvalStore(), store, Realise::Outputs, installables, repair ? bmRepair : buildMode); diff --git a/lix/nix/bundle.cc b/lix/nix/bundle.cc index ff21baf43..aa6d51c09 100644 --- a/lix/nix/bundle.cc +++ b/lix/nix/bundle.cc @@ -78,7 +78,7 @@ struct CmdBundle : InstallableCommand auto const installableValue = InstallableValue::require(installable); - auto val = installableValue->toValue().first; + auto val = installableValue->toValue(*evalState).first; auto [bundlerFlakeRef, bundlerName, extendedOutputsSpec] = parseFlakeRefWithFragmentAndExtendedOutputsSpec(bundler, absPath(".")); const flake::LockFlags lockFlags{ .writeLockFile = false }; @@ -92,7 +92,7 @@ struct CmdBundle : InstallableCommand }; auto vRes = evaluator->mem.allocValue(); - evalState->callFunction(*bundler.toValue().first, *val, *vRes, noPos); + evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos); if (!evalState->isDerivation(*vRes)) throw Error("the bundler '%s' does not produce a derivation", bundler.what()); diff --git a/lix/nix/derivation-show.cc b/lix/nix/derivation-show.cc index d6769af52..fc290b7db 100644 --- a/lix/nix/derivation-show.cc +++ b/lix/nix/derivation-show.cc @@ -41,7 +41,7 @@ struct CmdShowDerivation : InstallablesCommand void run(ref store, Installables && installables) override { - auto drvPaths = Installable::toDerivations(store, installables, true); + auto drvPaths = Installable::toDerivations(*getEvalState(), store, installables, true); if (recursive) { StorePathSet closure; diff --git a/lix/nix/develop.cc b/lix/nix/develop.cc index 7521af182..439f33fc8 100644 --- a/lix/nix/develop.cc +++ b/lix/nix/develop.cc @@ -364,9 +364,9 @@ struct Common : InstallableCommand, MixProfile /* Substitute redirects. */ for (auto & [installable_, dir_] : redirects) { auto dir = absPath(dir_); - auto installable = parseInstallable(store, installable_); + auto installable = parseInstallable(*getEvalState(), store, installable_); auto builtPaths = Installable::toStorePathSet( - getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); + *getEvalState(), getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); for (auto & path: builtPaths) { auto from = store->printStorePath(path); if (script.find(from) == std::string::npos) @@ -444,7 +444,7 @@ struct Common : InstallableCommand, MixProfile if (path && path->to_string().ends_with("-env")) return *path; else { - auto drvs = Installable::toDerivations(store, {installable}); + auto drvs = Installable::toDerivations(*getEvalState(), store, {installable}); if (drvs.size() != 1) throw Error("'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations", @@ -607,7 +607,7 @@ struct CmdDevelop : Common, MixEnvironment auto nixpkgs = defaultNixpkgsFlakeRef(); if (auto * i = dynamic_cast(&*installable)) - nixpkgs = i->nixpkgsFlakeRef(); + nixpkgs = i->nixpkgsFlakeRef(*state); auto bashInstallable = make_ref( this, @@ -621,7 +621,7 @@ struct CmdDevelop : Common, MixEnvironment bool found = false; - for (auto & path : Installable::toStorePathSet(getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { + for (auto & path : Installable::toStorePathSet(*state, getEvalStore(), store, Realise::Outputs, OperateOn::Output, {bashInstallable})) { auto s = store->printStorePath(path) + "/bin/bash"; if (pathExists(s)) { shell = s; @@ -651,7 +651,7 @@ struct CmdDevelop : Common, MixEnvironment // chdir if installable is a flake of type git+file or path auto installableFlake = installable.dynamic_pointer_cast(); if (installableFlake) { - auto sourcePath = installableFlake->getLockedFlake()->flake.resolvedRef.input.getSourcePath(); + auto sourcePath = installableFlake->getLockedFlake(*getEvalState())->flake.resolvedRef.input.getSourcePath(); if (sourcePath) { if (chdir(sourcePath->c_str()) == -1) { throw SysError("chdir to '%s' failed", *sourcePath); diff --git a/lix/nix/diff-closures.cc b/lix/nix/diff-closures.cc index 7162feb83..b44ed1c8f 100644 --- a/lix/nix/diff-closures.cc +++ b/lix/nix/diff-closures.cc @@ -124,10 +124,11 @@ struct CmdDiffClosures : SourceExprCommand, MixOperateOnOptions void run(ref store) override { - auto before = parseInstallable(store, _before); - auto beforePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, before); - auto after = parseInstallable(store, _after); - auto afterPath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, after); + auto state = getEvalState(); + auto before = parseInstallable(*state, store, _before); + auto beforePath = Installable::toStorePath(*state, getEvalStore(), store, Realise::Outputs, operateOn, before); + auto after = parseInstallable(*state, store, _after); + auto afterPath = Installable::toStorePath(*state, getEvalStore(), store, Realise::Outputs, operateOn, after); printClosureDiff(store, beforePath, afterPath, ""); } }; diff --git a/lix/nix/edit.cc b/lix/nix/edit.cc index 7ed7f2525..fabfca3d1 100644 --- a/lix/nix/edit.cc +++ b/lix/nix/edit.cc @@ -33,7 +33,7 @@ struct CmdEdit : InstallableCommand auto const installableValue = InstallableValue::require(installable); const auto [file, line] = [&] { - auto [v, pos] = installableValue->toValue(); + auto [v, pos] = installableValue->toValue(*state); try { return findPackageFilename(*state, *v, installable->what()); diff --git a/lix/nix/eval.cc b/lix/nix/eval.cc index 0b33ced0c..942e7f122 100644 --- a/lix/nix/eval.cc +++ b/lix/nix/eval.cc @@ -64,7 +64,7 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption auto evaluator = getEvalState(); auto state = evaluator; - auto [v, pos] = installableValue->toValue(); + auto [v, pos] = installableValue->toValue(*state); NixStringContext context; if (apply) { diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 515589bac..2230d40c1 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -864,7 +864,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand defaultTemplateAttrPathsPrefixes, lockFlags); - auto cursor = installable.getCursor(); + auto cursor = installable.getCursor(*evalState); auto templateDirAttr = cursor->getAttr(*evalState, "path"); auto templateDir = templateDirAttr->getString(*evalState); diff --git a/lix/nix/fmt.cc b/lix/nix/fmt.cc index 40d70cf9c..4d0576f6d 100644 --- a/lix/nix/fmt.cc +++ b/lix/nix/fmt.cc @@ -32,9 +32,9 @@ struct CmdFmt : SourceExprCommand { auto evalState = getEvalState(); auto evalStore = getEvalStore(); - auto installable_ = parseInstallable(store, "."); + auto installable_ = parseInstallable(*evalState, store, "."); auto & installable = InstallableValue::require(*installable_); - auto app = installable.toApp().resolve(evalStore, store); + auto app = installable.toApp(*evalState).resolve(*evalState, evalStore, store); Strings programArgs{app.program}; diff --git a/lix/nix/log.cc b/lix/nix/log.cc index 8ea26a405..1dd853d8e 100644 --- a/lix/nix/log.cc +++ b/lix/nix/log.cc @@ -30,7 +30,7 @@ struct CmdLog : InstallableCommand subs.push_front(store); - auto b = installable->toDerivedPath(); + auto b = installable->toDerivedPath(*getEvalState()); // For compat with CLI today, TODO revisit auto oneUp = std::visit(overloaded { diff --git a/lix/nix/profile.cc b/lix/nix/profile.cc index d5d20ce71..cd55a32bf 100644 --- a/lix/nix/profile.cc +++ b/lix/nix/profile.cc @@ -73,7 +73,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile auto builtPaths = builtPathsPerInstallable( Installable::build2( - getEvalStore(), store, Realise::Outputs, installables, bmNormal)); + *getEvalState(), getEvalStore(), store, Realise::Outputs, installables, bmNormal)); for (auto & installable : installables) { ProfileElement element; @@ -343,7 +343,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf lockFlags ); - auto derivedPaths = installable->toDerivedPaths(); + auto derivedPaths = installable->toDerivedPaths(*getEvalState()); if (derivedPaths.empty()) { continue; } @@ -393,7 +393,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf auto builtPaths = builtPathsPerInstallable( Installable::build2( - getEvalStore(), store, Realise::Outputs, installables, bmNormal)); + *getEvalState(), getEvalStore(), store, Realise::Outputs, installables, bmNormal)); for (size_t i = 0; i < installables.size(); ++i) { auto & installable = installables.at(i); diff --git a/lix/nix/repl.cc b/lix/nix/repl.cc index 0d8debdf5..c6ba796ac 100644 --- a/lix/nix/repl.cc +++ b/lix/nix/repl.cc @@ -66,13 +66,13 @@ struct CmdRepl : RawInstallablesCommand auto evaluator = getEvalState(); auto state = evaluator; auto getValues = [&]()->AbstractNixRepl::AnnotatedValues{ - auto installables = parseInstallables(store, rawInstallables); + auto installables = parseInstallables(*state, store, rawInstallables); AbstractNixRepl::AnnotatedValues values; for (auto & installable_: installables){ auto & installable = InstallableValue::require(*installable_); auto what = installable.what(); if (file){ - auto [val, pos] = installable.toValue(); + auto [val, pos] = installable.toValue(*state); auto what = installable.what(); state->forceValue(*val, pos); auto autoArgs = getAutoArgs(*evaluator); @@ -81,7 +81,7 @@ struct CmdRepl : RawInstallablesCommand state->forceValue(*valPost, pos); values.push_back( {valPost, what }); } else { - auto [val, pos] = installable.toValue(); + auto [val, pos] = installable.toValue(*state); values.push_back( {val, what} ); } } diff --git a/lix/nix/run.cc b/lix/nix/run.cc index 31019159c..8df68c343 100644 --- a/lix/nix/run.cc +++ b/lix/nix/run.cc @@ -111,7 +111,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment void run(ref store, Installables && installables) override { - auto outPaths = Installable::toStorePaths(getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables); + auto outPaths = Installable::toStorePaths(*getEvalState(), getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables); auto accessor = store->getFSAccessor(); @@ -205,7 +205,7 @@ struct CmdRun : InstallableCommand auto installableValue = InstallableValue::require(installable); lockFlags.applyNixConfig = true; - auto app = installableValue->toApp().resolve(getEvalStore(), store); + auto app = installableValue->toApp(*state).resolve(*state, getEvalStore(), store); Strings allArgs{app.program}; for (auto & i : args) allArgs.push_back(i); diff --git a/lix/nix/search.cc b/lix/nix/search.cc index 544617250..275dfbbb3 100644 --- a/lix/nix/search.cc +++ b/lix/nix/search.cc @@ -193,7 +193,7 @@ struct CmdSearch : InstallableCommand, MixJSON } }; - for (auto & cursor : installableValue->getCursors()) + for (auto & cursor : installableValue->getCursors(*state)) visit(*cursor, cursor->getAttrPath(*state), true); if (json) diff --git a/lix/nix/store-copy-log.cc b/lix/nix/store-copy-log.cc index ee3b13048..617024071 100644 --- a/lix/nix/store-copy-log.cc +++ b/lix/nix/store-copy-log.cc @@ -31,7 +31,7 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand auto dstStore = getDstStore(); auto & dstLogStore = require(*dstStore); - for (auto & drvPath : Installable::toDerivations(getEvalStore(), installables, true)) { + for (auto & drvPath : Installable::toDerivations(*getEvalState(), getEvalStore(), installables, true)) { if (auto log = srcLogStore.getBuildLog(drvPath)) dstLogStore.addBuildLog(drvPath, *log); else diff --git a/lix/nix/why-depends.cc b/lix/nix/why-depends.cc index 2cd3f801f..1a5246bb4 100644 --- a/lix/nix/why-depends.cc +++ b/lix/nix/why-depends.cc @@ -76,8 +76,9 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions void run(ref store) override { - auto package = parseInstallable(store, _package); - auto packagePath = Installable::toStorePath(getEvalStore(), store, Realise::Outputs, operateOn, package); + auto state = getEvalState(); + auto package = parseInstallable(*state, store, _package); + auto packagePath = Installable::toStorePath(*state, getEvalStore(), store, Realise::Outputs, operateOn, package); /* We don't need to build `dependency`. We try to get the store * path if it's already known, and if not, then it's not a dependency. @@ -89,10 +90,10 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions * derivation which hasn't been built), then `package` did not need it * to build. */ - auto dependency = parseInstallable(store, _dependency); + auto dependency = parseInstallable(*state, store, _dependency); auto optDependencyPath = [&]() -> std::optional { try { - return {Installable::toStorePath(getEvalStore(), store, Realise::Derivation, operateOn, dependency)}; + return {Installable::toStorePath(*state, getEvalStore(), store, Realise::Derivation, operateOn, dependency)}; } catch (MissingRealisation &) { return std::nullopt; }