nix build (and others): Force re-evaluation of cached errors

Fixes #3872.

This is a bit hacky. Ideally we would automatically re-evaluate the
failed attribute iff we need to print the error message (so in
commands like 'nix search' we wouldn't re-evaluate because we're
suppressing errors).
This commit is contained in:
Eelco Dolstra 2020-08-07 14:46:00 +02:00
parent 2ffc058950
commit 3c75ddc16b
2 changed files with 14 additions and 9 deletions

View file

@ -405,7 +405,7 @@ Value & AttrCursor::forceValue()
return v; return v;
} }
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name) std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
{ {
if (root->db) { if (root->db) {
if (!cachedValue) if (!cachedValue)
@ -422,9 +422,12 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
if (attr) { if (attr) {
if (std::get_if<missing_t>(&attr->second)) if (std::get_if<missing_t>(&attr->second))
return nullptr; return nullptr;
else if (std::get_if<failed_t>(&attr->second)) else if (std::get_if<failed_t>(&attr->second)) {
throw EvalError("cached failure of attribute '%s'", getAttrPathStr(name)); if (forceErrors)
debug("reevaluating failed cached attribute '%s'");
else else
throw CachedEvalError("cached failure of attribute '%s'", getAttrPathStr(name));
} else
return std::make_shared<AttrCursor>(root, return std::make_shared<AttrCursor>(root,
std::make_pair(shared_from_this(), name), nullptr, std::move(attr)); std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
} }
@ -469,9 +472,9 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
return maybeGetAttr(root->state.symbols.create(name)); return maybeGetAttr(root->state.symbols.create(name));
} }
std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name) std::shared_ptr<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
{ {
auto p = maybeGetAttr(name); auto p = maybeGetAttr(name, forceErrors);
if (!p) if (!p)
throw Error("attribute '%s' does not exist", getAttrPathStr(name)); throw Error("attribute '%s' does not exist", getAttrPathStr(name));
return p; return p;
@ -600,7 +603,7 @@ bool AttrCursor::isDerivation()
StorePath AttrCursor::forceDerivation() StorePath AttrCursor::forceDerivation()
{ {
auto aDrvPath = getAttr(root->state.sDrvPath); auto aDrvPath = getAttr(root->state.sDrvPath, true);
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString()); auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) { if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
/* The eval cache contains 'drvPath', but the actual path has /* The eval cache contains 'drvPath', but the actual path has

View file

@ -9,6 +9,8 @@
namespace nix::eval_cache { namespace nix::eval_cache {
MakeError(CachedEvalError, EvalError);
class AttrDb; class AttrDb;
class AttrCursor; class AttrCursor;
@ -92,11 +94,11 @@ public:
std::string getAttrPathStr(Symbol name) const; std::string getAttrPathStr(Symbol name) const;
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name); std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name); std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
std::shared_ptr<AttrCursor> getAttr(Symbol name); std::shared_ptr<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
std::shared_ptr<AttrCursor> getAttr(std::string_view name); std::shared_ptr<AttrCursor> getAttr(std::string_view name);