aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcmd/installables.cc33
-rw-r--r--src/libcmd/installables.hh2
-rw-r--r--src/libexpr/eval-cache.cc54
-rw-r--r--src/libexpr/eval-cache.hh6
-rw-r--r--src/nix/app.cc2
-rw-r--r--src/nix/flake.cc4
-rw-r--r--src/nix/search.cc6
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);