nix search: Search legacyPackages recursively

This commit is contained in:
Eelco Dolstra 2020-04-27 16:29:26 +02:00
parent 0469795978
commit b4e23dcd9e
6 changed files with 76 additions and 22 deletions

View file

@ -106,6 +106,21 @@ struct AttrDb
return state->db.getLastInsertedRowId(); 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) AttrId setPlaceholder(AttrKey key)
{ {
auto state(_state->lock()); auto state(_state->lock());
@ -170,26 +185,31 @@ struct AttrDb
auto rowId = (AttrType) queryAttribute.getInt(0); auto rowId = (AttrType) queryAttribute.getInt(0);
auto type = (AttrType) queryAttribute.getInt(1); auto type = (AttrType) queryAttribute.getInt(1);
if (type == AttrType::Placeholder) switch (type) {
case AttrType::Placeholder:
return {{rowId, placeholder_t()}}; return {{rowId, placeholder_t()}};
else if (type == AttrType::FullAttrs) { case AttrType::FullAttrs: {
// FIXME: expensive, should separate this out. // FIXME: expensive, should separate this out.
std::vector<Symbol> attrs; std::vector<Symbol> attrs;
auto queryAttributes(state->queryAttributes.use()(rowId)); auto queryAttributes(state->queryAttributes.use()(rowId));
while (queryAttributes.next()) while (queryAttributes.next())
attrs.push_back(symbols.create(queryAttributes.getStr(0))); attrs.push_back(symbols.create(queryAttributes.getStr(0)));
return {{rowId, attrs}}; return {{rowId, attrs}};
} else if (type == AttrType::String) { }
case AttrType::String:
return {{rowId, queryAttribute.getStr(2)}}; return {{rowId, queryAttribute.getStr(2)}};
} else if (type == AttrType::Missing) { case AttrType::Bool:
return {{rowId, queryAttribute.getInt(2) != 0}};
case AttrType::Missing:
return {{rowId, missing_t()}}; return {{rowId, missing_t()}};
} else if (type == AttrType::Misc) { case AttrType::Misc:
return {{rowId, misc_t()}}; return {{rowId, misc_t()}};
} else if (type == AttrType::Failed) { case AttrType::Failed:
return {{rowId, failed_t()}}; return {{rowId, failed_t()}};
} else default:
throw Error("unexpected type in evaluation cache"); throw Error("unexpected type in evaluation cache");
} }
}
}; };
EvalCache::EvalCache( EvalCache::EvalCache(
@ -301,6 +321,8 @@ Value & AttrCursor::forceValue()
if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) { if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) {
if (v.type == tString) if (v.type == tString)
cachedValue = {root->db->setString(getKey(), v.string.s), v.string.s}; 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) else if (v.type == tAttrs)
; // FIXME: do something? ; // FIXME: do something?
else else
@ -419,6 +441,28 @@ std::string AttrCursor::getString()
return v.string.s; 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<placeholder_t>(&cachedValue->second)) {
if (auto b = std::get_if<bool>(&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<Symbol> AttrCursor::getAttrs() std::vector<Symbol> AttrCursor::getAttrs()
{ {
if (root->db) { if (root->db) {

View file

@ -41,6 +41,7 @@ enum AttrType {
Missing = 3, Missing = 3,
Misc = 4, Misc = 4,
Failed = 5, Failed = 5,
Bool = 6,
}; };
struct placeholder_t {}; struct placeholder_t {};
@ -49,7 +50,7 @@ struct misc_t {};
struct failed_t {}; struct failed_t {};
typedef uint64_t AttrId; typedef uint64_t AttrId;
typedef std::pair<AttrId, Symbol> AttrKey; typedef std::pair<AttrId, Symbol> AttrKey;
typedef std::variant<std::vector<Symbol>, std::string, placeholder_t, missing_t, misc_t, failed_t> AttrValue; typedef std::variant<std::vector<Symbol>, std::string, placeholder_t, missing_t, misc_t, failed_t, bool> AttrValue;
class AttrCursor : public std::enable_shared_from_this<AttrCursor> class AttrCursor : public std::enable_shared_from_this<AttrCursor>
{ {
@ -93,6 +94,8 @@ public:
std::string getString(); std::string getString();
bool getBool();
std::vector<Symbol> getAttrs(); std::vector<Symbol> getAttrs();
bool isDerivation(); bool isDerivation();

View file

@ -352,6 +352,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
, sDescription(symbols.create("description")) , sDescription(symbols.create("description"))
, sSelf(symbols.create("self")) , sSelf(symbols.create("self"))
, sEpsilon(symbols.create("")) , sEpsilon(symbols.create(""))
, sRecurseForDerivations(symbols.create("recurseForDerivations"))
, repair(NoRepair) , repair(NoRepair)
, store(store) , store(store)
, baseEnv(allocEnv(128)) , baseEnv(allocEnv(128))

View file

@ -75,7 +75,7 @@ public:
sFile, sLine, sColumn, sFunctor, sToString, sFile, sLine, sColumn, sFunctor, sToString,
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs, sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
sOutputHash, sOutputHashAlgo, sOutputHashMode, sOutputHash, sOutputHashAlgo, sOutputHashMode,
sDescription, sSelf, sEpsilon; sDescription, sSelf, sEpsilon, sRecurseForDerivations;
Symbol sDerivationNix; Symbol sDerivationNix;
/* If set, force copying files to the Nix store even if they /* If set, force copying files to the Nix store even if they

View file

@ -348,7 +348,7 @@ static void getDerivations(EvalState & state, Value & vIn,
should we recurse into it? => Only if it has a should we recurse into it? => Only if it has a
`recurseForDerivations = true' attribute. */ `recurseForDerivations = true' attribute. */
if (i->value->type == tAttrs) { 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)) if (j != i->value->attrs->end() && state.forceBool(*j->value, *j->pos))
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
} }

View file

@ -165,6 +165,12 @@ struct CmdSearch : InstallableCommand, MixJSON
|| (attrPath[0] == "packages" && attrPath.size() <= 2)) || (attrPath[0] == "packages" && attrPath.size() <= 2))
recurse(); recurse();
else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations);
if (attr && attr->getBool())
recurse();
}
} catch (EvalError & e) { } catch (EvalError & e) {
if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages")) if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages"))
throw; throw;