diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index e17dbde84..b503d8f04 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -106,6 +106,21 @@ struct AttrDb return state->db.getLastInsertedRowId(); } + AttrId setBool( + AttrKey key, + bool b) + { + auto state(_state->lock()); + + state->insertAttribute.use() + (key.first) + (key.second) + (AttrType::Bool) + (b ? 1 : 0).exec(); + + return state->db.getLastInsertedRowId(); + } + AttrId setPlaceholder(AttrKey key) { auto state(_state->lock()); @@ -170,25 +185,30 @@ struct AttrDb auto rowId = (AttrType) queryAttribute.getInt(0); auto type = (AttrType) queryAttribute.getInt(1); - if (type == AttrType::Placeholder) - return {{rowId, placeholder_t()}}; - else if (type == AttrType::FullAttrs) { - // FIXME: expensive, should separate this out. - std::vector attrs; - auto queryAttributes(state->queryAttributes.use()(rowId)); - while (queryAttributes.next()) - attrs.push_back(symbols.create(queryAttributes.getStr(0))); - return {{rowId, attrs}}; - } else if (type == AttrType::String) { - return {{rowId, queryAttribute.getStr(2)}}; - } else if (type == AttrType::Missing) { - return {{rowId, missing_t()}}; - } else if (type == AttrType::Misc) { - return {{rowId, misc_t()}}; - } else if (type == AttrType::Failed) { - return {{rowId, failed_t()}}; - } else - throw Error("unexpected type in evaluation cache"); + switch (type) { + case AttrType::Placeholder: + return {{rowId, placeholder_t()}}; + case AttrType::FullAttrs: { + // FIXME: expensive, should separate this out. + std::vector attrs; + auto queryAttributes(state->queryAttributes.use()(rowId)); + while (queryAttributes.next()) + attrs.push_back(symbols.create(queryAttributes.getStr(0))); + return {{rowId, attrs}}; + } + case AttrType::String: + return {{rowId, queryAttribute.getStr(2)}}; + case AttrType::Bool: + return {{rowId, queryAttribute.getInt(2) != 0}}; + case AttrType::Missing: + return {{rowId, missing_t()}}; + case AttrType::Misc: + return {{rowId, misc_t()}}; + case AttrType::Failed: + return {{rowId, failed_t()}}; + default: + throw Error("unexpected type in evaluation cache"); + } } }; @@ -301,6 +321,8 @@ Value & AttrCursor::forceValue() if (root->db && (!cachedValue || std::get_if(&cachedValue->second))) { if (v.type == tString) cachedValue = {root->db->setString(getKey(), v.string.s), v.string.s}; + else if (v.type == tBool) + cachedValue = {root->db->setBool(getKey(), v.boolean), v.boolean}; else if (v.type == tAttrs) ; // FIXME: do something? else @@ -419,6 +441,28 @@ std::string AttrCursor::getString() return v.string.s; } +bool AttrCursor::getBool() +{ + if (root->db) { + if (!cachedValue) + cachedValue = root->db->getAttr(getKey(), root->state.symbols); + if (cachedValue && !std::get_if(&cachedValue->second)) { + if (auto b = std::get_if(&cachedValue->second)) { + debug("using cached Boolean attribute '%s'", getAttrPathStr()); + return *b; + } else + throw TypeError("'%s' is not a Boolean", getAttrPathStr()); + } + } + + auto & v = forceValue(); + + if (v.type != tBool) + throw TypeError("'%s' is not a Boolean", getAttrPathStr()); + + return v.boolean; +} + std::vector AttrCursor::getAttrs() { if (root->db) { diff --git a/src/libexpr/eval-cache.hh b/src/libexpr/eval-cache.hh index a2c21b6ea..9c47da315 100644 --- a/src/libexpr/eval-cache.hh +++ b/src/libexpr/eval-cache.hh @@ -41,6 +41,7 @@ enum AttrType { Missing = 3, Misc = 4, Failed = 5, + Bool = 6, }; struct placeholder_t {}; @@ -49,7 +50,7 @@ struct misc_t {}; struct failed_t {}; typedef uint64_t AttrId; typedef std::pair AttrKey; -typedef std::variant, std::string, placeholder_t, missing_t, misc_t, failed_t> AttrValue; +typedef std::variant, std::string, placeholder_t, missing_t, misc_t, failed_t, bool> AttrValue; class AttrCursor : public std::enable_shared_from_this { @@ -93,6 +94,8 @@ public: std::string getString(); + bool getBool(); + std::vector getAttrs(); bool isDerivation(); diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 95f52dc93..dd2c44c6d 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -352,6 +352,7 @@ EvalState::EvalState(const Strings & _searchPath, ref store) , sDescription(symbols.create("description")) , sSelf(symbols.create("self")) , sEpsilon(symbols.create("")) + , sRecurseForDerivations(symbols.create("recurseForDerivations")) , repair(NoRepair) , store(store) , baseEnv(allocEnv(128)) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 994954e44..9cf0030f9 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -75,7 +75,7 @@ public: sFile, sLine, sColumn, sFunctor, sToString, sRight, sWrong, sStructuredAttrs, sBuilder, sArgs, sOutputHash, sOutputHashAlgo, sOutputHashMode, - sDescription, sSelf, sEpsilon; + sDescription, sSelf, sEpsilon, sRecurseForDerivations; Symbol sDerivationNix; /* If set, force copying files to the Nix store even if they diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index ca9c547fa..a4937e722 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -348,7 +348,7 @@ static void getDerivations(EvalState & state, Value & vIn, should we recurse into it? => Only if it has a `recurseForDerivations = true' attribute. */ if (i->value->type == tAttrs) { - Bindings::iterator j = i->value->attrs->find(state.symbols.create("recurseForDerivations")); + Bindings::iterator j = i->value->attrs->find(state.sRecurseForDerivations); if (j != i->value->attrs->end() && state.forceBool(*j->value, *j->pos)) getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); } diff --git a/src/nix/search.cc b/src/nix/search.cc index 586bff5e5..fca49350a 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -165,6 +165,12 @@ struct CmdSearch : InstallableCommand, MixJSON || (attrPath[0] == "packages" && attrPath.size() <= 2)) recurse(); + else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) { + auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations); + if (attr && attr->getBool()) + recurse(); + } + } catch (EvalError & e) { if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages")) throw;