Use BuildableReq for buildPaths and ensurePath

This avoids an ambiguity where the `StorePathWithOutputs { drvPath, {}
}` could mean "build `brvPath`" or "substitute `drvPath`" depending on
context.

It also brings the internals closer in line to the new CLI, by
generalizing the `Buildable` type is used there and makes that
distinction already.

In doing so, relegate `StorePathWithOutputs` to being a type just for
backwards compatibility (CLI and RPC).
This commit is contained in:
John Ericson 2021-03-02 03:50:41 +00:00
parent 32f4454b9f
commit 255d145ba7
31 changed files with 364 additions and 126 deletions

View file

@ -679,19 +679,20 @@ Buildables build(ref<Store> store, Realise mode,
Buildables buildables; Buildables buildables;
std::vector<StorePathWithOutputs> pathsToBuild; std::vector<BuildableReq> pathsToBuild;
for (auto & i : installables) { for (auto & i : installables) {
for (auto & b : i->toBuildables()) { for (auto & b : i->toBuildables()) {
std::visit(overloaded { std::visit(overloaded {
[&](BuildableOpaque bo) { [&](BuildableOpaque bo) {
pathsToBuild.push_back({bo.path}); pathsToBuild.push_back(bo);
}, },
[&](BuildableFromDrv bfd) { [&](BuildableFromDrv bfd) {
StringSet outputNames; StringSet outputNames;
for (auto & output : bfd.outputs) for (auto & output : bfd.outputs)
outputNames.insert(output.first); outputNames.insert(output.first);
pathsToBuild.push_back({bfd.drvPath, outputNames}); pathsToBuild.push_back(
BuildableReqFromDrv{bfd.drvPath, outputNames});
}, },
}, b); }, b);
buildables.push_back(std::move(b)); buildables.push_back(std::move(b));

View file

@ -2,6 +2,7 @@
#include "util.hh" #include "util.hh"
#include "eval-inline.hh" #include "eval-inline.hh"
#include "store-api.hh" #include "store-api.hh"
#include "path-with-outputs.hh"
#include <cstring> #include <cstring>
#include <regex> #include <regex>

View file

@ -35,7 +35,7 @@ InvalidPathError::InvalidPathError(const Path & path) :
void EvalState::realiseContext(const PathSet & context) void EvalState::realiseContext(const PathSet & context)
{ {
std::vector<StorePathWithOutputs> drvs; std::vector<BuildableReqFromDrv> drvs;
for (auto & i : context) { for (auto & i : context) {
auto [ctxS, outputName] = decodeContext(i); auto [ctxS, outputName] = decodeContext(i);
@ -43,7 +43,7 @@ void EvalState::realiseContext(const PathSet & context)
if (!store->isValidPath(ctx)) if (!store->isValidPath(ctx))
throw InvalidPathError(store->printStorePath(ctx)); throw InvalidPathError(store->printStorePath(ctx));
if (!outputName.empty() && ctx.isDerivation()) { if (!outputName.empty() && ctx.isDerivation()) {
drvs.push_back(StorePathWithOutputs{ctx, {outputName}}); drvs.push_back({ctx, {outputName}});
} }
} }
@ -51,14 +51,16 @@ void EvalState::realiseContext(const PathSet & context)
if (!evalSettings.enableImportFromDerivation) if (!evalSettings.enableImportFromDerivation)
throw EvalError("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false", throw EvalError("attempted to realize '%1%' during evaluation but 'allow-import-from-derivation' is false",
store->printStorePath(drvs.begin()->path)); store->printStorePath(drvs.begin()->drvPath));
/* For performance, prefetch all substitute info. */ /* For performance, prefetch all substitute info. */
StorePathSet willBuild, willSubstitute, unknown; StorePathSet willBuild, willSubstitute, unknown;
uint64_t downloadSize, narSize; uint64_t downloadSize, narSize;
store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize); std::vector<BuildableReq> buildReqs;
for (auto & d : drvs) buildReqs.emplace_back(BuildableReq { d });
store->queryMissing(buildReqs, willBuild, willSubstitute, unknown, downloadSize, narSize);
store->buildPaths(drvs); store->buildPaths(buildReqs);
/* Add the output of this derivations to the allowed /* Add the output of this derivations to the allowed
paths. */ paths. */

View file

@ -36,7 +36,7 @@ void printGCWarning()
} }
void printMissing(ref<Store> store, const std::vector<StorePathWithOutputs> & paths, Verbosity lvl) void printMissing(ref<Store> store, const std::vector<BuildableReq> & paths, Verbosity lvl)
{ {
uint64_t downloadSize, narSize; uint64_t downloadSize, narSize;
StorePathSet willBuild, willSubstitute, unknown; StorePathSet willBuild, willSubstitute, unknown;

View file

@ -4,6 +4,7 @@
#include "args.hh" #include "args.hh"
#include "common-args.hh" #include "common-args.hh"
#include "path.hh" #include "path.hh"
#include "buildable.hh"
#include <signal.h> #include <signal.h>
@ -42,7 +43,7 @@ struct StorePathWithOutputs;
void printMissing( void printMissing(
ref<Store> store, ref<Store> store,
const std::vector<StorePathWithOutputs> & paths, const std::vector<BuildableReq> & paths,
Verbosity lvl = lvlInfo); Verbosity lvl = lvlInfo);
void printMissing(ref<Store> store, const StorePathSet & willBuild, void printMissing(ref<Store> store, const StorePathSet & willBuild,

View file

@ -73,7 +73,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath,
state = &DerivationGoal::getDerivation; state = &DerivationGoal::getDerivation;
name = fmt( name = fmt(
"building of '%s' from .drv file", "building of '%s' from .drv file",
StorePathWithOutputs { drvPath, wantedOutputs }.to_string(worker.store)); to_string(worker.store, BuildableReqFromDrv { drvPath, wantedOutputs }));
trace("created"); trace("created");
mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.expectedBuilds); mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.expectedBuilds);
@ -94,7 +94,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation
state = &DerivationGoal::haveDerivation; state = &DerivationGoal::haveDerivation;
name = fmt( name = fmt(
"building of '%s' from in-memory derivation", "building of '%s' from in-memory derivation",
StorePathWithOutputs { drvPath, drv.outputNames() }.to_string(worker.store)); to_string(worker.store, BuildableReqFromDrv { drvPath, drv.outputNames() }));
trace("created"); trace("created");
mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.expectedBuilds); mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.expectedBuilds);

View file

@ -6,16 +6,20 @@
namespace nix { namespace nix {
void Store::buildPaths(const std::vector<StorePathWithOutputs> & drvPaths, BuildMode buildMode) void Store::buildPaths(const std::vector<BuildableReq> & reqs, BuildMode buildMode)
{ {
Worker worker(*this); Worker worker(*this);
Goals goals; Goals goals;
for (auto & path : drvPaths) { for (auto & br : reqs) {
if (path.path.isDerivation()) std::visit(overloaded {
goals.insert(worker.makeDerivationGoal(path.path, path.outputs, buildMode)); [&](BuildableReqFromDrv bfd) {
else goals.insert(worker.makeDerivationGoal(bfd.drvPath, bfd.outputs, buildMode));
goals.insert(worker.makePathSubstitutionGoal(path.path, buildMode == bmRepair ? Repair : NoRepair)); },
[&](BuildableOpaque bo) {
goals.insert(worker.makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair));
},
}, br);
} }
worker.run(goals); worker.run(goals);

View file

@ -1190,6 +1190,26 @@ void LocalDerivationGoal::writeStructuredAttrs()
chownToBuilder(tmpDir + "/.attrs.sh"); chownToBuilder(tmpDir + "/.attrs.sh");
} }
static StorePath pathPartOfReq(const BuildableReq & req)
{
return std::visit(overloaded {
[&](BuildableOpaque bo) {
return bo.path;
},
[&](BuildableReqFromDrv bfd) {
return bfd.drvPath;
},
}, req);
}
bool LocalDerivationGoal::isAllowed(const BuildableReq & req)
{
return this->isAllowed(pathPartOfReq(req));
}
struct RestrictedStoreConfig : virtual LocalFSStoreConfig struct RestrictedStoreConfig : virtual LocalFSStoreConfig
{ {
using LocalFSStoreConfig::LocalFSStoreConfig; using LocalFSStoreConfig::LocalFSStoreConfig;
@ -1312,25 +1332,27 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
// an allowed derivation // an allowed derivation
{ throw Error("queryRealisation"); } { throw Error("queryRealisation"); }
void buildPaths(const std::vector<StorePathWithOutputs> & paths, BuildMode buildMode) override void buildPaths(const std::vector<BuildableReq> & paths, BuildMode buildMode) override
{ {
if (buildMode != bmNormal) throw Error("unsupported build mode"); if (buildMode != bmNormal) throw Error("unsupported build mode");
StorePathSet newPaths; StorePathSet newPaths;
for (auto & path : paths) { for (auto & req : paths) {
if (!goal.isAllowed(path.path)) if (!goal.isAllowed(req))
throw InvalidPath("cannot build unknown path '%s' in recursive Nix", printStorePath(path.path)); throw InvalidPath("cannot build '%s' in recursive Nix because path is unknown", to_string(*next, req));
} }
next->buildPaths(paths, buildMode); next->buildPaths(paths, buildMode);
for (auto & path : paths) { for (auto & path : paths) {
if (!path.path.isDerivation()) continue; auto p = std::get_if<BuildableReqFromDrv>(&path);
auto outputs = next->queryDerivationOutputMap(path.path); if (!p) continue;
for (auto & output : outputs) auto & bfd = *p;
if (wantOutput(output.first, path.outputs)) auto outputs = next->queryDerivationOutputMap(bfd.drvPath);
newPaths.insert(output.second); for (auto & [outputName, outputPath] : outputs)
if (wantOutput(outputName, bfd.outputs))
newPaths.insert(outputPath);
} }
StorePathSet closure; StorePathSet closure;
@ -1358,7 +1380,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
void addSignatures(const StorePath & storePath, const StringSet & sigs) override void addSignatures(const StorePath & storePath, const StringSet & sigs) override
{ unsupported("addSignatures"); } { unsupported("addSignatures"); }
void queryMissing(const std::vector<StorePathWithOutputs> & targets, void queryMissing(const std::vector<BuildableReq> & targets,
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
uint64_t & downloadSize, uint64_t & narSize) override uint64_t & downloadSize, uint64_t & narSize) override
{ {
@ -1366,12 +1388,12 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
client about what paths will be built/substituted or are client about what paths will be built/substituted or are
already present. Probably not a big deal. */ already present. Probably not a big deal. */
std::vector<StorePathWithOutputs> allowed; std::vector<BuildableReq> allowed;
for (auto & path : targets) { for (auto & req : targets) {
if (goal.isAllowed(path.path)) if (goal.isAllowed(req))
allowed.emplace_back(path); allowed.emplace_back(req);
else else
unknown.insert(path.path); unknown.insert(pathPartOfReq(req));
} }
next->queryMissing(allowed, willBuild, willSubstitute, next->queryMissing(allowed, willBuild, willSubstitute,

View file

@ -116,6 +116,7 @@ struct LocalDerivationGoal : public DerivationGoal
{ {
return inputPaths.count(path) || addedPaths.count(path); return inputPaths.count(path) || addedPaths.count(path);
} }
bool isAllowed(const BuildableReq & req);
friend struct RestrictedStore; friend struct RestrictedStore;

View file

@ -226,14 +226,14 @@ void Worker::waitForAWhile(GoalPtr goal)
void Worker::run(const Goals & _topGoals) void Worker::run(const Goals & _topGoals)
{ {
std::vector<nix::StorePathWithOutputs> topPaths; std::vector<nix::BuildableReq> topPaths;
for (auto & i : _topGoals) { for (auto & i : _topGoals) {
topGoals.insert(i); topGoals.insert(i);
if (auto goal = dynamic_cast<DerivationGoal *>(i.get())) { if (auto goal = dynamic_cast<DerivationGoal *>(i.get())) {
topPaths.push_back({goal->drvPath, goal->wantedOutputs}); topPaths.push_back(BuildableReqFromDrv{goal->drvPath, goal->wantedOutputs});
} else if (auto goal = dynamic_cast<PathSubstitutionGoal *>(i.get())) { } else if (auto goal = dynamic_cast<PathSubstitutionGoal *>(i.get())) {
topPaths.push_back({goal->storePath}); topPaths.push_back(BuildableOpaque{goal->storePath});
} }
} }

View file

@ -11,6 +11,7 @@ nlohmann::json BuildableOpaque::toJSON(ref<Store> store) const {
return res; return res;
} }
template<>
nlohmann::json BuildableFromDrv::toJSON(ref<Store> store) const { nlohmann::json BuildableFromDrv::toJSON(ref<Store> store) const {
nlohmann::json res; nlohmann::json res;
res["drvPath"] = store->printStorePath(drvPath); res["drvPath"] = store->printStorePath(drvPath);
@ -30,4 +31,50 @@ nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store)
return res; return res;
} }
std::string BuildableOpaque::to_string(const Store & store) const {
return store.printStorePath(path);
}
template<>
std::string BuildableReqFromDrv::to_string(const Store & store) const {
return store.printStorePath(drvPath)
+ "!"
+ (outputs.empty() ? std::string { "*" } : concatStringsSep(",", outputs));
}
std::string to_string(const Store & store, const BuildableReq & req)
{
return std::visit(
[&](const auto & req) { return req.to_string(store); },
req);
}
BuildableOpaque BuildableOpaque::parse(const Store & store, std::string_view s)
{
return {store.parseStorePath(s)};
}
template<>
BuildableReqFromDrv BuildableReqFromDrv::parse(const Store & store, std::string_view s)
{
size_t n = s.find("!");
assert(n != s.npos);
auto drvPath = store.parseStorePath(s.substr(0, n));
auto outputsS = s.substr(n + 1);
std::set<string> outputs;
if (outputsS != "*")
outputs = tokenizeString<std::set<string>>(outputsS);
return {drvPath, outputs};
}
BuildableReq parseBuildableReq(const Store & store, std::string_view s)
{
size_t n = s.find("!");
return n == s.npos
? (BuildableReq) BuildableOpaque::parse(store, s)
: (BuildableReq) BuildableReqFromDrv::parse(store, s);
}
} }

View file

@ -2,6 +2,7 @@
#include "util.hh" #include "util.hh"
#include "path.hh" #include "path.hh"
#include "path.hh"
#include <optional> #include <optional>
@ -13,19 +14,37 @@ class Store;
struct BuildableOpaque { struct BuildableOpaque {
StorePath path; StorePath path;
nlohmann::json toJSON(ref<Store> store) const; nlohmann::json toJSON(ref<Store> store) const;
std::string to_string(const Store & store) const;
static BuildableOpaque parse(const Store & store, std::string_view);
}; };
struct BuildableFromDrv { template<typename Outputs>
struct BuildableForFromDrv {
StorePath drvPath; StorePath drvPath;
std::map<std::string, std::optional<StorePath>> outputs; Outputs outputs;
nlohmann::json toJSON(ref<Store> store) const; nlohmann::json toJSON(ref<Store> store) const;
std::string to_string(const Store & store) const;
static BuildableForFromDrv<Outputs> parse(const Store & store, std::string_view);
}; };
typedef std::variant< template <typename Outputs>
using BuildableFor = std::variant<
BuildableOpaque, BuildableOpaque,
BuildableFromDrv BuildableForFromDrv<Outputs>
> Buildable; >;
typedef BuildableForFromDrv<std::set<std::string>> BuildableReqFromDrv;
typedef BuildableFor<std::set<std::string>> BuildableReq;
std::string to_string(const Store & store, const BuildableReq &);
BuildableReq parseBuildableReq(const Store & store, std::string_view);
typedef BuildableForFromDrv<std::map<std::string, std::optional<StorePath>>> BuildableFromDrv;
typedef BuildableFor<std::map<std::string, std::optional<StorePath>>> Buildable;
typedef std::vector<Buildable> Buildables; typedef std::vector<Buildable> Buildables;

View file

@ -2,6 +2,7 @@
#include "monitor-fd.hh" #include "monitor-fd.hh"
#include "worker-protocol.hh" #include "worker-protocol.hh"
#include "store-api.hh" #include "store-api.hh"
#include "path-with-outputs.hh"
#include "finally.hh" #include "finally.hh"
#include "affinity.hh" #include "affinity.hh"
#include "archive.hh" #include "archive.hh"
@ -259,6 +260,18 @@ static void writeValidPathInfo(
} }
} }
static std::vector<BuildableReq> readBuildableReqs(Store & store, unsigned int clientVersion, Source & from)
{
std::vector<BuildableReq> reqs;
if (GET_PROTOCOL_MINOR(clientVersion) >= 29) {
reqs = worker_proto::read(store, from, Phantom<std::vector<BuildableReq>> {});
} else {
for (auto & s : readStrings<Strings>(from))
reqs.push_back(parsePathWithOutputs(store, s).toBuildableReq());
}
return reqs;
}
static void performOp(TunnelLogger * logger, ref<Store> store, static void performOp(TunnelLogger * logger, ref<Store> store,
TrustedFlag trusted, RecursiveFlag recursive, unsigned int clientVersion, TrustedFlag trusted, RecursiveFlag recursive, unsigned int clientVersion,
Source & from, BufferedSink & to, unsigned int op) Source & from, BufferedSink & to, unsigned int op)
@ -493,9 +506,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
} }
case wopBuildPaths: { case wopBuildPaths: {
std::vector<StorePathWithOutputs> drvs; auto drvs = readBuildableReqs(*store, clientVersion, from);
for (auto & s : readStrings<Strings>(from))
drvs.push_back(parsePathWithOutputs(*store, s));
BuildMode mode = bmNormal; BuildMode mode = bmNormal;
if (GET_PROTOCOL_MINOR(clientVersion) >= 15) { if (GET_PROTOCOL_MINOR(clientVersion) >= 15) {
mode = (BuildMode) readInt(from); mode = (BuildMode) readInt(from);
@ -859,9 +870,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
} }
case wopQueryMissing: { case wopQueryMissing: {
std::vector<StorePathWithOutputs> targets; auto targets = readBuildableReqs(*store, clientVersion, from);
for (auto & s : readStrings<Strings>(from))
targets.push_back(parsePathWithOutputs(*store, s));
logger->startWork(); logger->startWork();
StorePathSet willBuild, willSubstitute, unknown; StorePathSet willBuild, willSubstitute, unknown;
uint64_t downloadSize, narSize; uint64_t downloadSize, narSize;

View file

@ -3,6 +3,7 @@
#include "remote-store.hh" #include "remote-store.hh"
#include "serve-protocol.hh" #include "serve-protocol.hh"
#include "store-api.hh" #include "store-api.hh"
#include "path-with-outputs.hh"
#include "worker-protocol.hh" #include "worker-protocol.hh"
#include "ssh.hh" #include "ssh.hh"
#include "derivations.hh" #include "derivations.hh"
@ -266,14 +267,23 @@ public:
return status; return status;
} }
void buildPaths(const std::vector<StorePathWithOutputs> & drvPaths, BuildMode buildMode) override void buildPaths(const std::vector<BuildableReq> & drvPaths, BuildMode buildMode) override
{ {
auto conn(connections->get()); auto conn(connections->get());
conn->to << cmdBuildPaths; conn->to << cmdBuildPaths;
Strings ss; Strings ss;
for (auto & p : drvPaths) for (auto & p : drvPaths) {
ss.push_back(p.to_string(*this)); auto sOrDrvPath = StorePathWithOutputs::tryFromBuildableReq(p);
std::visit(overloaded {
[&](StorePathWithOutputs s) {
ss.push_back(s.to_string(*this));
},
[&](StorePath drvPath) {
throw Error("wanted to fetch '%s' but the legacy ssh protocol doesn't support merely substituting drv files via the build paths command. It would build them instead. Try using ssh-ng://", printStorePath(drvPath));
},
}, sOrDrvPath);
}
conn->to << ss; conn->to << ss;
putBuildSettings(*conn); putBuildSettings(*conn);

View file

@ -117,7 +117,7 @@ std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv)
return std::nullopt; return std::nullopt;
} }
void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets, void Store::queryMissing(const std::vector<BuildableReq> & targets,
StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_, StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_,
uint64_t & downloadSize_, uint64_t & narSize_) uint64_t & downloadSize_, uint64_t & narSize_)
{ {
@ -145,7 +145,7 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
Sync<State> state_(State{{}, unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_}); Sync<State> state_(State{{}, unknown_, willSubstitute_, willBuild_, downloadSize_, narSize_});
std::function<void(StorePathWithOutputs)> doPath; std::function<void(BuildableReq)> doPath;
auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) { auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) {
{ {
@ -154,7 +154,7 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
} }
for (auto & i : drv.inputDrvs) for (auto & i : drv.inputDrvs)
pool.enqueue(std::bind(doPath, StorePathWithOutputs { i.first, i.second })); pool.enqueue(std::bind(doPath, BuildableReqFromDrv { i.first, i.second }));
}; };
auto checkOutput = [&]( auto checkOutput = [&](
@ -177,24 +177,25 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
drvState->outPaths.insert(outPath); drvState->outPaths.insert(outPath);
if (!drvState->left) { if (!drvState->left) {
for (auto & path : drvState->outPaths) for (auto & path : drvState->outPaths)
pool.enqueue(std::bind(doPath, StorePathWithOutputs { path } )); pool.enqueue(std::bind(doPath, BuildableOpaque { path } ));
} }
} }
} }
}; };
doPath = [&](const StorePathWithOutputs & path) { doPath = [&](const BuildableReq & req) {
{ {
auto state(state_.lock()); auto state(state_.lock());
if (!state->done.insert(path.to_string(*this)).second) return; if (!state->done.insert(to_string(*this, req)).second) return;
} }
if (path.path.isDerivation()) { std::visit(overloaded {
if (!isValidPath(path.path)) { [&](BuildableReqFromDrv bfd) {
if (!isValidPath(bfd.drvPath)) {
// FIXME: we could try to substitute the derivation. // FIXME: we could try to substitute the derivation.
auto state(state_.lock()); auto state(state_.lock());
state->unknown.insert(path.path); state->unknown.insert(bfd.drvPath);
return; return;
} }
@ -202,52 +203,54 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
/* true for regular derivations, and CA derivations for which we /* true for regular derivations, and CA derivations for which we
have a trust mapping for all wanted outputs. */ have a trust mapping for all wanted outputs. */
auto knownOutputPaths = true; auto knownOutputPaths = true;
for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(path.path)) { for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(bfd.drvPath)) {
if (!pathOpt) { if (!pathOpt) {
knownOutputPaths = false; knownOutputPaths = false;
break; break;
} }
if (wantOutput(outputName, path.outputs) && !isValidPath(*pathOpt)) if (wantOutput(outputName, bfd.outputs) && !isValidPath(*pathOpt))
invalid.insert(*pathOpt); invalid.insert(*pathOpt);
} }
if (knownOutputPaths && invalid.empty()) return; if (knownOutputPaths && invalid.empty()) return;
auto drv = make_ref<Derivation>(derivationFromPath(path.path)); auto drv = make_ref<Derivation>(derivationFromPath(bfd.drvPath));
ParsedDerivation parsedDrv(StorePath(path.path), *drv); ParsedDerivation parsedDrv(StorePath(bfd.drvPath), *drv);
if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) { if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size())); auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
for (auto & output : invalid) for (auto & output : invalid)
pool.enqueue(std::bind(checkOutput, path.path, drv, output, drvState)); pool.enqueue(std::bind(checkOutput, bfd.drvPath, drv, output, drvState));
} else } else
mustBuildDrv(path.path, *drv); mustBuildDrv(bfd.drvPath, *drv);
} else { },
[&](BuildableOpaque bo) {
if (isValidPath(path.path)) return; if (isValidPath(bo.path)) return;
SubstitutablePathInfos infos; SubstitutablePathInfos infos;
querySubstitutablePathInfos({{path.path, std::nullopt}}, infos); querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos);
if (infos.empty()) { if (infos.empty()) {
auto state(state_.lock()); auto state(state_.lock());
state->unknown.insert(path.path); state->unknown.insert(bo.path);
return; return;
} }
auto info = infos.find(path.path); auto info = infos.find(bo.path);
assert(info != infos.end()); assert(info != infos.end());
{ {
auto state(state_.lock()); auto state(state_.lock());
state->willSubstitute.insert(path.path); state->willSubstitute.insert(bo.path);
state->downloadSize += info->second.downloadSize; state->downloadSize += info->second.downloadSize;
state->narSize += info->second.narSize; state->narSize += info->second.narSize;
} }
for (auto & ref : info->second.references) for (auto & ref : info->second.references)
pool.enqueue(std::bind(doPath, StorePathWithOutputs { ref })); pool.enqueue(std::bind(doPath, BuildableOpaque { ref }));
} },
}, req);
}; };
for (auto & path : targets) for (auto & path : targets)

View file

@ -1,3 +1,4 @@
#include "path-with-outputs.hh"
#include "store-api.hh" #include "store-api.hh"
namespace nix { namespace nix {
@ -10,6 +11,40 @@ std::string StorePathWithOutputs::to_string(const Store & store) const
} }
BuildableReq StorePathWithOutputs::toBuildableReq() const
{
if (!outputs.empty() || path.isDerivation())
return BuildableReqFromDrv { path, outputs };
else
return BuildableOpaque { path };
}
std::vector<BuildableReq> toBuildableReqs(const std::vector<StorePathWithOutputs> ss)
{
std::vector<BuildableReq> reqs;
for (auto & s : ss) reqs.push_back(s.toBuildableReq());
return reqs;
}
std::variant<StorePathWithOutputs, StorePath> StorePathWithOutputs::tryFromBuildableReq(const BuildableReq & p)
{
return std::visit(overloaded {
[&](BuildableOpaque bo) -> std::variant<StorePathWithOutputs, StorePath> {
if (bo.path.isDerivation()) {
// drv path gets interpreted as "build", not "get drv file itself"
return bo.path;
}
return StorePathWithOutputs { bo.path };
},
[&](BuildableReqFromDrv bfd) -> std::variant<StorePathWithOutputs, StorePath> {
return StorePathWithOutputs { bfd.drvPath, bfd.outputs };
},
}, p);
}
std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s) std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s)
{ {
size_t n = s.find("!"); size_t n = s.find("!");

View file

@ -1,6 +1,9 @@
#pragma once #pragma once
#include <variant>
#include "path.hh" #include "path.hh"
#include "buildable.hh"
namespace nix { namespace nix {
@ -10,8 +13,14 @@ struct StorePathWithOutputs
std::set<std::string> outputs; std::set<std::string> outputs;
std::string to_string(const Store & store) const; std::string to_string(const Store & store) const;
BuildableReq toBuildableReq() const;
static std::variant<StorePathWithOutputs, StorePath> tryFromBuildableReq(const BuildableReq &);
}; };
std::vector<BuildableReq> toBuildableReqs(const std::vector<StorePathWithOutputs>);
std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s); std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s);
class Store; class Store;

View file

@ -1,5 +1,6 @@
#include "serialise.hh" #include "serialise.hh"
#include "util.hh" #include "util.hh"
#include "path-with-outputs.hh"
#include "remote-fs-accessor.hh" #include "remote-fs-accessor.hh"
#include "remote-store.hh" #include "remote-store.hh"
#include "worker-protocol.hh" #include "worker-protocol.hh"
@ -50,6 +51,19 @@ void write(const Store & store, Sink & out, const ContentAddress & ca)
out << renderContentAddress(ca); out << renderContentAddress(ca);
} }
BuildableReq read(const Store & store, Source & from, Phantom<BuildableReq> _)
{
auto s = readString(from);
return parseBuildableReq(store, s);
}
void write(const Store & store, Sink & out, const BuildableReq & req)
{
out << to_string(store, req);
}
Realisation read(const Store & store, Source & from, Phantom<Realisation> _) Realisation read(const Store & store, Source & from, Phantom<Realisation> _)
{ {
std::string rawInput = readString(from); std::string rawInput = readString(from);
@ -58,8 +72,12 @@ Realisation read(const Store & store, Source & from, Phantom<Realisation> _)
"remote-protocol" "remote-protocol"
); );
} }
void write(const Store & store, Sink & out, const Realisation & realisation) void write(const Store & store, Sink & out, const Realisation & realisation)
{ out << realisation.toJSON().dump(); } {
out << realisation.toJSON().dump();
}
DrvOutput read(const Store & store, Source & from, Phantom<DrvOutput> _) DrvOutput read(const Store & store, Source & from, Phantom<DrvOutput> _)
{ {
@ -652,16 +670,36 @@ std::optional<const Realisation> RemoteStore::queryRealisation(const DrvOutput &
return {Realisation{.id = id, .outPath = *outPaths.begin()}}; return {Realisation{.id = id, .outPath = *outPaths.begin()}};
} }
static void writeBuildableReqs(RemoteStore & store, ConnectionHandle & conn, const std::vector<BuildableReq> & reqs)
{
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 29) {
worker_proto::write(store, conn->to, reqs);
} else {
Strings ss;
for (auto & p : reqs) {
auto sOrDrvPath = StorePathWithOutputs::tryFromBuildableReq(p);
std::visit(overloaded {
[&](StorePathWithOutputs s) {
ss.push_back(s.to_string(store));
},
[&](StorePath drvPath) {
throw Error("trying to request '%s', but daemon protocol %d.%d is too old (< 1.29) to request a derivation file",
store.printStorePath(drvPath),
GET_PROTOCOL_MAJOR(conn->daemonVersion),
GET_PROTOCOL_MINOR(conn->daemonVersion));
},
}, sOrDrvPath);
}
conn->to << ss;
}
}
void RemoteStore::buildPaths(const std::vector<StorePathWithOutputs> & drvPaths, BuildMode buildMode) void RemoteStore::buildPaths(const std::vector<BuildableReq> & drvPaths, BuildMode buildMode)
{ {
auto conn(getConnection()); auto conn(getConnection());
conn->to << wopBuildPaths; conn->to << wopBuildPaths;
assert(GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13); assert(GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13);
Strings ss; writeBuildableReqs(*this, conn, drvPaths);
for (auto & p : drvPaths)
ss.push_back(p.to_string(*this));
conn->to << ss;
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15) if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15)
conn->to << buildMode; conn->to << buildMode;
else else
@ -800,7 +838,7 @@ void RemoteStore::addSignatures(const StorePath & storePath, const StringSet & s
} }
void RemoteStore::queryMissing(const std::vector<StorePathWithOutputs> & targets, void RemoteStore::queryMissing(const std::vector<BuildableReq> & targets,
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
uint64_t & downloadSize, uint64_t & narSize) uint64_t & downloadSize, uint64_t & narSize)
{ {
@ -811,10 +849,7 @@ void RemoteStore::queryMissing(const std::vector<StorePathWithOutputs> & targets
// to prevent a deadlock. // to prevent a deadlock.
goto fallback; goto fallback;
conn->to << wopQueryMissing; conn->to << wopQueryMissing;
Strings ss; writeBuildableReqs(*this, conn, targets);
for (auto & p : targets)
ss.push_back(p.to_string(*this));
conn->to << ss;
conn.processStderr(); conn.processStderr();
willBuild = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {}); willBuild = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
willSubstitute = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {}); willSubstitute = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});

View file

@ -85,7 +85,7 @@ public:
std::optional<const Realisation> queryRealisation(const DrvOutput &) override; std::optional<const Realisation> queryRealisation(const DrvOutput &) override;
void buildPaths(const std::vector<StorePathWithOutputs> & paths, BuildMode buildMode) override; void buildPaths(const std::vector<BuildableReq> & paths, BuildMode buildMode) override;
BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv, BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
BuildMode buildMode) override; BuildMode buildMode) override;
@ -108,7 +108,7 @@ public:
void addSignatures(const StorePath & storePath, const StringSet & sigs) override; void addSignatures(const StorePath & storePath, const StringSet & sigs) override;
void queryMissing(const std::vector<StorePathWithOutputs> & targets, void queryMissing(const std::vector<BuildableReq> & targets,
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
uint64_t & downloadSize, uint64_t & narSize) override; uint64_t & downloadSize, uint64_t & narSize) override;

View file

@ -529,10 +529,10 @@ void Store::queryPathInfo(const StorePath & storePath,
void Store::substitutePaths(const StorePathSet & paths) void Store::substitutePaths(const StorePathSet & paths)
{ {
std::vector<StorePathWithOutputs> paths2; std::vector<BuildableReq> paths2;
for (auto & path : paths) for (auto & path : paths)
if (!path.isDerivation()) if (!path.isDerivation())
paths2.push_back({path}); paths2.push_back(BuildableOpaque{path});
uint64_t downloadSize, narSize; uint64_t downloadSize, narSize;
StorePathSet willBuild, willSubstitute, unknown; StorePathSet willBuild, willSubstitute, unknown;
queryMissing(paths2, queryMissing(paths2,
@ -540,8 +540,8 @@ void Store::substitutePaths(const StorePathSet & paths)
if (!willSubstitute.empty()) if (!willSubstitute.empty())
try { try {
std::vector<StorePathWithOutputs> subs; std::vector<BuildableReq> subs;
for (auto & p : willSubstitute) subs.push_back({p}); for (auto & p : willSubstitute) subs.push_back(BuildableOpaque{p});
buildPaths(subs); buildPaths(subs);
} catch (Error & e) { } catch (Error & e) {
logWarning(e.info()); logWarning(e.info());

View file

@ -2,7 +2,7 @@
#include "realisation.hh" #include "realisation.hh"
#include "path.hh" #include "path.hh"
#include "path-with-outputs.hh" #include "buildable.hh"
#include "hash.hh" #include "hash.hh"
#include "content-address.hh" #include "content-address.hh"
#include "serialise.hh" #include "serialise.hh"
@ -494,7 +494,7 @@ public:
recursively building any sub-derivations. For inputs that are recursively building any sub-derivations. For inputs that are
not derivations, substitute them. */ not derivations, substitute them. */
virtual void buildPaths( virtual void buildPaths(
const std::vector<StorePathWithOutputs> & paths, const std::vector<BuildableReq> & paths,
BuildMode buildMode = bmNormal); BuildMode buildMode = bmNormal);
/* Build a single non-materialized derivation (i.e. not from an /* Build a single non-materialized derivation (i.e. not from an
@ -656,7 +656,7 @@ public:
/* Given a set of paths that are to be built, return the set of /* Given a set of paths that are to be built, return the set of
derivations that will be built, and the set of output paths derivations that will be built, and the set of output paths
that will be substituted. */ that will be substituted. */
virtual void queryMissing(const std::vector<StorePathWithOutputs> & targets, virtual void queryMissing(const std::vector<BuildableReq> & targets,
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown, StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
uint64_t & downloadSize, uint64_t & narSize); uint64_t & downloadSize, uint64_t & narSize);

View file

@ -86,9 +86,11 @@ namespace worker_proto {
MAKE_WORKER_PROTO(, std::string); MAKE_WORKER_PROTO(, std::string);
MAKE_WORKER_PROTO(, StorePath); MAKE_WORKER_PROTO(, StorePath);
MAKE_WORKER_PROTO(, ContentAddress); MAKE_WORKER_PROTO(, ContentAddress);
MAKE_WORKER_PROTO(, BuildableReq);
MAKE_WORKER_PROTO(, Realisation); MAKE_WORKER_PROTO(, Realisation);
MAKE_WORKER_PROTO(, DrvOutput); MAKE_WORKER_PROTO(, DrvOutput);
MAKE_WORKER_PROTO(template<typename T>, std::vector<T>);
MAKE_WORKER_PROTO(template<typename T>, std::set<T>); MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
#define X_ template<typename K, typename V> #define X_ template<typename K, typename V>
@ -113,6 +115,26 @@ MAKE_WORKER_PROTO(X_, Y_);
MAKE_WORKER_PROTO(, std::optional<StorePath>); MAKE_WORKER_PROTO(, std::optional<StorePath>);
MAKE_WORKER_PROTO(, std::optional<ContentAddress>); MAKE_WORKER_PROTO(, std::optional<ContentAddress>);
template<typename T>
std::vector<T> read(const Store & store, Source & from, Phantom<std::vector<T>> _)
{
std::vector<T> resSet;
auto size = readNum<size_t>(from);
while (size--) {
resSet.push_back(read(store, from, Phantom<T> {}));
}
return resSet;
}
template<typename T>
void write(const Store & store, Sink & out, const std::vector<T> & resSet)
{
out << resSet.size();
for (auto & key : resSet) {
write(store, out, key);
}
}
template<typename T> template<typename T>
std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _) std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _)
{ {

View file

@ -12,6 +12,7 @@
#include "affinity.hh" #include "affinity.hh"
#include "util.hh" #include "util.hh"
#include "shared.hh" #include "shared.hh"
#include "path-with-outputs.hh"
#include "eval.hh" #include "eval.hh"
#include "eval-inline.hh" #include "eval-inline.hh"
#include "get-drvs.hh" #include "get-drvs.hh"
@ -321,7 +322,8 @@ static void main_nix_build(int argc, char * * argv)
state->printStats(); state->printStats();
auto buildPaths = [&](const std::vector<StorePathWithOutputs> & paths) { auto buildPaths = [&](const std::vector<StorePathWithOutputs> & paths0) {
auto paths = toBuildableReqs(paths0);
/* Note: we do this even when !printMissing to efficiently /* Note: we do this even when !printMissing to efficiently
fetch binary cache data. */ fetch binary cache data. */
uint64_t downloadSize, narSize; uint64_t downloadSize, narSize;

View file

@ -6,6 +6,7 @@
#include "globals.hh" #include "globals.hh"
#include "names.hh" #include "names.hh"
#include "profiles.hh" #include "profiles.hh"
#include "path-with-outputs.hh"
#include "shared.hh" #include "shared.hh"
#include "store-api.hh" #include "store-api.hh"
#include "local-fs-store.hh" #include "local-fs-store.hh"
@ -418,13 +419,13 @@ static void queryInstSources(EvalState & state,
static void printMissing(EvalState & state, DrvInfos & elems) static void printMissing(EvalState & state, DrvInfos & elems)
{ {
std::vector<StorePathWithOutputs> targets; std::vector<BuildableReq> targets;
for (auto & i : elems) { for (auto & i : elems) {
Path drvPath = i.queryDrvPath(); Path drvPath = i.queryDrvPath();
if (drvPath != "") if (drvPath != "")
targets.push_back({state.store->parseStorePath(drvPath)}); targets.push_back(BuildableReqFromDrv{state.store->parseStorePath(drvPath)});
else else
targets.push_back({state.store->parseStorePath(i.queryOutPath())}); targets.push_back(BuildableOpaque{state.store->parseStorePath(i.queryOutPath())});
} }
printMissing(state.store, targets); printMissing(state.store, targets);
@ -693,17 +694,18 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
if (globals.forceName != "") if (globals.forceName != "")
drv.setName(globals.forceName); drv.setName(globals.forceName);
if (drv.queryDrvPath() != "") { std::vector<BuildableReq> paths {
std::vector<StorePathWithOutputs> paths{{globals.state->store->parseStorePath(drv.queryDrvPath())}}; (drv.queryDrvPath() != "")
? (BuildableReq) (BuildableReqFromDrv {
globals.state->store->parseStorePath(drv.queryDrvPath())
})
: (BuildableReq) (BuildableOpaque {
globals.state->store->parseStorePath(drv.queryOutPath())
}),
};
printMissing(globals.state->store, paths); printMissing(globals.state->store, paths);
if (globals.dryRun) return; if (globals.dryRun) return;
globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal); globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal);
} else {
printMissing(globals.state->store,
{{globals.state->store->parseStorePath(drv.queryOutPath())}});
if (globals.dryRun) return;
globals.state->store->ensurePath(globals.state->store->parseStorePath(drv.queryOutPath()));
}
debug(format("switching to new user environment")); debug(format("switching to new user environment"));
Path generation = createGeneration( Path generation = createGeneration(

View file

@ -2,6 +2,7 @@
#include "util.hh" #include "util.hh"
#include "derivations.hh" #include "derivations.hh"
#include "store-api.hh" #include "store-api.hh"
#include "path-with-outputs.hh"
#include "local-fs-store.hh" #include "local-fs-store.hh"
#include "globals.hh" #include "globals.hh"
#include "shared.hh" #include "shared.hh"
@ -41,7 +42,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
drvsToBuild.push_back({state.store->parseStorePath(i.queryDrvPath())}); drvsToBuild.push_back({state.store->parseStorePath(i.queryDrvPath())});
debug(format("building user environment dependencies")); debug(format("building user environment dependencies"));
state.store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal); state.store->buildPaths(
toBuildableReqs(drvsToBuild),
state.repair ? bmRepair : bmNormal);
/* Construct the whole top level derivation. */ /* Construct the whole top level derivation. */
StorePathSet references; StorePathSet references;
@ -136,7 +139,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
debug("building user environment"); debug("building user environment");
std::vector<StorePathWithOutputs> topLevelDrvs; std::vector<StorePathWithOutputs> topLevelDrvs;
topLevelDrvs.push_back({topLevelDrv}); topLevelDrvs.push_back({topLevelDrv});
state.store->buildPaths(topLevelDrvs, state.repair ? bmRepair : bmNormal); state.store->buildPaths(
toBuildableReqs(topLevelDrvs),
state.repair ? bmRepair : bmNormal);
/* Switch the current user environment to the output path. */ /* Switch the current user environment to the output path. */
auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>(); auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();

View file

@ -10,6 +10,7 @@
#include "worker-protocol.hh" #include "worker-protocol.hh"
#include "graphml.hh" #include "graphml.hh"
#include "legacy.hh" #include "legacy.hh"
#include "path-with-outputs.hh"
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
@ -62,7 +63,7 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true)
auto store2 = std::dynamic_pointer_cast<LocalFSStore>(store); auto store2 = std::dynamic_pointer_cast<LocalFSStore>(store);
if (path.path.isDerivation()) { if (path.path.isDerivation()) {
if (build) store->buildPaths({path}); if (build) store->buildPaths({path.toBuildableReq()});
auto outputPaths = store->queryDerivationOutputMap(path.path); auto outputPaths = store->queryDerivationOutputMap(path.path);
Derivation drv = store->derivationFromPath(path.path); Derivation drv = store->derivationFromPath(path.path);
rootNr++; rootNr++;
@ -132,7 +133,9 @@ static void opRealise(Strings opFlags, Strings opArgs)
uint64_t downloadSize, narSize; uint64_t downloadSize, narSize;
StorePathSet willBuild, willSubstitute, unknown; StorePathSet willBuild, willSubstitute, unknown;
store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize); store->queryMissing(
toBuildableReqs(paths),
willBuild, willSubstitute, unknown, downloadSize, narSize);
if (ignoreUnknown) { if (ignoreUnknown) {
std::vector<StorePathWithOutputs> paths2; std::vector<StorePathWithOutputs> paths2;
@ -148,7 +151,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
if (dryRun) return; if (dryRun) return;
/* Build all paths at the same time to exploit parallelism. */ /* Build all paths at the same time to exploit parallelism. */
store->buildPaths(paths, buildMode); store->buildPaths(toBuildableReqs(paths), buildMode);
if (!ignoreUnknown) if (!ignoreUnknown)
for (auto & i : paths) { for (auto & i : paths) {
@ -879,7 +882,7 @@ static void opServe(Strings opFlags, Strings opArgs)
try { try {
MonitorFdHup monitor(in.fd); MonitorFdHup monitor(in.fd);
store->buildPaths(paths); store->buildPaths(toBuildableReqs(paths));
out << 0; out << 0;
} catch (Error & e) { } catch (Error & e) {
assert(e.status); assert(e.status);

View file

@ -70,7 +70,7 @@ struct CmdBundle : InstallableCommand
auto evalState = getEvalState(); auto evalState = getEvalState();
auto app = installable->toApp(*evalState); auto app = installable->toApp(*evalState);
store->buildPaths(app.context); store->buildPaths(toBuildableReqs(app.context));
auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath(".")); auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
const flake::LockFlags lockFlags{ .writeLockFile = false }; const flake::LockFlags lockFlags{ .writeLockFile = false };
@ -110,7 +110,7 @@ struct CmdBundle : InstallableCommand
StorePath outPath = store->parseStorePath(evalState->coerceToPath(*attr2->pos, *attr2->value, context2)); StorePath outPath = store->parseStorePath(evalState->coerceToPath(*attr2->pos, *attr2->value, context2));
store->buildPaths({{drvPath}}); store->buildPaths({ BuildableReqFromDrv { drvPath } });
auto outPathS = store->printStorePath(outPath); auto outPathS = store->printStorePath(outPath);

View file

@ -3,6 +3,7 @@
#include "common-args.hh" #include "common-args.hh"
#include "shared.hh" #include "shared.hh"
#include "store-api.hh" #include "store-api.hh"
#include "path-with-outputs.hh"
#include "derivations.hh" #include "derivations.hh"
#include "affinity.hh" #include "affinity.hh"
#include "progress-bar.hh" #include "progress-bar.hh"
@ -159,7 +160,7 @@ StorePath getDerivationEnvironment(ref<Store> store, const StorePath & drvPath)
auto shellDrvPath = writeDerivation(*store, drv); auto shellDrvPath = writeDerivation(*store, drv);
/* Build the derivation. */ /* Build the derivation. */
store->buildPaths({{shellDrvPath}}); store->buildPaths({BuildableReqFromDrv{shellDrvPath}});
for (auto & [_0, outputAndOptPath] : drv.outputsAndOptPaths(*store)) { for (auto & [_0, outputAndOptPath] : drv.outputsAndOptPaths(*store)) {
auto & [_1, optPath] = outputAndOptPath; auto & [_1, optPath] = outputAndOptPath;

View file

@ -7,6 +7,7 @@
#include "get-drvs.hh" #include "get-drvs.hh"
#include "store-api.hh" #include "store-api.hh"
#include "derivations.hh" #include "derivations.hh"
#include "path-with-outputs.hh"
#include "attr-path.hh" #include "attr-path.hh"
#include "fetchers.hh" #include "fetchers.hh"
#include "registry.hh" #include "registry.hh"
@ -292,7 +293,7 @@ struct CmdFlakeCheck : FlakeCommand
} }
}; };
std::vector<StorePathWithOutputs> drvPaths; std::vector<BuildableReq> drvPaths;
auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) { auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) {
try { try {
@ -461,7 +462,7 @@ struct CmdFlakeCheck : FlakeCommand
fmt("%s.%s.%s", name, attr.name, attr2.name), fmt("%s.%s.%s", name, attr.name, attr2.name),
*attr2.value, *attr2.pos); *attr2.value, *attr2.pos);
if ((std::string) attr.name == settings.thisSystem.get()) if ((std::string) attr.name == settings.thisSystem.get())
drvPaths.push_back({drvPath}); drvPaths.push_back(BuildableReqFromDrv{drvPath});
} }
} }
} }

View file

@ -233,7 +233,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
{ {
ProfileManifest manifest(*getEvalState(), *profile); ProfileManifest manifest(*getEvalState(), *profile);
std::vector<StorePathWithOutputs> pathsToBuild; std::vector<BuildableReq> pathsToBuild;
for (auto & installable : installables) { for (auto & installable : installables) {
if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) { if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) {
@ -249,7 +249,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
attrPath, attrPath,
}; };
pathsToBuild.push_back({drv.drvPath, StringSet{drv.outputName}}); pathsToBuild.push_back(BuildableReqFromDrv{drv.drvPath, StringSet{drv.outputName}});
manifest.elements.emplace_back(std::move(element)); manifest.elements.emplace_back(std::move(element));
} else { } else {
@ -260,12 +260,15 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
std::visit(overloaded { std::visit(overloaded {
[&](BuildableOpaque bo) { [&](BuildableOpaque bo) {
pathsToBuild.push_back({bo.path, {}}); pathsToBuild.push_back(bo);
element.storePaths.insert(bo.path); element.storePaths.insert(bo.path);
}, },
[&](BuildableFromDrv bfd) { [&](BuildableFromDrv bfd) {
// TODO: Why are we querying if we know the output
// names already? Is it just to figure out what the
// default one is?
for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) { for (auto & output : store->queryDerivationOutputMap(bfd.drvPath)) {
pathsToBuild.push_back({bfd.drvPath, {output.first}}); pathsToBuild.push_back(BuildableReqFromDrv{bfd.drvPath, {output.first}});
element.storePaths.insert(output.second); element.storePaths.insert(output.second);
} }
}, },
@ -388,7 +391,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
auto matchers = getMatchers(store); auto matchers = getMatchers(store);
// FIXME: code duplication // FIXME: code duplication
std::vector<StorePathWithOutputs> pathsToBuild; std::vector<BuildableReq> pathsToBuild;
for (size_t i = 0; i < manifest.elements.size(); ++i) { for (size_t i = 0; i < manifest.elements.size(); ++i) {
auto & element(manifest.elements[i]); auto & element(manifest.elements[i]);
@ -423,7 +426,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
attrPath, attrPath,
}; };
pathsToBuild.push_back({drv.drvPath, StringSet{"out"}}); // FIXME pathsToBuild.push_back(BuildableReqFromDrv{drv.drvPath, {"out"}}); // FIXME
} }
} }

View file

@ -182,7 +182,7 @@ struct CmdRun : InstallableCommand, RunCommon
auto app = installable->toApp(*state); auto app = installable->toApp(*state);
state->store->buildPaths(app.context); state->store->buildPaths(toBuildableReqs(app.context));
Strings allArgs{app.program}; Strings allArgs{app.program};
for (auto & i : args) allArgs.push_back(i); for (auto & i : args) allArgs.push_back(i);