diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index ea3319f99..0042eebe0 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -418,6 +418,14 @@ Value & AttrCursor::getValue() return **_value; } +void AttrCursor::fetchCachedValue() +{ + if (!cachedValue) + cachedValue = root->db->getAttr(getKey()); + if (cachedValue && std::get_if(&cachedValue->second) && parent) + throw CachedEvalError(ref(parent->first), parent->second); +} + std::vector AttrCursor::getAttrPath() const { if (parent) { @@ -494,8 +502,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol name) std::shared_ptr AttrCursor::maybeGetAttr(Symbol name) { if (root->db) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue) { if (auto attrs = std::get_if>(&cachedValue->second)) { @@ -585,8 +592,7 @@ OrSuggestions> AttrCursor::findAlongAttrPath(const std::vectordb) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto s = std::get_if(&cachedValue->second)) { debug("using cached string attribute '%s'", getAttrPathStr()); @@ -607,8 +613,7 @@ std::string AttrCursor::getString() string_t AttrCursor::getStringWithContext() { if (root->db) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto s = std::get_if(&cachedValue->second)) { bool valid = true; @@ -654,8 +659,7 @@ string_t AttrCursor::getStringWithContext() bool AttrCursor::getBool() { if (root->db) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto b = std::get_if(&cachedValue->second)) { debug("using cached Boolean attribute '%s'", getAttrPathStr()); @@ -676,8 +680,7 @@ bool AttrCursor::getBool() NixInt AttrCursor::getInt() { if (root->db) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto i = std::get_if(&cachedValue->second)) { debug("using cached integer attribute '%s'", getAttrPathStr()); @@ -698,8 +701,7 @@ NixInt AttrCursor::getInt() std::vector AttrCursor::getListOfStrings() { if (root->db) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto l = std::get_if>(&cachedValue->second)) { debug("using cached list of strings attribute '%s'", getAttrPathStr()); @@ -731,8 +733,7 @@ std::vector AttrCursor::getListOfStrings() std::vector AttrCursor::getAttrs() { if (root->db) { - if (!cachedValue) - cachedValue = root->db->getAttr(getKey()); + fetchCachedValue(); if (cachedValue && !std::get_if(&cachedValue->second)) { if (auto attrs = std::get_if>(&cachedValue->second)) { debug("using cached attrset attribute '%s'", getAttrPathStr()); diff --git a/src/libexpr/eval-cache.hh b/src/libexpr/eval-cache.hh index b1911e3a4..d37303b31 100644 --- a/src/libexpr/eval-cache.hh +++ b/src/libexpr/eval-cache.hh @@ -99,6 +99,14 @@ class AttrCursor : public std::enable_shared_from_this Value & getValue(); + /** + * If `cachedValue` is unset, try to initialize it from the + * database. It is not an error if it does not exist. Throw a + * `CachedEvalError` exception if it does exist but has type + * `AttrType::Failed`. + */ + void fetchCachedValue(); + public: AttrCursor(