From 9ff702554d353383ae7996c787cdf3ec74b7f1d2 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Tue, 3 Dec 2024 20:38:41 +0100 Subject: [PATCH] libexpr: eval caches should not have an EvalState& and for the same reason DrvInfo shouldn't, only even more so. the eval cache infrastructure wants to be a wrapper around evaluation, with its lifetimes fully decoupled from the lifetime of the wrapped evaluation. this can't not create problems when eval lifetime must become bounded. Change-Id: Ib8eec649995b4decd7290c2266322f67d73b6b46 --- lix/libcmd/installable-flake.cc | 34 +++---- lix/libcmd/installables.cc | 8 +- lix/libexpr/eval-cache.cc | 153 ++++++++++++++++---------------- lix/libexpr/eval-cache.hh | 37 ++++---- lix/nix/app.cc | 28 +++--- lix/nix/flake.cc | 40 ++++----- lix/nix/search.cc | 20 ++--- 7 files changed, 159 insertions(+), 161 deletions(-) diff --git a/lix/libcmd/installable-flake.cc b/lix/libcmd/installable-flake.cc index 06ca7d39a..9cbdf566f 100644 --- a/lix/libcmd/installable-flake.cc +++ b/lix/libcmd/installable-flake.cc @@ -77,12 +77,12 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() auto attr = getCursor(); - auto attrPath = attr->getAttrPathStr(); + auto attrPath = attr->getAttrPathStr(*state); - if (!attr->isDerivation()) { + if (!attr->isDerivation(*state)) { // FIXME: use eval cache? - auto v = attr->forceValue(); + auto v = attr->forceValue(*state); if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths( v, @@ -100,14 +100,14 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() } } - auto drvPath = attr->forceDerivation(); + auto drvPath = attr->forceDerivation(*state); std::optional priority; - if (attr->maybeGetAttr("outputSpecified")) { - } else if (auto aMeta = attr->maybeGetAttr("meta")) { - if (auto aPriority = aMeta->maybeGetAttr("priority")) - priority = aPriority->getInt().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 +116,14 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() .outputs = std::visit(overloaded { [&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec { std::set outputsToInstall; - if (auto aOutputSpecified = attr->maybeGetAttr("outputSpecified")) { - if (aOutputSpecified->getBool()) { - if (auto aOutputName = attr->maybeGetAttr("outputName")) - outputsToInstall = { aOutputName->getString() }; + 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("meta")) { - if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall")) - for (auto & s : aOutputsToInstall->getListOfStrings()) + } else if (auto aMeta = attr->maybeGetAttr(*state, "meta")) { + if (auto aOutputsToInstall = aMeta->maybeGetAttr(*state, "outputsToInstall")) + for (auto & s : aOutputsToInstall->getListOfStrings(*state)) outputsToInstall.insert(s); } @@ -152,7 +152,7 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths() std::pair InstallableFlake::toValue() { - return {&getCursor()->forceValue(), noPos}; + return {&getCursor()->forceValue(*state), noPos}; } std::vector> @@ -170,7 +170,7 @@ InstallableFlake::getCursors() for (auto & attrPath : attrPaths) { debug("trying flake output attribute '%s'", attrPath); - auto attr = root->findAlongAttrPath(parseAttrPath(attrPath)); + auto attr = root->findAlongAttrPath(*state, parseAttrPath(attrPath)); if (attr) { res.push_back(ref(*attr)); } else { diff --git a/lix/libcmd/installables.cc b/lix/libcmd/installables.cc index bf34a1169..02d199ea9 100644 --- a/lix/libcmd/installables.cc +++ b/lix/libcmd/installables.cc @@ -317,12 +317,12 @@ void completeFlakeRefWithFragment( attrPath.pop_back(); } - auto attr = root->findAlongAttrPath(attrPath); + auto attr = root->findAlongAttrPath(*evalState, attrPath); if (!attr) continue; - for (auto & attr2 : (*attr)->getAttrs()) { + for (auto & attr2 : (*attr)->getAttrs(*evalState)) { if (std::string_view attr2s = attr2; attr2s.starts_with(lastAttr)) { - auto attrPath2 = (*attr)->getAttrPath(attr2s); + auto attrPath2 = (*attr)->getAttrPath(*evalState, attr2s); /* Strip the attrpath prefix. */ attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); completions.add(flakeRefS + "#" + prefixRoot + concatStringsSep(".", attrPath2)); @@ -334,7 +334,7 @@ void completeFlakeRefWithFragment( attrpaths. */ if (fragment.empty()) { for (auto & attrPath : defaultFlakeAttrPaths) { - auto attr = root->findAlongAttrPath(parseAttrPath(attrPath)); + auto attr = root->findAlongAttrPath(*evalState, parseAttrPath(attrPath)); if (!attr) continue; completions.add(flakeRefS + "#" + prefixRoot); } diff --git a/lix/libexpr/eval-cache.cc b/lix/libexpr/eval-cache.cc index bf1560fc4..44ed5767d 100644 --- a/lix/libexpr/eval-cache.cc +++ b/lix/libexpr/eval-cache.cc @@ -344,7 +344,6 @@ EvalCache::EvalCache( EvalState & state, RootLoader rootLoader) : db(useCache ? makeAttrDb(*state.store, *useCache) : nullptr) - , state(state) , rootLoader(rootLoader) { } @@ -385,15 +384,15 @@ AttrKey AttrCursor::getKey() return {parent->first->cachedValue->first, parent->second}; } -Value & AttrCursor::getValue() +Value & AttrCursor::getValue(EvalState & state) { if (!_value) { if (parent) { - auto & vParent = parent->first->getValue(); - root->state.forceAttrs(vParent, noPos, "while searching for an attribute"); - auto attr = vParent.attrs->get(root->state.symbols.create(parent->second)); + auto & vParent = parent->first->getValue(state); + state.forceAttrs(vParent, noPos, "while searching for an attribute"); + auto attr = vParent.attrs->get(state.symbols.create(parent->second)); if (!attr) - throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr()); + throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr(state)); _value = allocRootValue(attr->value); } else _value = allocRootValue(root->getRootValue()); @@ -401,43 +400,43 @@ Value & AttrCursor::getValue() return **_value; } -std::vector AttrCursor::getAttrPath() const +std::vector AttrCursor::getAttrPath(EvalState & state) const { if (parent) { - auto attrPath = parent->first->getAttrPath(); + auto attrPath = parent->first->getAttrPath(state); attrPath.push_back(parent->second); return attrPath; } else return {}; } -std::vector AttrCursor::getAttrPath(std::string_view name) const +std::vector AttrCursor::getAttrPath(EvalState & state, std::string_view name) const { - auto attrPath = getAttrPath(); + auto attrPath = getAttrPath(state); attrPath.emplace_back(name); return attrPath; } -std::string AttrCursor::getAttrPathStr() const +std::string AttrCursor::getAttrPathStr(EvalState & state) const { - return concatStringsSep(".", getAttrPath()); + return concatStringsSep(".", getAttrPath(state)); } -std::string AttrCursor::getAttrPathStr(std::string_view name) const +std::string AttrCursor::getAttrPathStr(EvalState & state, std::string_view name) const { - return concatStringsSep(".", getAttrPath(name)); + return concatStringsSep(".", getAttrPath(state, name)); } -Value & AttrCursor::forceValue() +Value & AttrCursor::forceValue(EvalState & state) { - debug("evaluating uncached attribute '%s'", getAttrPathStr()); + debug("evaluating uncached attribute '%s'", getAttrPathStr(state)); - auto & v = getValue(); + auto & v = getValue(state); try { - root->state.forceValue(v, noPos); + state.forceValue(v, noPos); } catch (EvalError &) { - debug("setting '%s' to failed", getAttrPathStr()); + debug("setting '%s' to failed", getAttrPathStr(state)); if (root->db) cachedValue = {root->db->setFailed(getKey()), failed_t()}; throw; @@ -464,13 +463,13 @@ Value & AttrCursor::forceValue() return v; } -Suggestions AttrCursor::getSuggestionsForAttr(const std::string & name) +Suggestions AttrCursor::getSuggestionsForAttr(EvalState & state, const std::string & name) { - auto attrNames = getAttrs(); + auto attrNames = getAttrs(state); return Suggestions::bestMatches({attrNames.begin(), attrNames.end()}, name); } -std::shared_ptr AttrCursor::maybeGetAttr(const std::string & name) +std::shared_ptr AttrCursor::maybeGetAttr(EvalState & state, const std::string & name) { if (root->db) { if (!cachedValue) @@ -488,7 +487,7 @@ std::shared_ptr AttrCursor::maybeGetAttr(const std::string & name) if (std::get_if(&attr->second)) return nullptr; else if (std::get_if(&attr->second)) { - debug("reevaluating failed cached attribute '%s'", getAttrPathStr(name)); + debug("reevaluating failed cached attribute '%s'", getAttrPathStr(state, name)); } else return std::make_shared(root, std::make_pair(shared_from_this(), name), nullptr, std::move(attr)); @@ -501,13 +500,13 @@ std::shared_ptr AttrCursor::maybeGetAttr(const std::string & name) } } - auto & v = forceValue(); + auto & v = forceValue(state); if (v.type() != nAttrs) return nullptr; //errors.make("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); - auto attr = v.attrs->get(root->state.symbols.create(name)); + auto attr = v.attrs->get(state.symbols.create(name)); if (!attr) { if (root->db) { @@ -529,21 +528,21 @@ std::shared_ptr AttrCursor::maybeGetAttr(const std::string & name) root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2)); } -ref AttrCursor::getAttr(const std::string & name) +ref AttrCursor::getAttr(EvalState & state, const std::string & name) { - auto p = maybeGetAttr(name); + auto p = maybeGetAttr(state, name); if (!p) - throw Error("attribute '%s' does not exist", getAttrPathStr(name)); + throw Error("attribute '%s' does not exist", getAttrPathStr(state, name)); return ref(p); } -OrSuggestions> AttrCursor::findAlongAttrPath(const Strings & attrPath) +OrSuggestions> AttrCursor::findAlongAttrPath(EvalState & state, const Strings & attrPath) { auto res = shared_from_this(); for (auto & attr : attrPath) { - auto child = res->maybeGetAttr(attr); + auto child = res->maybeGetAttr(state, attr); if (!child) { - auto suggestions = res->getSuggestionsForAttr(attr); + auto suggestions = res->getSuggestionsForAttr(state, attr); return OrSuggestions>::failed(suggestions); } res = child; @@ -551,30 +550,30 @@ OrSuggestions> AttrCursor::findAlongAttrPath(const Strings & att return ref(res); } -std::string AttrCursor::getString() +std::string AttrCursor::getString(EvalState & state) { if (root->db) { if (!cachedValue) cachedValue = root->db->getAttr(getKey()); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto s = std::get_if(&cachedValue->second)) { - debug("using cached string attribute '%s'", getAttrPathStr()); + debug("using cached string attribute '%s'", getAttrPathStr(state)); return s->first; } else - root->state.errors.make("'%s' is not a string", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not a string", getAttrPathStr(state)).debugThrow(); } } - auto & v = forceValue(); + auto & v = forceValue(state); if (v.type() != nString && v.type() != nPath) { - root->state.errors.make("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow(); + state.errors.make("'%s' is not a string but %s", getAttrPathStr(state), v.type()).debugThrow(); } return v.type() == nString ? v.string.s : v.path().to_string(); } -string_t AttrCursor::getStringWithContext() +string_t AttrCursor::getStringWithContext(EvalState & state) { if (root->db) { if (!cachedValue) @@ -594,21 +593,21 @@ string_t AttrCursor::getStringWithContext() return o.path; }, }, c.raw); - if (!root->state.store->isValidPath(path)) { + if (!state.store->isValidPath(path)) { valid = false; break; } } if (valid) { - debug("using cached string attribute '%s'", getAttrPathStr()); + debug("using cached string attribute '%s'", getAttrPathStr(state)); return *s; } } else - root->state.errors.make("'%s' is not a string", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not a string", getAttrPathStr(state)).debugThrow(); } } - auto & v = forceValue(); + auto & v = forceValue(state); if (v.type() == nString) { NixStringContext context; @@ -617,80 +616,80 @@ string_t AttrCursor::getStringWithContext() } else if (v.type() == nPath) { return {v.path().to_string(), {}}; } else { - root->state.errors.make("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow(); + state.errors.make("'%s' is not a string but %s", getAttrPathStr(state), v.type()).debugThrow(); } } -bool AttrCursor::getBool() +bool AttrCursor::getBool(EvalState & state) { if (root->db) { if (!cachedValue) cachedValue = root->db->getAttr(getKey()); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto b = std::get_if(&cachedValue->second)) { - debug("using cached Boolean attribute '%s'", getAttrPathStr()); + debug("using cached Boolean attribute '%s'", getAttrPathStr(state)); return *b; } else - root->state.errors.make("'%s' is not a Boolean", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow(); } } - auto & v = forceValue(); + auto & v = forceValue(state); if (v.type() != nBool) - root->state.errors.make("'%s' is not a Boolean", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow(); return v.boolean; } -NixInt AttrCursor::getInt() +NixInt AttrCursor::getInt(EvalState & state) { if (root->db) { if (!cachedValue) cachedValue = root->db->getAttr(getKey()); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto i = std::get_if(&cachedValue->second)) { - debug("using cached integer attribute '%s'", getAttrPathStr()); + debug("using cached integer attribute '%s'", getAttrPathStr(state)); return i->x; } else - root->state.errors.make("'%s' is not an integer", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not an integer", getAttrPathStr(state)).debugThrow(); } } - auto & v = forceValue(); + auto & v = forceValue(state); if (v.type() != nInt) - root->state.errors.make("'%s' is not an integer", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not an integer", getAttrPathStr(state)).debugThrow(); return v.integer; } -std::vector AttrCursor::getListOfStrings() +std::vector AttrCursor::getListOfStrings(EvalState & state) { if (root->db) { if (!cachedValue) cachedValue = root->db->getAttr(getKey()); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto l = std::get_if>(&cachedValue->second)) { - debug("using cached list of strings attribute '%s'", getAttrPathStr()); + debug("using cached list of strings attribute '%s'", getAttrPathStr(state)); return *l; } else - root->state.errors.make("'%s' is not a list of strings", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not a list of strings", getAttrPathStr(state)).debugThrow(); } } - debug("evaluating uncached attribute '%s'", getAttrPathStr()); + debug("evaluating uncached attribute '%s'", getAttrPathStr(state)); - auto & v = getValue(); - root->state.forceValue(v, noPos); + auto & v = getValue(state); + state.forceValue(v, noPos); if (v.type() != nList) - root->state.errors.make("'%s' is not a list", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not a list", getAttrPathStr(state)).debugThrow(); std::vector res; for (auto & elem : v.listItems()) - res.push_back(std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching"))); + res.push_back(std::string(state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching"))); if (root->db) cachedValue = {root->db->setListOfStrings(getKey(), res), res}; @@ -698,28 +697,28 @@ std::vector AttrCursor::getListOfStrings() return res; } -std::vector AttrCursor::getAttrs() +std::vector AttrCursor::getAttrs(EvalState & state) { if (root->db) { if (!cachedValue) cachedValue = root->db->getAttr(getKey()); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto attrs = std::get_if(&cachedValue->second)) { - debug("using cached attrset attribute '%s'", getAttrPathStr()); + debug("using cached attrset attribute '%s'", getAttrPathStr(state)); return attrs->p; } else - root->state.errors.make("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow(); } } - auto & v = forceValue(); + auto & v = forceValue(state); if (v.type() != nAttrs) - root->state.errors.make("'%s' is not an attribute set", getAttrPathStr()).debugThrow(); + state.errors.make("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow(); fullattr_t attrs; - for (auto & attr : *getValue().attrs) - attrs.p.push_back(root->state.symbols[attr.name]); + for (auto & attr : *getValue(state).attrs) + attrs.p.push_back(state.symbols[attr.name]); std::sort(attrs.p.begin(), attrs.p.end()); if (root->db) @@ -728,23 +727,23 @@ std::vector AttrCursor::getAttrs() return attrs.p; } -bool AttrCursor::isDerivation() +bool AttrCursor::isDerivation(EvalState & state) { - auto aType = maybeGetAttr("type"); - return aType && aType->getString() == "derivation"; + auto aType = maybeGetAttr(state, "type"); + return aType && aType->getString(state) == "derivation"; } -StorePath AttrCursor::forceDerivation() +StorePath AttrCursor::forceDerivation(EvalState & state) { - auto aDrvPath = getAttr("drvPath"); - auto drvPath = root->state.store->parseStorePath(aDrvPath->getString()); - if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) { + auto aDrvPath = getAttr(state, "drvPath"); + auto drvPath = state.store->parseStorePath(aDrvPath->getString(state)); + if (!state.store->isValidPath(drvPath) && !settings.readOnlyMode) { /* The eval cache contains 'drvPath', but the actual path has been garbage-collected. So force it to be regenerated. */ - aDrvPath->forceValue(); - if (!root->state.store->isValidPath(drvPath)) + aDrvPath->forceValue(state); + if (!state.store->isValidPath(drvPath)) throw Error("don't know how to recreate store derivation '%s'!", - root->state.store->printStorePath(drvPath)); + state.store->printStorePath(drvPath)); } return drvPath; } diff --git a/lix/libexpr/eval-cache.hh b/lix/libexpr/eval-cache.hh index bff81dc1e..124efbb58 100644 --- a/lix/libexpr/eval-cache.hh +++ b/lix/libexpr/eval-cache.hh @@ -40,7 +40,6 @@ class EvalCache : public std::enable_shared_from_this friend class AttrCursor; std::shared_ptr db; - EvalState & state; RootLoader rootLoader; RootValue value; @@ -102,7 +101,7 @@ class AttrCursor : public std::enable_shared_from_this AttrKey getKey(); - Value & getValue(); + Value & getValue(EvalState & state); public: @@ -112,46 +111,46 @@ public: Value * value = nullptr, std::optional> && cachedValue = {}); - std::vector getAttrPath() const; + std::vector getAttrPath(EvalState & state) const; - std::vector getAttrPath(std::string_view name) const; + std::vector getAttrPath(EvalState & state, std::string_view name) const; - std::string getAttrPathStr() const; + std::string getAttrPathStr(EvalState & state) const; - std::string getAttrPathStr(std::string_view name) const; + std::string getAttrPathStr(EvalState & state, std::string_view name) const; - Suggestions getSuggestionsForAttr(const std::string & name); + Suggestions getSuggestionsForAttr(EvalState & state, const std::string & name); - std::shared_ptr maybeGetAttr(const std::string & name); + std::shared_ptr maybeGetAttr(EvalState & state, const std::string & name); - ref getAttr(const std::string & name); + ref getAttr(EvalState & state, const std::string & name); /** * Get an attribute along a chain of attrsets. Note that this does * not auto-call functors or functions. */ - OrSuggestions> findAlongAttrPath(const Strings & attrPath); + OrSuggestions> findAlongAttrPath(EvalState & state, const Strings & attrPath); - std::string getString(); + std::string getString(EvalState & state); - string_t getStringWithContext(); + string_t getStringWithContext(EvalState & state); - bool getBool(); + bool getBool(EvalState & state); - NixInt getInt(); + NixInt getInt(EvalState & state); - std::vector getListOfStrings(); + std::vector getListOfStrings(EvalState & state); - std::vector getAttrs(); + std::vector getAttrs(EvalState & state); - bool isDerivation(); + bool isDerivation(EvalState & state); - Value & forceValue(); + Value & forceValue(EvalState & state); /** * Force creation of the .drv file in the Nix store. */ - StorePath forceDerivation(); + StorePath forceDerivation(EvalState & state); }; } diff --git a/lix/nix/app.cc b/lix/nix/app.cc index 8bcc54c75..9d2d456a8 100644 --- a/lix/nix/app.cc +++ b/lix/nix/app.cc @@ -54,18 +54,18 @@ std::string resolveString( UnresolvedApp InstallableValue::toApp() { auto cursor = getCursor(); - auto attrPath = cursor->getAttrPath(); + auto attrPath = cursor->getAttrPath(*state); - auto type = cursor->getAttr("type")->getString(); + 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(), expected); + throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(*state), expected); if (type == "app") { - auto [program, context] = cursor->getAttr("program")->getStringWithContext(); + 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(); - auto outPath = cursor->getAttr("outPath")->getString(); - auto outputName = cursor->getAttr("outputName")->getString(); - auto name = cursor->getAttr("name")->getString(); - auto aPname = cursor->maybeGetAttr("pname"); - auto aMeta = cursor->maybeGetAttr("meta"); - auto aMainProgram = aMeta ? aMeta->maybeGetAttr("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() + ? aMainProgram->getString(*state) : aPname - ? aPname->getString() + ? aPname->getString(*state) : DrvName(name).name; auto program = outPath + "/bin/" + mainProgram; return UnresolvedApp { App { @@ -122,7 +122,7 @@ UnresolvedApp InstallableValue::toApp() } else - throw Error("attribute '%s' has unsupported type '%s'", cursor->getAttrPathStr(), type); + throw Error("attribute '%s' has unsupported type '%s'", cursor->getAttrPathStr(*state), type); } // FIXME: move to libcmd diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 631b6c48f..7f945ac96 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -864,14 +864,14 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand auto cursor = installable.getCursor(); - auto templateDirAttr = cursor->getAttr("path"); - auto templateDir = templateDirAttr->getString(); + auto templateDirAttr = cursor->getAttr(*evalState, "path"); + auto templateDir = templateDirAttr->getString(*evalState); if (!store->isInStore(templateDir)) evalState->errors.make( "'%s' was not found in the Nix store\n" "If you've set '%s' to a string, try using a path instead.", - templateDir, templateDirAttr->getAttrPathStr()).debugThrow(); + templateDir, templateDirAttr->getAttrPathStr(*evalState)).debugThrow(); std::vector changedFiles; std::vector conflictedFiles; @@ -928,10 +928,10 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand for (auto & s : changedFiles) args.push_back(s); runProgram("git", true, args); } - auto welcomeText = cursor->maybeGetAttr("welcomeText"); + auto welcomeText = cursor->maybeGetAttr(*evalState, "welcomeText"); if (welcomeText) { notice("\n"); - notice(renderMarkdownToTerminal(welcomeText->getString())); + notice(renderMarkdownToTerminal(welcomeText->getString(*evalState))); } if (!conflictedFiles.empty()) @@ -1152,7 +1152,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON { attrPath.push_back(attr); - auto visitor2 = visitor.getAttr(attr); + auto visitor2 = visitor.getAttr(*state, attr); try { if ((attrPath[0] == "apps" @@ -1161,7 +1161,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON || attrPath[0] == "legacyPackages" || attrPath[0] == "packages") && (attrPath.size() == 1 || attrPath.size() == 2)) { - for (const auto &subAttr : visitor2->getAttrs()) { + for (const auto &subAttr : visitor2->getAttrs(*state)) { if (hasContent(*visitor2, attrPath, subAttr)) { return true; } @@ -1175,7 +1175,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON || attrPath[0] == "nixosModules" || attrPath[0] == "overlays" )) { - for (const auto &subAttr : visitor2->getAttrs()) { + for (const auto &subAttr : visitor2->getAttrs(*state)) { if (hasContent(*visitor2, attrPath, subAttr)) { return true; } @@ -1217,14 +1217,14 @@ struct CmdFlakeShow : FlakeCommand, MixJSON if (!json) logger->cout("%s", headerPrefix); std::vector attrs; - for (const auto &attr : visitor.getAttrs()) { + for (const auto &attr : visitor.getAttrs(*state)) { if (hasContent(visitor, attrPath, attr)) attrs.push_back(attr); } for (const auto & [i, attr] : enumerate(attrs)) { bool last = i + 1 == attrs.size(); - auto visitor2 = visitor.getAttr(attr); + auto visitor2 = visitor.getAttr(*state, attr); auto attrPath2(attrPath); attrPath2.push_back(attr); auto j2 = visit(*visitor2, attrPath2, @@ -1236,11 +1236,11 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto showDerivation = [&]() { - auto name = visitor.getAttr("name")->getString(); + auto name = visitor.getAttr(*state, "name")->getString(*state); std::optional description; - if (auto aMeta = visitor.maybeGetAttr("meta")) { - if (auto aDescription = aMeta->maybeGetAttr("description")) - description = aDescription->getString(); + if (auto aMeta = visitor.maybeGetAttr(*state, "meta")) { + if (auto aDescription = aMeta->maybeGetAttr(*state, "description")) + description = aDescription->getString(*state); } if (json) { @@ -1324,7 +1324,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON logger->warn(fmt("%s omitted (use '--all-systems' to show)", concatStringsSep(".", attrPath))); } } else { - if (visitor.isDerivation()) + if (visitor.isDerivation(*state)) showDerivation(); else throw Error("expected a derivation"); @@ -1332,7 +1332,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON } else if (attrPath.size() > 0 && attrPath[0] == "hydraJobs") { - if (visitor.isDerivation()) + if (visitor.isDerivation(*state)) showDerivation(); else recurse(); @@ -1354,7 +1354,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON logger->warn(fmt("%s omitted (use '--all-systems' to show)", concatStringsSep(".", attrPath))); } } else { - if (visitor.isDerivation()) + if (visitor.isDerivation(*state)) showDerivation(); else if (attrPath.size() <= 2) // FIXME: handle recurseIntoAttrs @@ -1366,8 +1366,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON (attrPath.size() == 2 && attrPath[0] == "defaultApp") || (attrPath.size() == 3 && attrPath[0] == "apps")) { - auto aType = visitor.maybeGetAttr("type"); - if (!aType || aType->getString() != "app") + auto aType = visitor.maybeGetAttr(*state, "type"); + if (!aType || aType->getString(*state) != "app") state->errors.make("not an app definition").debugThrow(); if (json) { j.emplace("type", "app"); @@ -1380,7 +1380,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON (attrPath.size() == 1 && attrPath[0] == "defaultTemplate") || (attrPath.size() == 2 && attrPath[0] == "templates")) { - auto description = visitor.getAttr("description")->getString(); + auto description = visitor.getAttr(*state, "description")->getString(*state); if (json) { j.emplace("type", "template"); j.emplace("description", description); diff --git a/lix/nix/search.cc b/lix/nix/search.cc index b9845df7a..60f14a726 100644 --- a/lix/nix/search.cc +++ b/lix/nix/search.cc @@ -100,20 +100,20 @@ struct CmdSearch : InstallableCommand, MixJSON try { auto recurse = [&]() { - for (const auto & attr : cursor.getAttrs()) { - auto cursor2 = cursor.getAttr(attr); + for (const auto & attr : cursor.getAttrs(*state)) { + auto cursor2 = cursor.getAttr(*state, attr); auto attrPath2(attrPath); attrPath2.emplace_back(attr); visit(*cursor2, attrPath2, false); } }; - if (cursor.isDerivation()) { - DrvName name(cursor.getAttr("name")->getString()); + if (cursor.isDerivation(*state)) { + DrvName name(cursor.getAttr(*state, "name")->getString(*state)); - auto aMeta = cursor.maybeGetAttr("meta"); - auto aDescription = aMeta ? aMeta->maybeGetAttr("description") : nullptr; - auto description = aDescription ? aDescription->getString() : ""; + auto aMeta = cursor.maybeGetAttr(*state, "meta"); + auto aDescription = aMeta ? aMeta->maybeGetAttr(*state, "description") : nullptr; + auto description = aDescription ? aDescription->getString(*state) : ""; std::replace(description.begin(), description.end(), '\n', ' '); auto attrPath2 = concatStringsSep(".", attrPath); @@ -181,8 +181,8 @@ struct CmdSearch : InstallableCommand, MixJSON recurse(); else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) { - auto attr = cursor.maybeGetAttr("recurseForDerivations"); - if (attr && attr->getBool()) + auto attr = cursor.maybeGetAttr(*state, "recurseForDerivations"); + if (attr && attr->getBool(*state)) recurse(); } @@ -193,7 +193,7 @@ struct CmdSearch : InstallableCommand, MixJSON }; for (auto & cursor : installableValue->getCursors()) - visit(*cursor, cursor->getAttrPath(), true); + visit(*cursor, cursor->getAttrPath(*state), true); if (json) logger->cout("%s", *jsonOut);