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
This commit is contained in:
eldritch horrors 2024-12-03 20:38:41 +01:00
parent 8468dc65c7
commit 9ff702554d
7 changed files with 159 additions and 161 deletions

View file

@ -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<NixInt::Inner> 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<std::string> 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<Value *, PosIdx> InstallableFlake::toValue()
{
return {&getCursor()->forceValue(), noPos};
return {&getCursor()->forceValue(*state), noPos};
}
std::vector<ref<eval_cache::AttrCursor>>
@ -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 {

View file

@ -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);
}

View file

@ -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<std::string> AttrCursor::getAttrPath() const
std::vector<std::string> 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<std::string> AttrCursor::getAttrPath(std::string_view name) const
std::vector<std::string> 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> AttrCursor::maybeGetAttr(const std::string & name)
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(EvalState & state, const std::string & name)
{
if (root->db) {
if (!cachedValue)
@ -488,7 +487,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(const std::string & name)
if (std::get_if<missing_t>(&attr->second))
return nullptr;
else if (std::get_if<failed_t>(&attr->second)) {
debug("reevaluating failed cached attribute '%s'", getAttrPathStr(name));
debug("reevaluating failed cached attribute '%s'", getAttrPathStr(state, name));
} else
return std::make_shared<AttrCursor>(root,
std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
@ -501,13 +500,13 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(const std::string & name)
}
}
auto & v = forceValue();
auto & v = forceValue(state);
if (v.type() != nAttrs)
return nullptr;
//errors.make<TypeError>("'%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> AttrCursor::maybeGetAttr(const std::string & name)
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
}
ref<AttrCursor> AttrCursor::getAttr(const std::string & name)
ref<AttrCursor> 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<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const Strings & attrPath)
OrSuggestions<ref<AttrCursor>> 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<ref<AttrCursor>>::failed(suggestions);
}
res = child;
@ -551,30 +550,30 @@ OrSuggestions<ref<AttrCursor>> 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<placeholder_t>(&cachedValue->second)) {
if (auto s = std::get_if<string_t>(&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<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%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<TypeError>("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow();
state.errors.make<TypeError>("'%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<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%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<TypeError>("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow();
state.errors.make<TypeError>("'%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<placeholder_t>(&cachedValue->second)) {
if (auto b = std::get_if<bool>(&cachedValue->second)) {
debug("using cached Boolean attribute '%s'", getAttrPathStr());
debug("using cached Boolean attribute '%s'", getAttrPathStr(state));
return *b;
} else
root->state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue();
auto & v = forceValue(state);
if (v.type() != nBool)
root->state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%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<placeholder_t>(&cachedValue->second)) {
if (auto i = std::get_if<int_t>(&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<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue();
auto & v = forceValue(state);
if (v.type() != nInt)
root->state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
return v.integer;
}
std::vector<std::string> AttrCursor::getListOfStrings()
std::vector<std::string> AttrCursor::getListOfStrings(EvalState & state)
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto l = std::get_if<std::vector<std::string>>(&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<TypeError>("'%s' is not a list of strings", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%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<TypeError>("'%s' is not a list", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%s' is not a list", getAttrPathStr(state)).debugThrow();
std::vector<std::string> 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<std::string> AttrCursor::getListOfStrings()
return res;
}
std::vector<std::string> AttrCursor::getAttrs()
std::vector<std::string> AttrCursor::getAttrs(EvalState & state)
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto attrs = std::get_if<fullattr_t>(&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<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue();
auto & v = forceValue(state);
if (v.type() != nAttrs)
root->state.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
state.errors.make<TypeError>("'%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<std::string> 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;
}

View file

@ -40,7 +40,6 @@ class EvalCache : public std::enable_shared_from_this<EvalCache>
friend class AttrCursor;
std::shared_ptr<AttrDb> db;
EvalState & state;
RootLoader rootLoader;
RootValue value;
@ -102,7 +101,7 @@ class AttrCursor : public std::enable_shared_from_this<AttrCursor>
AttrKey getKey();
Value & getValue();
Value & getValue(EvalState & state);
public:
@ -112,46 +111,46 @@ public:
Value * value = nullptr,
std::optional<std::pair<AttrId, AttrValue>> && cachedValue = {});
std::vector<std::string> getAttrPath() const;
std::vector<std::string> getAttrPath(EvalState & state) const;
std::vector<std::string> getAttrPath(std::string_view name) const;
std::vector<std::string> 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<AttrCursor> maybeGetAttr(const std::string & name);
std::shared_ptr<AttrCursor> maybeGetAttr(EvalState & state, const std::string & name);
ref<AttrCursor> getAttr(const std::string & name);
ref<AttrCursor> 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<ref<AttrCursor>> findAlongAttrPath(const Strings & attrPath);
OrSuggestions<ref<AttrCursor>> 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<std::string> getListOfStrings();
std::vector<std::string> getListOfStrings(EvalState & state);
std::vector<std::string> getAttrs();
std::vector<std::string> 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);
};
}

View file

@ -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<DerivedPath> 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

View file

@ -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<TypeError>(
"'%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<Path> changedFiles;
std::vector<Path> 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<std::string> 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<std::string> 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<EvalError>("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);

View file

@ -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);