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:
parent
8468dc65c7
commit
9ff702554d
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue