diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcmd/installables.cc | 33 | ||||
-rw-r--r-- | src/libcmd/installables.hh | 2 | ||||
-rw-r--r-- | src/libexpr/eval-cache.cc | 54 | ||||
-rw-r--r-- | src/libexpr/eval-cache.hh | 6 | ||||
-rw-r--r-- | src/nix/app.cc | 2 | ||||
-rw-r--r-- | src/nix/flake.cc | 4 | ||||
-rw-r--r-- | src/nix/search.cc | 6 |
7 files changed, 91 insertions, 16 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index e3210d18d..e2ee47dea 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -440,10 +440,8 @@ DerivedPaths InstallableValue::toDerivedPaths() // Group by derivation, helps with .all in particular for (auto & drv : toDerivations()) { - auto outputName = drv.outputName; - if (outputName == "") - throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath)); - drvsToOutputs[drv.drvPath].insert(outputName); + for (auto & outputName : drv.outputsToInstall) + drvsToOutputs[drv.drvPath].insert(outputName); drvsToCopy.insert(drv.drvPath); } @@ -497,7 +495,13 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations auto drvPath = drvInfo.queryDrvPath(); if (!drvPath) throw Error("'%s' is not a derivation", what()); - res.push_back({ *drvPath, drvInfo.queryOutputName() }); + std::set<std::string> outputsToInstall; + for (auto & output : drvInfo.queryOutputs(false, true)) + outputsToInstall.insert(output.first); + res.push_back(DerivationInfo { + .drvPath = *drvPath, + .outputsToInstall = std::move(outputsToInstall) + }); } return res; @@ -598,9 +602,24 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF auto drvPath = attr->forceDerivation(); + std::set<std::string> outputsToInstall; + + if (auto aMeta = attr->maybeGetAttr(state->sMeta)) + if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall")) + for (auto & s : aOutputsToInstall->getListOfStrings()) + outputsToInstall.insert(s); + + if (outputsToInstall.empty()) + if (auto aOutputs = attr->maybeGetAttr(state->sOutputs)) + for (auto & s : aOutputs->getListOfStrings()) + outputsToInstall.insert(s); + + if (outputsToInstall.empty()) + outputsToInstall.insert("out"); + auto drvInfo = DerivationInfo { - std::move(drvPath), - attr->getAttr(state->sOutputName)->getString() + .drvPath = std::move(drvPath), + .outputsToInstall = std::move(outputsToInstall), }; return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)}; diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index de8b08525..3c2c33549 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -141,7 +141,7 @@ struct InstallableValue : Installable struct DerivationInfo { StorePath drvPath; - std::string outputName; + std::set<std::string> outputsToInstall; }; virtual std::vector<DerivationInfo> toDerivations() = 0; diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc index 6fb4bf266..3a92f2815 100644 --- a/src/libexpr/eval-cache.cc +++ b/src/libexpr/eval-cache.cc @@ -175,6 +175,24 @@ struct AttrDb }); } + AttrId setListOfStrings( + AttrKey key, + const std::vector<std::string> & l) + { + return doSQLite([&]() + { + auto state(_state->lock()); + + state->insertAttribute.use() + (key.first) + (symbols[key.second]) + (AttrType::ListOfStrings) + (concatStringsSep("\t", l)).exec(); + + return state->db.getLastInsertedRowId(); + }); + } + AttrId setPlaceholder(AttrKey key) { return doSQLite([&]() @@ -269,6 +287,8 @@ struct AttrDb } case AttrType::Bool: return {{rowId, queryAttribute.getInt(2) != 0}}; + case AttrType::ListOfStrings: + return {{rowId, tokenizeString<std::vector<std::string>>(queryAttribute.getStr(2), "\t")}}; case AttrType::Missing: return {{rowId, missing_t()}}; case AttrType::Misc: @@ -385,7 +405,7 @@ std::string AttrCursor::getAttrPathStr(Symbol name) const Value & AttrCursor::forceValue() { - debug("evaluating uncached attribute %s", getAttrPathStr()); + debug("evaluating uncached attribute '%s'", getAttrPathStr()); auto & v = getValue(); @@ -601,6 +621,38 @@ bool AttrCursor::getBool() return v.boolean; } +std::vector<std::string> AttrCursor::getListOfStrings() +{ + 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()); + return *l; + } else + throw TypeError("'%s' is not a list of strings", getAttrPathStr()); + } + } + + debug("evaluating uncached attribute '%s'", getAttrPathStr()); + + auto & v = getValue(); + root->state.forceValue(v, noPos); + + if (v.type() != nList) + throw TypeError("'%s' is not a list", getAttrPathStr()); + + std::vector<std::string> res; + + for (auto & elem : v.listItems()) + res.push_back(std::string(root->state.forceStringNoCtx(*elem))); + + cachedValue = {root->db->setListOfStrings(getKey(), res), res}; + + return res; +} + std::vector<Symbol> AttrCursor::getAttrs() { if (root->db) { diff --git a/src/libexpr/eval-cache.hh b/src/libexpr/eval-cache.hh index b0709ebc2..636e293ad 100644 --- a/src/libexpr/eval-cache.hh +++ b/src/libexpr/eval-cache.hh @@ -44,6 +44,7 @@ enum AttrType { Misc = 4, Failed = 5, Bool = 6, + ListOfStrings = 7, }; struct placeholder_t {}; @@ -61,7 +62,8 @@ typedef std::variant< missing_t, misc_t, failed_t, - bool + bool, + std::vector<std::string> > AttrValue; class AttrCursor : public std::enable_shared_from_this<AttrCursor> @@ -114,6 +116,8 @@ public: bool getBool(); + std::vector<std::string> getListOfStrings(); + std::vector<Symbol> getAttrs(); bool isDerivation(); diff --git a/src/nix/app.cc b/src/nix/app.cc index cce84d026..821964f86 100644 --- a/src/nix/app.cc +++ b/src/nix/app.cc @@ -89,7 +89,7 @@ UnresolvedApp Installable::toApp(EvalState & state) auto outputName = cursor->getAttr(state.sOutputName)->getString(); auto name = cursor->getAttr(state.sName)->getString(); auto aPname = cursor->maybeGetAttr("pname"); - auto aMeta = cursor->maybeGetAttr("meta"); + auto aMeta = cursor->maybeGetAttr(state.sMeta); auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr; auto mainProgram = aMainProgram diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 040c1c7af..6a34ca67b 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1015,8 +1015,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto name = visitor.getAttr(state->sName)->getString(); if (json) { std::optional<std::string> description; - if (auto aMeta = visitor.maybeGetAttr("meta")) { - if (auto aDescription = aMeta->maybeGetAttr("description")) + if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) { + if (auto aDescription = aMeta->maybeGetAttr(state->sDescription)) description = aDescription->getString(); } j.emplace("type", "derivation"); diff --git a/src/nix/search.cc b/src/nix/search.cc index 76451f810..87dc1c0de 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -93,10 +93,10 @@ struct CmdSearch : InstallableCommand, MixJSON }; if (cursor.isDerivation()) { - DrvName name(cursor.getAttr("name")->getString()); + DrvName name(cursor.getAttr(state->sName)->getString()); - auto aMeta = cursor.maybeGetAttr("meta"); - auto aDescription = aMeta ? aMeta->maybeGetAttr("description") : nullptr; + auto aMeta = cursor.maybeGetAttr(state->sMeta); + auto aDescription = aMeta ? aMeta->maybeGetAttr(state->sDescription) : nullptr; auto description = aDescription ? aDescription->getString() : ""; std::replace(description.begin(), description.end(), '\n', ' '); auto attrPath2 = concatStringsSep(".", attrPathS); |