forked from lix-project/lix
Merge pull request #4594 from obsidiansystems/lots-of-buildable
Use `DerivedPath` for `buildPaths` and `ensurePath`
This commit is contained in:
commit
4bf3eb27e6
|
@ -162,7 +162,7 @@ void MixProfile::updateProfile(const StorePath & storePath)
|
|||
profile2, storePath));
|
||||
}
|
||||
|
||||
void MixProfile::updateProfile(const Buildables & buildables)
|
||||
void MixProfile::updateProfile(const DerivedPathsWithHints & buildables)
|
||||
{
|
||||
if (!profile) return;
|
||||
|
||||
|
@ -170,10 +170,10 @@ void MixProfile::updateProfile(const Buildables & buildables)
|
|||
|
||||
for (auto & buildable : buildables) {
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
result.push_back(bo.path);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
for (auto & output : bfd.outputs) {
|
||||
/* Output path should be known because we just tried to
|
||||
build it. */
|
||||
|
@ -181,7 +181,7 @@ void MixProfile::updateProfile(const Buildables & buildables)
|
|||
result.push_back(*output.second);
|
||||
}
|
||||
},
|
||||
}, buildable);
|
||||
}, buildable.raw());
|
||||
}
|
||||
|
||||
if (result.size() != 1)
|
||||
|
|
|
@ -216,7 +216,7 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
|
|||
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
|
||||
}
|
||||
|
||||
Buildables build(ref<Store> store, Realise mode,
|
||||
DerivedPathsWithHints build(ref<Store> store, Realise mode,
|
||||
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode = bmNormal);
|
||||
|
||||
std::set<StorePath> toStorePaths(ref<Store> store,
|
||||
|
@ -252,7 +252,7 @@ struct MixProfile : virtual StoreCommand
|
|||
|
||||
/* If 'profile' is set, make it point at the store path produced
|
||||
by 'buildables'. */
|
||||
void updateProfile(const Buildables & buildables);
|
||||
void updateProfile(const DerivedPathsWithHints & buildables);
|
||||
};
|
||||
|
||||
struct MixDefaultProfile : MixProfile
|
||||
|
|
|
@ -20,31 +20,6 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
nlohmann::json BuildableOpaque::toJSON(ref<Store> store) const {
|
||||
nlohmann::json res;
|
||||
res["path"] = store->printStorePath(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
nlohmann::json BuildableFromDrv::toJSON(ref<Store> store) const {
|
||||
nlohmann::json res;
|
||||
res["drvPath"] = store->printStorePath(drvPath);
|
||||
for (const auto& [output, path] : outputs) {
|
||||
res["outputs"][output] = path ? store->printStorePath(*path) : "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store) {
|
||||
auto res = nlohmann::json::array();
|
||||
for (const Buildable & buildable : buildables) {
|
||||
std::visit([&res, store](const auto & buildable) {
|
||||
res.push_back(buildable.toJSON(store));
|
||||
}, buildable);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void completeFlakeInputPath(
|
||||
ref<EvalState> evalState,
|
||||
const FlakeRef & flakeRef,
|
||||
|
@ -310,9 +285,9 @@ void completeFlakeRef(ref<Store> store, std::string_view prefix)
|
|||
}
|
||||
}
|
||||
|
||||
Buildable Installable::toBuildable()
|
||||
DerivedPathWithHints Installable::toDerivedPathWithHints()
|
||||
{
|
||||
auto buildables = toBuildables();
|
||||
auto buildables = toDerivedPathsWithHints();
|
||||
if (buildables.size() != 1)
|
||||
throw Error("installable '%s' evaluates to %d derivations, where only one is expected", what(), buildables.size());
|
||||
return std::move(buildables[0]);
|
||||
|
@ -346,7 +321,7 @@ struct InstallableStorePath : Installable
|
|||
|
||||
std::string what() override { return store->printStorePath(storePath); }
|
||||
|
||||
Buildables toBuildables() override
|
||||
DerivedPathsWithHints toDerivedPathsWithHints() override
|
||||
{
|
||||
if (storePath.isDerivation()) {
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
|
@ -354,14 +329,14 @@ struct InstallableStorePath : Installable
|
|||
for (auto & [name, output] : drv.outputsAndOptPaths(*store))
|
||||
outputs.emplace(name, output.second);
|
||||
return {
|
||||
BuildableFromDrv {
|
||||
DerivedPathWithHints::Built {
|
||||
.drvPath = storePath,
|
||||
.outputs = std::move(outputs)
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
BuildableOpaque {
|
||||
DerivedPathWithHints::Opaque {
|
||||
.path = storePath,
|
||||
}
|
||||
};
|
||||
|
@ -374,9 +349,9 @@ struct InstallableStorePath : Installable
|
|||
}
|
||||
};
|
||||
|
||||
Buildables InstallableValue::toBuildables()
|
||||
DerivedPathsWithHints InstallableValue::toDerivedPathsWithHints()
|
||||
{
|
||||
Buildables res;
|
||||
DerivedPathsWithHints res;
|
||||
|
||||
std::map<StorePath, std::map<std::string, std::optional<StorePath>>> drvsToOutputs;
|
||||
|
||||
|
@ -389,7 +364,7 @@ Buildables InstallableValue::toBuildables()
|
|||
}
|
||||
|
||||
for (auto & i : drvsToOutputs)
|
||||
res.push_back(BuildableFromDrv { i.first, i.second });
|
||||
res.push_back(DerivedPathWithHints::Built { i.first, i.second });
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -696,29 +671,30 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
|||
return installables.front();
|
||||
}
|
||||
|
||||
Buildables build(ref<Store> store, Realise mode,
|
||||
DerivedPathsWithHints build(ref<Store> store, Realise mode,
|
||||
std::vector<std::shared_ptr<Installable>> installables, BuildMode bMode)
|
||||
{
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
Buildables buildables;
|
||||
DerivedPathsWithHints buildables;
|
||||
|
||||
std::vector<StorePathWithOutputs> pathsToBuild;
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
|
||||
for (auto & i : installables) {
|
||||
for (auto & b : i->toBuildables()) {
|
||||
for (auto & b : i->toDerivedPathsWithHints()) {
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
pathsToBuild.push_back({bo.path});
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
pathsToBuild.push_back(bo);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
StringSet outputNames;
|
||||
for (auto & output : bfd.outputs)
|
||||
outputNames.insert(output.first);
|
||||
pathsToBuild.push_back({bfd.drvPath, outputNames});
|
||||
pathsToBuild.push_back(
|
||||
DerivedPath::Built{bfd.drvPath, outputNames});
|
||||
},
|
||||
}, b);
|
||||
}, b.raw());
|
||||
buildables.push_back(std::move(b));
|
||||
}
|
||||
}
|
||||
|
@ -741,10 +717,10 @@ std::set<RealisedPath> toRealisedPaths(
|
|||
if (operateOn == OperateOn::Output) {
|
||||
for (auto & b : build(store, mode, installables))
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
res.insert(bo.path);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
auto drv = store->readDerivation(bfd.drvPath);
|
||||
auto outputHashes = staticOutputHashes(*store, drv);
|
||||
for (auto & output : bfd.outputs) {
|
||||
|
@ -769,14 +745,14 @@ std::set<RealisedPath> toRealisedPaths(
|
|||
}
|
||||
}
|
||||
},
|
||||
}, b);
|
||||
}, b.raw());
|
||||
} else {
|
||||
if (mode == Realise::Nothing)
|
||||
settings.readOnlyMode = true;
|
||||
|
||||
for (auto & i : installables)
|
||||
for (auto & b : i->toBuildables())
|
||||
if (auto bfd = std::get_if<BuildableFromDrv>(&b))
|
||||
for (auto & b : i->toDerivedPathsWithHints())
|
||||
if (auto bfd = std::get_if<DerivedPathWithHints::Built>(&b))
|
||||
res.insert(bfd->drvPath);
|
||||
}
|
||||
|
||||
|
@ -811,9 +787,9 @@ StorePathSet toDerivations(ref<Store> store,
|
|||
StorePathSet drvPaths;
|
||||
|
||||
for (auto & i : installables)
|
||||
for (auto & b : i->toBuildables())
|
||||
for (auto & b : i->toDerivedPathsWithHints())
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
if (!useDeriver)
|
||||
throw Error("argument '%s' did not evaluate to a derivation", i->what());
|
||||
auto derivers = store->queryValidDerivers(bo.path);
|
||||
|
@ -822,10 +798,10 @@ StorePathSet toDerivations(ref<Store> store,
|
|||
// FIXME: use all derivers?
|
||||
drvPaths.insert(*derivers.begin());
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
drvPaths.insert(bfd.drvPath);
|
||||
},
|
||||
}, b);
|
||||
}, b.raw());
|
||||
|
||||
return drvPaths;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
#include "util.hh"
|
||||
#include "path.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "derived-path.hh"
|
||||
#include "eval.hh"
|
||||
#include "flake/flake.hh"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct DrvInfo;
|
||||
|
@ -16,25 +16,6 @@ struct SourceExprCommand;
|
|||
|
||||
namespace eval_cache { class EvalCache; class AttrCursor; }
|
||||
|
||||
struct BuildableOpaque {
|
||||
StorePath path;
|
||||
nlohmann::json toJSON(ref<Store> store) const;
|
||||
};
|
||||
|
||||
struct BuildableFromDrv {
|
||||
StorePath drvPath;
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
nlohmann::json toJSON(ref<Store> store) const;
|
||||
};
|
||||
|
||||
typedef std::variant<
|
||||
BuildableOpaque,
|
||||
BuildableFromDrv
|
||||
> Buildable;
|
||||
|
||||
typedef std::vector<Buildable> Buildables;
|
||||
nlohmann::json buildablesToJSON(const Buildables & buildables, ref<Store> store);
|
||||
|
||||
struct App
|
||||
{
|
||||
std::vector<StorePathWithOutputs> context;
|
||||
|
@ -48,9 +29,9 @@ struct Installable
|
|||
|
||||
virtual std::string what() = 0;
|
||||
|
||||
virtual Buildables toBuildables() = 0;
|
||||
virtual DerivedPathsWithHints toDerivedPathsWithHints() = 0;
|
||||
|
||||
Buildable toBuildable();
|
||||
DerivedPathWithHints toDerivedPathWithHints();
|
||||
|
||||
App toApp(EvalState & state);
|
||||
|
||||
|
@ -93,7 +74,7 @@ struct InstallableValue : Installable
|
|||
|
||||
virtual std::vector<DerivationInfo> toDerivations() = 0;
|
||||
|
||||
Buildables toBuildables() override;
|
||||
DerivedPathsWithHints toDerivedPathsWithHints() override;
|
||||
};
|
||||
|
||||
struct InstallableFlake : InstallableValue
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "util.hh"
|
||||
#include "eval-inline.hh"
|
||||
#include "store-api.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <regex>
|
||||
|
@ -19,7 +20,7 @@ DrvInfo::DrvInfo(EvalState & state, const string & attrPath, Bindings * attrs)
|
|||
DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPathWithOutputs)
|
||||
: state(&state), attrs(nullptr), attrPath("")
|
||||
{
|
||||
auto [drvPath, selectedOutputs] = store->parsePathWithOutputs(drvPathWithOutputs);
|
||||
auto [drvPath, selectedOutputs] = parsePathWithOutputs(*store, drvPathWithOutputs);
|
||||
|
||||
this->drvPath = store->printStorePath(drvPath);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ InvalidPathError::InvalidPathError(const Path & path) :
|
|||
|
||||
void EvalState::realiseContext(const PathSet & context)
|
||||
{
|
||||
std::vector<StorePathWithOutputs> drvs;
|
||||
std::vector<DerivedPath::Built> drvs;
|
||||
|
||||
for (auto & i : context) {
|
||||
auto [ctxS, outputName] = decodeContext(i);
|
||||
|
@ -43,7 +43,7 @@ void EvalState::realiseContext(const PathSet & context)
|
|||
if (!store->isValidPath(ctx))
|
||||
throw InvalidPathError(store->printStorePath(ctx));
|
||||
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)
|
||||
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. */
|
||||
StorePathSet willBuild, willSubstitute, unknown;
|
||||
uint64_t downloadSize, narSize;
|
||||
store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
|
||||
std::vector<DerivedPath> buildReqs;
|
||||
for (auto & d : drvs) buildReqs.emplace_back(DerivedPath { d });
|
||||
store->queryMissing(buildReqs, willBuild, willSubstitute, unknown, downloadSize, narSize);
|
||||
|
||||
store->buildPaths(drvs);
|
||||
store->buildPaths(buildReqs);
|
||||
|
||||
/* Add the output of this derivations to the allowed
|
||||
paths. */
|
||||
|
|
|
@ -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<DerivedPath> & paths, Verbosity lvl)
|
||||
{
|
||||
uint64_t downloadSize, narSize;
|
||||
StorePathSet willBuild, willSubstitute, unknown;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "args.hh"
|
||||
#include "common-args.hh"
|
||||
#include "path.hh"
|
||||
#include "derived-path.hh"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
|
@ -42,7 +43,7 @@ struct StorePathWithOutputs;
|
|||
|
||||
void printMissing(
|
||||
ref<Store> store,
|
||||
const std::vector<StorePathWithOutputs> & paths,
|
||||
const std::vector<DerivedPath> & paths,
|
||||
Verbosity lvl = lvlInfo);
|
||||
|
||||
void printMissing(ref<Store> store, const StorePathSet & willBuild,
|
||||
|
|
|
@ -73,7 +73,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath,
|
|||
state = &DerivationGoal::getDerivation;
|
||||
name = fmt(
|
||||
"building of '%s' from .drv file",
|
||||
StorePathWithOutputs { drvPath, wantedOutputs }.to_string(worker.store));
|
||||
DerivedPath::Built { drvPath, wantedOutputs }.to_string(worker.store));
|
||||
trace("created");
|
||||
|
||||
mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.expectedBuilds);
|
||||
|
@ -94,7 +94,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath, const BasicDerivation
|
|||
state = &DerivationGoal::haveDerivation;
|
||||
name = fmt(
|
||||
"building of '%s' from in-memory derivation",
|
||||
StorePathWithOutputs { drvPath, drv.outputNames() }.to_string(worker.store));
|
||||
DerivedPath::Built { drvPath, drv.outputNames() }.to_string(worker.store));
|
||||
trace("created");
|
||||
|
||||
mcExpectedBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.expectedBuilds);
|
||||
|
|
|
@ -6,16 +6,20 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
void Store::buildPaths(const std::vector<StorePathWithOutputs> & drvPaths, BuildMode buildMode)
|
||||
void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMode)
|
||||
{
|
||||
Worker worker(*this);
|
||||
|
||||
Goals goals;
|
||||
for (auto & path : drvPaths) {
|
||||
if (path.path.isDerivation())
|
||||
goals.insert(worker.makeDerivationGoal(path.path, path.outputs, buildMode));
|
||||
else
|
||||
goals.insert(worker.makePathSubstitutionGoal(path.path, buildMode == bmRepair ? Repair : NoRepair));
|
||||
for (auto & br : reqs) {
|
||||
std::visit(overloaded {
|
||||
[&](DerivedPath::Built bfd) {
|
||||
goals.insert(worker.makeDerivationGoal(bfd.drvPath, bfd.outputs, buildMode));
|
||||
},
|
||||
[&](DerivedPath::Opaque bo) {
|
||||
goals.insert(worker.makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair));
|
||||
},
|
||||
}, br.raw());
|
||||
}
|
||||
|
||||
worker.run(goals);
|
||||
|
|
|
@ -1190,6 +1190,26 @@ void LocalDerivationGoal::writeStructuredAttrs()
|
|||
chownToBuilder(tmpDir + "/.attrs.sh");
|
||||
}
|
||||
|
||||
|
||||
static StorePath pathPartOfReq(const DerivedPath & req)
|
||||
{
|
||||
return std::visit(overloaded {
|
||||
[&](DerivedPath::Opaque bo) {
|
||||
return bo.path;
|
||||
},
|
||||
[&](DerivedPath::Built bfd) {
|
||||
return bfd.drvPath;
|
||||
},
|
||||
}, req.raw());
|
||||
}
|
||||
|
||||
|
||||
bool LocalDerivationGoal::isAllowed(const DerivedPath & req)
|
||||
{
|
||||
return this->isAllowed(pathPartOfReq(req));
|
||||
}
|
||||
|
||||
|
||||
struct RestrictedStoreConfig : virtual LocalFSStoreConfig
|
||||
{
|
||||
using LocalFSStoreConfig::LocalFSStoreConfig;
|
||||
|
@ -1312,25 +1332,27 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
|
|||
// an allowed derivation
|
||||
{ throw Error("queryRealisation"); }
|
||||
|
||||
void buildPaths(const std::vector<StorePathWithOutputs> & paths, BuildMode buildMode) override
|
||||
void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode) override
|
||||
{
|
||||
if (buildMode != bmNormal) throw Error("unsupported build mode");
|
||||
|
||||
StorePathSet newPaths;
|
||||
|
||||
for (auto & path : paths) {
|
||||
if (!goal.isAllowed(path.path))
|
||||
throw InvalidPath("cannot build unknown path '%s' in recursive Nix", printStorePath(path.path));
|
||||
for (auto & req : paths) {
|
||||
if (!goal.isAllowed(req))
|
||||
throw InvalidPath("cannot build '%s' in recursive Nix because path is unknown", req.to_string(*next));
|
||||
}
|
||||
|
||||
next->buildPaths(paths, buildMode);
|
||||
|
||||
for (auto & path : paths) {
|
||||
if (!path.path.isDerivation()) continue;
|
||||
auto outputs = next->queryDerivationOutputMap(path.path);
|
||||
for (auto & output : outputs)
|
||||
if (wantOutput(output.first, path.outputs))
|
||||
newPaths.insert(output.second);
|
||||
auto p = std::get_if<DerivedPath::Built>(&path);
|
||||
if (!p) continue;
|
||||
auto & bfd = *p;
|
||||
auto outputs = next->queryDerivationOutputMap(bfd.drvPath);
|
||||
for (auto & [outputName, outputPath] : outputs)
|
||||
if (wantOutput(outputName, bfd.outputs))
|
||||
newPaths.insert(outputPath);
|
||||
}
|
||||
|
||||
StorePathSet closure;
|
||||
|
@ -1358,7 +1380,7 @@ struct RestrictedStore : public virtual RestrictedStoreConfig, public virtual Lo
|
|||
void addSignatures(const StorePath & storePath, const StringSet & sigs) override
|
||||
{ unsupported("addSignatures"); }
|
||||
|
||||
void queryMissing(const std::vector<StorePathWithOutputs> & targets,
|
||||
void queryMissing(const std::vector<DerivedPath> & targets,
|
||||
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
|
||||
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
|
||||
already present. Probably not a big deal. */
|
||||
|
||||
std::vector<StorePathWithOutputs> allowed;
|
||||
for (auto & path : targets) {
|
||||
if (goal.isAllowed(path.path))
|
||||
allowed.emplace_back(path);
|
||||
std::vector<DerivedPath> allowed;
|
||||
for (auto & req : targets) {
|
||||
if (goal.isAllowed(req))
|
||||
allowed.emplace_back(req);
|
||||
else
|
||||
unknown.insert(path.path);
|
||||
unknown.insert(pathPartOfReq(req));
|
||||
}
|
||||
|
||||
next->queryMissing(allowed, willBuild, willSubstitute,
|
||||
|
|
|
@ -116,6 +116,7 @@ struct LocalDerivationGoal : public DerivationGoal
|
|||
{
|
||||
return inputPaths.count(path) || addedPaths.count(path);
|
||||
}
|
||||
bool isAllowed(const DerivedPath & req);
|
||||
|
||||
friend struct RestrictedStore;
|
||||
|
||||
|
|
|
@ -226,14 +226,14 @@ void Worker::waitForAWhile(GoalPtr goal)
|
|||
|
||||
void Worker::run(const Goals & _topGoals)
|
||||
{
|
||||
std::vector<nix::StorePathWithOutputs> topPaths;
|
||||
std::vector<nix::DerivedPath> topPaths;
|
||||
|
||||
for (auto & i : _topGoals) {
|
||||
topGoals.insert(i);
|
||||
if (auto goal = dynamic_cast<DerivationGoal *>(i.get())) {
|
||||
topPaths.push_back({goal->drvPath, goal->wantedOutputs});
|
||||
topPaths.push_back(DerivedPath::Built{goal->drvPath, goal->wantedOutputs});
|
||||
} else if (auto goal = dynamic_cast<PathSubstitutionGoal *>(i.get())) {
|
||||
topPaths.push_back({goal->storePath});
|
||||
topPaths.push_back(DerivedPath::Opaque{goal->storePath});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "monitor-fd.hh"
|
||||
#include "worker-protocol.hh"
|
||||
#include "store-api.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "finally.hh"
|
||||
#include "affinity.hh"
|
||||
#include "archive.hh"
|
||||
|
@ -259,6 +260,18 @@ static void writeValidPathInfo(
|
|||
}
|
||||
}
|
||||
|
||||
static std::vector<DerivedPath> readDerivedPaths(Store & store, unsigned int clientVersion, Source & from)
|
||||
{
|
||||
std::vector<DerivedPath> reqs;
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 29) {
|
||||
reqs = worker_proto::read(store, from, Phantom<std::vector<DerivedPath>> {});
|
||||
} else {
|
||||
for (auto & s : readStrings<Strings>(from))
|
||||
reqs.push_back(parsePathWithOutputs(store, s).toDerivedPath());
|
||||
}
|
||||
return reqs;
|
||||
}
|
||||
|
||||
static void performOp(TunnelLogger * logger, ref<Store> store,
|
||||
TrustedFlag trusted, RecursiveFlag recursive, unsigned int clientVersion,
|
||||
Source & from, BufferedSink & to, unsigned int op)
|
||||
|
@ -493,9 +506,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
|||
}
|
||||
|
||||
case wopBuildPaths: {
|
||||
std::vector<StorePathWithOutputs> drvs;
|
||||
for (auto & s : readStrings<Strings>(from))
|
||||
drvs.push_back(store->parsePathWithOutputs(s));
|
||||
auto drvs = readDerivedPaths(*store, clientVersion, from);
|
||||
BuildMode mode = bmNormal;
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 15) {
|
||||
mode = (BuildMode) readInt(from);
|
||||
|
@ -859,9 +870,7 @@ static void performOp(TunnelLogger * logger, ref<Store> store,
|
|||
}
|
||||
|
||||
case wopQueryMissing: {
|
||||
std::vector<StorePathWithOutputs> targets;
|
||||
for (auto & s : readStrings<Strings>(from))
|
||||
targets.push_back(store->parsePathWithOutputs(s));
|
||||
auto targets = readDerivedPaths(*store, clientVersion, from);
|
||||
logger->startWork();
|
||||
StorePathSet willBuild, willSubstitute, unknown;
|
||||
uint64_t downloadSize, narSize;
|
||||
|
|
|
@ -590,14 +590,6 @@ std::map<std::string, Hash> staticOutputHashes(Store& store, const Derivation& d
|
|||
}
|
||||
|
||||
|
||||
std::string StorePathWithOutputs::to_string(const Store & store) const
|
||||
{
|
||||
return outputs.empty()
|
||||
? store.printStorePath(path)
|
||||
: store.printStorePath(path) + "!" + concatStringsSep(",", outputs);
|
||||
}
|
||||
|
||||
|
||||
bool wantOutput(const string & output, const std::set<string> & wanted)
|
||||
{
|
||||
return wanted.empty() || wanted.find(output) != wanted.end();
|
||||
|
|
77
src/libstore/derived-path.cc
Normal file
77
src/libstore/derived-path.cc
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "derived-path.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace nix {
|
||||
|
||||
nlohmann::json DerivedPath::Opaque::toJSON(ref<Store> store) const {
|
||||
nlohmann::json res;
|
||||
res["path"] = store->printStorePath(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
nlohmann::json DerivedPathWithHints::Built::toJSON(ref<Store> store) const {
|
||||
nlohmann::json res;
|
||||
res["drvPath"] = store->printStorePath(drvPath);
|
||||
for (const auto& [output, path] : outputs) {
|
||||
res["outputs"][output] = path ? store->printStorePath(*path) : "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nlohmann::json derivedPathsWithHintsToJSON(const DerivedPathsWithHints & buildables, ref<Store> store) {
|
||||
auto res = nlohmann::json::array();
|
||||
for (const DerivedPathWithHints & buildable : buildables) {
|
||||
std::visit([&res, store](const auto & buildable) {
|
||||
res.push_back(buildable.toJSON(store));
|
||||
}, buildable.raw());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::string DerivedPath::Opaque::to_string(const Store & store) const {
|
||||
return store.printStorePath(path);
|
||||
}
|
||||
|
||||
std::string DerivedPath::Built::to_string(const Store & store) const {
|
||||
return store.printStorePath(drvPath)
|
||||
+ "!"
|
||||
+ (outputs.empty() ? std::string { "*" } : concatStringsSep(",", outputs));
|
||||
}
|
||||
|
||||
std::string DerivedPath::to_string(const Store & store) const
|
||||
{
|
||||
return std::visit(
|
||||
[&](const auto & req) { return req.to_string(store); },
|
||||
this->raw());
|
||||
}
|
||||
|
||||
|
||||
DerivedPath::Opaque DerivedPath::Opaque::parse(const Store & store, std::string_view s)
|
||||
{
|
||||
return {store.parseStorePath(s)};
|
||||
}
|
||||
|
||||
DerivedPath::Built DerivedPath::Built::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};
|
||||
}
|
||||
|
||||
DerivedPath DerivedPath::parse(const Store & store, std::string_view s)
|
||||
{
|
||||
size_t n = s.find("!");
|
||||
return n == s.npos
|
||||
? (DerivedPath) DerivedPath::Opaque::parse(store, s)
|
||||
: (DerivedPath) DerivedPath::Built::parse(store, s);
|
||||
}
|
||||
|
||||
}
|
129
src/libstore/derived-path.hh
Normal file
129
src/libstore/derived-path.hh
Normal file
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
|
||||
#include "util.hh"
|
||||
#include "path.hh"
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace nix {
|
||||
|
||||
class Store;
|
||||
|
||||
/**
|
||||
* An opaque derived path.
|
||||
*
|
||||
* Opaque derived paths are just store paths, and fully evaluated. They
|
||||
* cannot be simplified further. Since they are opaque, they cannot be
|
||||
* built, but they can fetched.
|
||||
*/
|
||||
struct DerivedPathOpaque {
|
||||
StorePath path;
|
||||
|
||||
nlohmann::json toJSON(ref<Store> store) const;
|
||||
std::string to_string(const Store & store) const;
|
||||
static DerivedPathOpaque parse(const Store & store, std::string_view);
|
||||
};
|
||||
|
||||
/**
|
||||
* A derived path that is built from a derivation
|
||||
*
|
||||
* Built derived paths are pair of a derivation and some output names.
|
||||
* They are evaluated by building the derivation, and then replacing the
|
||||
* output names with the resulting outputs.
|
||||
*
|
||||
* Note that does mean a derived store paths evaluates to multiple
|
||||
* opaque paths, which is sort of icky as expressions are supposed to
|
||||
* evaluate to single values. Perhaps this should have just a single
|
||||
* output name.
|
||||
*/
|
||||
struct DerivedPathBuilt {
|
||||
StorePath drvPath;
|
||||
std::set<std::string> outputs;
|
||||
|
||||
std::string to_string(const Store & store) const;
|
||||
static DerivedPathBuilt parse(const Store & store, std::string_view);
|
||||
};
|
||||
|
||||
using _DerivedPathRaw = std::variant<
|
||||
DerivedPathOpaque,
|
||||
DerivedPathBuilt
|
||||
>;
|
||||
|
||||
/**
|
||||
* A "derived path" is a very simple sort of expression that evaluates
|
||||
* to (concrete) store path. It is either:
|
||||
*
|
||||
* - opaque, in which case it is just a concrete store path with
|
||||
* possibly no known derivation
|
||||
*
|
||||
* - built, in which case it is a pair of a derivation path and an
|
||||
* output name.
|
||||
*/
|
||||
struct DerivedPath : _DerivedPathRaw {
|
||||
using Raw = _DerivedPathRaw;
|
||||
using Raw::Raw;
|
||||
|
||||
using Opaque = DerivedPathOpaque;
|
||||
using Built = DerivedPathBuilt;
|
||||
|
||||
inline const Raw & raw() const {
|
||||
return static_cast<const Raw &>(*this);
|
||||
}
|
||||
|
||||
std::string to_string(const Store & store) const;
|
||||
static DerivedPath parse(const Store & store, std::string_view);
|
||||
};
|
||||
|
||||
/**
|
||||
* A built derived path with hints in the form of optional concrete output paths.
|
||||
*
|
||||
* See 'DerivedPathWithHints' for more an explanation.
|
||||
*/
|
||||
struct DerivedPathWithHintsBuilt {
|
||||
StorePath drvPath;
|
||||
std::map<std::string, std::optional<StorePath>> outputs;
|
||||
|
||||
nlohmann::json toJSON(ref<Store> store) const;
|
||||
static DerivedPathWithHintsBuilt parse(const Store & store, std::string_view);
|
||||
};
|
||||
|
||||
using _DerivedPathWithHintsRaw = std::variant<
|
||||
DerivedPath::Opaque,
|
||||
DerivedPathWithHintsBuilt
|
||||
>;
|
||||
|
||||
/**
|
||||
* A derived path with hints in the form of optional concrete output paths in the built case.
|
||||
*
|
||||
* This type is currently just used by the CLI. The paths are filled in
|
||||
* during evaluation for derivations that know what paths they will
|
||||
* produce in advanced, i.e. input-addressed or fixed-output content
|
||||
* addressed derivations.
|
||||
*
|
||||
* That isn't very good, because it puts floating content-addressed
|
||||
* derivations "at a disadvantage". It would be better to never rely on
|
||||
* the output path of unbuilt derivations, and exclusively use the
|
||||
* realizations types to work with built derivations' concrete output
|
||||
* paths.
|
||||
*/
|
||||
// FIXME Stop using and delete this, or if that is not possible move out of libstore to libcmd.
|
||||
struct DerivedPathWithHints : _DerivedPathWithHintsRaw {
|
||||
using Raw = _DerivedPathWithHintsRaw;
|
||||
using Raw::Raw;
|
||||
|
||||
using Opaque = DerivedPathOpaque;
|
||||
using Built = DerivedPathWithHintsBuilt;
|
||||
|
||||
inline const Raw & raw() const {
|
||||
return static_cast<const Raw &>(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<DerivedPathWithHints> DerivedPathsWithHints;
|
||||
|
||||
nlohmann::json derivedPathsWithHintsToJSON(const DerivedPathsWithHints & buildables, ref<Store> store);
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include "remote-store.hh"
|
||||
#include "serve-protocol.hh"
|
||||
#include "store-api.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "worker-protocol.hh"
|
||||
#include "ssh.hh"
|
||||
#include "derivations.hh"
|
||||
|
@ -266,14 +267,23 @@ public:
|
|||
return status;
|
||||
}
|
||||
|
||||
void buildPaths(const std::vector<StorePathWithOutputs> & drvPaths, BuildMode buildMode) override
|
||||
void buildPaths(const std::vector<DerivedPath> & drvPaths, BuildMode buildMode) override
|
||||
{
|
||||
auto conn(connections->get());
|
||||
|
||||
conn->to << cmdBuildPaths;
|
||||
Strings ss;
|
||||
for (auto & p : drvPaths)
|
||||
ss.push_back(p.to_string(*this));
|
||||
for (auto & p : drvPaths) {
|
||||
auto sOrDrvPath = StorePathWithOutputs::tryFromDerivedPath(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;
|
||||
|
||||
putBuildSettings(*conn);
|
||||
|
|
|
@ -117,7 +117,7 @@ std::optional<ContentAddress> getDerivationCA(const BasicDerivation & drv)
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
|
||||
void Store::queryMissing(const std::vector<DerivedPath> & targets,
|
||||
StorePathSet & willBuild_, StorePathSet & willSubstitute_, StorePathSet & unknown_,
|
||||
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_});
|
||||
|
||||
std::function<void(StorePathWithOutputs)> doPath;
|
||||
std::function<void(DerivedPath)> doPath;
|
||||
|
||||
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)
|
||||
pool.enqueue(std::bind(doPath, StorePathWithOutputs { i.first, i.second }));
|
||||
pool.enqueue(std::bind(doPath, DerivedPath::Built { i.first, i.second }));
|
||||
};
|
||||
|
||||
auto checkOutput = [&](
|
||||
|
@ -177,24 +177,25 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
|
|||
drvState->outPaths.insert(outPath);
|
||||
if (!drvState->left) {
|
||||
for (auto & path : drvState->outPaths)
|
||||
pool.enqueue(std::bind(doPath, StorePathWithOutputs { path } ));
|
||||
pool.enqueue(std::bind(doPath, DerivedPath::Opaque { path } ));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
doPath = [&](const StorePathWithOutputs & path) {
|
||||
doPath = [&](const DerivedPath & req) {
|
||||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
if (!state->done.insert(path.to_string(*this)).second) return;
|
||||
if (!state->done.insert(req.to_string(*this)).second) return;
|
||||
}
|
||||
|
||||
if (path.path.isDerivation()) {
|
||||
if (!isValidPath(path.path)) {
|
||||
std::visit(overloaded {
|
||||
[&](DerivedPath::Built bfd) {
|
||||
if (!isValidPath(bfd.drvPath)) {
|
||||
// FIXME: we could try to substitute the derivation.
|
||||
auto state(state_.lock());
|
||||
state->unknown.insert(path.path);
|
||||
state->unknown.insert(bfd.drvPath);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -202,52 +203,54 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
|
|||
/* true for regular derivations, and CA derivations for which we
|
||||
have a trust mapping for all wanted outputs. */
|
||||
auto knownOutputPaths = true;
|
||||
for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(path.path)) {
|
||||
for (auto & [outputName, pathOpt] : queryPartialDerivationOutputMap(bfd.drvPath)) {
|
||||
if (!pathOpt) {
|
||||
knownOutputPaths = false;
|
||||
break;
|
||||
}
|
||||
if (wantOutput(outputName, path.outputs) && !isValidPath(*pathOpt))
|
||||
if (wantOutput(outputName, bfd.outputs) && !isValidPath(*pathOpt))
|
||||
invalid.insert(*pathOpt);
|
||||
}
|
||||
if (knownOutputPaths && invalid.empty()) return;
|
||||
|
||||
auto drv = make_ref<Derivation>(derivationFromPath(path.path));
|
||||
ParsedDerivation parsedDrv(StorePath(path.path), *drv);
|
||||
auto drv = make_ref<Derivation>(derivationFromPath(bfd.drvPath));
|
||||
ParsedDerivation parsedDrv(StorePath(bfd.drvPath), *drv);
|
||||
|
||||
if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
|
||||
auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
|
||||
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
|
||||
mustBuildDrv(path.path, *drv);
|
||||
mustBuildDrv(bfd.drvPath, *drv);
|
||||
|
||||
} else {
|
||||
},
|
||||
[&](DerivedPath::Opaque bo) {
|
||||
|
||||
if (isValidPath(path.path)) return;
|
||||
if (isValidPath(bo.path)) return;
|
||||
|
||||
SubstitutablePathInfos infos;
|
||||
querySubstitutablePathInfos({{path.path, std::nullopt}}, infos);
|
||||
querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos);
|
||||
|
||||
if (infos.empty()) {
|
||||
auto state(state_.lock());
|
||||
state->unknown.insert(path.path);
|
||||
state->unknown.insert(bo.path);
|
||||
return;
|
||||
}
|
||||
|
||||
auto info = infos.find(path.path);
|
||||
auto info = infos.find(bo.path);
|
||||
assert(info != infos.end());
|
||||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
state->willSubstitute.insert(path.path);
|
||||
state->willSubstitute.insert(bo.path);
|
||||
state->downloadSize += info->second.downloadSize;
|
||||
state->narSize += info->second.narSize;
|
||||
}
|
||||
|
||||
for (auto & ref : info->second.references)
|
||||
pool.enqueue(std::bind(doPath, StorePathWithOutputs { ref }));
|
||||
}
|
||||
pool.enqueue(std::bind(doPath, DerivedPath::Opaque { ref }));
|
||||
},
|
||||
}, req.raw());
|
||||
};
|
||||
|
||||
for (auto & path : targets)
|
||||
|
|
71
src/libstore/path-with-outputs.cc
Normal file
71
src/libstore/path-with-outputs.cc
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include "path-with-outputs.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
std::string StorePathWithOutputs::to_string(const Store & store) const
|
||||
{
|
||||
return outputs.empty()
|
||||
? store.printStorePath(path)
|
||||
: store.printStorePath(path) + "!" + concatStringsSep(",", outputs);
|
||||
}
|
||||
|
||||
|
||||
DerivedPath StorePathWithOutputs::toDerivedPath() const
|
||||
{
|
||||
if (!outputs.empty() || path.isDerivation())
|
||||
return DerivedPath::Built { path, outputs };
|
||||
else
|
||||
return DerivedPath::Opaque { path };
|
||||
}
|
||||
|
||||
|
||||
std::vector<DerivedPath> toDerivedPaths(const std::vector<StorePathWithOutputs> ss)
|
||||
{
|
||||
std::vector<DerivedPath> reqs;
|
||||
for (auto & s : ss) reqs.push_back(s.toDerivedPath());
|
||||
return reqs;
|
||||
}
|
||||
|
||||
|
||||
std::variant<StorePathWithOutputs, StorePath> StorePathWithOutputs::tryFromDerivedPath(const DerivedPath & p)
|
||||
{
|
||||
return std::visit(overloaded {
|
||||
[&](DerivedPath::Opaque 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 };
|
||||
},
|
||||
[&](DerivedPath::Built bfd) -> std::variant<StorePathWithOutputs, StorePath> {
|
||||
return StorePathWithOutputs { bfd.drvPath, bfd.outputs };
|
||||
},
|
||||
}, p.raw());
|
||||
}
|
||||
|
||||
|
||||
std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s)
|
||||
{
|
||||
size_t n = s.find("!");
|
||||
return n == s.npos
|
||||
? std::make_pair(s, std::set<string>())
|
||||
: std::make_pair(((std::string_view) s).substr(0, n),
|
||||
tokenizeString<std::set<string>>(((std::string_view) s).substr(n + 1), ","));
|
||||
}
|
||||
|
||||
|
||||
StorePathWithOutputs parsePathWithOutputs(const Store & store, std::string_view pathWithOutputs)
|
||||
{
|
||||
auto [path, outputs] = parsePathWithOutputs(pathWithOutputs);
|
||||
return StorePathWithOutputs { store.parseStorePath(path), std::move(outputs) };
|
||||
}
|
||||
|
||||
|
||||
StorePathWithOutputs followLinksToStorePathWithOutputs(const Store & store, std::string_view pathWithOutputs)
|
||||
{
|
||||
auto [path, outputs] = parsePathWithOutputs(pathWithOutputs);
|
||||
return StorePathWithOutputs { store.followLinksToStorePath(path), std::move(outputs) };
|
||||
}
|
||||
|
||||
}
|
35
src/libstore/path-with-outputs.hh
Normal file
35
src/libstore/path-with-outputs.hh
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include "path.hh"
|
||||
#include "derived-path.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct StorePathWithOutputs
|
||||
{
|
||||
StorePath path;
|
||||
std::set<std::string> outputs;
|
||||
|
||||
std::string to_string(const Store & store) const;
|
||||
|
||||
DerivedPath toDerivedPath() const;
|
||||
|
||||
static std::variant<StorePathWithOutputs, StorePath> tryFromDerivedPath(const DerivedPath &);
|
||||
};
|
||||
|
||||
std::vector<DerivedPath> toDerivedPaths(const std::vector<StorePathWithOutputs>);
|
||||
|
||||
std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s);
|
||||
|
||||
class Store;
|
||||
|
||||
/* Split a string specifying a derivation and a set of outputs
|
||||
(/nix/store/hash-foo!out1,out2,...) into the derivation path
|
||||
and the outputs. */
|
||||
StorePathWithOutputs parsePathWithOutputs(const Store & store, std::string_view pathWithOutputs);
|
||||
|
||||
StorePathWithOutputs followLinksToStorePathWithOutputs(const Store & store, std::string_view pathWithOutputs);
|
||||
|
||||
}
|
|
@ -82,19 +82,4 @@ PathSet Store::printStorePathSet(const StorePathSet & paths) const
|
|||
return res;
|
||||
}
|
||||
|
||||
std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s)
|
||||
{
|
||||
size_t n = s.find("!");
|
||||
return n == s.npos
|
||||
? std::make_pair(s, std::set<string>())
|
||||
: std::make_pair(((std::string_view) s).substr(0, n),
|
||||
tokenizeString<std::set<string>>(((std::string_view) s).substr(n + 1), ","));
|
||||
}
|
||||
|
||||
StorePathWithOutputs Store::parsePathWithOutputs(const std::string & s)
|
||||
{
|
||||
auto [path, outputs] = nix::parsePathWithOutputs(s);
|
||||
return {parseStorePath(path), std::move(outputs)};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -69,16 +69,6 @@ typedef std::map<StorePath, std::optional<ContentAddress>> StorePathCAMap;
|
|||
/* Extension of derivations in the Nix store. */
|
||||
const std::string drvExtension = ".drv";
|
||||
|
||||
struct StorePathWithOutputs
|
||||
{
|
||||
StorePath path;
|
||||
std::set<std::string> outputs;
|
||||
|
||||
std::string to_string(const Store & store) const;
|
||||
};
|
||||
|
||||
std::pair<std::string_view, StringSet> parsePathWithOutputs(std::string_view s);
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "serialise.hh"
|
||||
#include "util.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "remote-fs-accessor.hh"
|
||||
#include "remote-store.hh"
|
||||
#include "worker-protocol.hh"
|
||||
|
@ -50,6 +51,19 @@ void write(const Store & store, Sink & out, const ContentAddress & ca)
|
|||
out << renderContentAddress(ca);
|
||||
}
|
||||
|
||||
|
||||
DerivedPath read(const Store & store, Source & from, Phantom<DerivedPath> _)
|
||||
{
|
||||
auto s = readString(from);
|
||||
return DerivedPath::parse(store, s);
|
||||
}
|
||||
|
||||
void write(const Store & store, Sink & out, const DerivedPath & req)
|
||||
{
|
||||
out << req.to_string(store);
|
||||
}
|
||||
|
||||
|
||||
Realisation read(const Store & store, Source & from, Phantom<Realisation> _)
|
||||
{
|
||||
std::string rawInput = readString(from);
|
||||
|
@ -58,8 +72,12 @@ Realisation read(const Store & store, Source & from, Phantom<Realisation> _)
|
|||
"remote-protocol"
|
||||
);
|
||||
}
|
||||
|
||||
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> _)
|
||||
{
|
||||
|
@ -652,16 +670,36 @@ std::optional<const Realisation> RemoteStore::queryRealisation(const DrvOutput &
|
|||
return {Realisation{.id = id, .outPath = *outPaths.begin()}};
|
||||
}
|
||||
|
||||
static void writeDerivedPaths(RemoteStore & store, ConnectionHandle & conn, const std::vector<DerivedPath> & 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::tryFromDerivedPath(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<DerivedPath> & drvPaths, BuildMode buildMode)
|
||||
{
|
||||
auto conn(getConnection());
|
||||
conn->to << wopBuildPaths;
|
||||
assert(GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13);
|
||||
Strings ss;
|
||||
for (auto & p : drvPaths)
|
||||
ss.push_back(p.to_string(*this));
|
||||
conn->to << ss;
|
||||
writeDerivedPaths(*this, conn, drvPaths);
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15)
|
||||
conn->to << buildMode;
|
||||
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<DerivedPath> & targets,
|
||||
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
|
||||
uint64_t & downloadSize, uint64_t & narSize)
|
||||
{
|
||||
|
@ -811,10 +849,7 @@ void RemoteStore::queryMissing(const std::vector<StorePathWithOutputs> & targets
|
|||
// to prevent a deadlock.
|
||||
goto fallback;
|
||||
conn->to << wopQueryMissing;
|
||||
Strings ss;
|
||||
for (auto & p : targets)
|
||||
ss.push_back(p.to_string(*this));
|
||||
conn->to << ss;
|
||||
writeDerivedPaths(*this, conn, targets);
|
||||
conn.processStderr();
|
||||
willBuild = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
|
||||
willSubstitute = worker_proto::read(*this, conn->from, Phantom<StorePathSet> {});
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
|
||||
std::optional<const Realisation> queryRealisation(const DrvOutput &) override;
|
||||
|
||||
void buildPaths(const std::vector<StorePathWithOutputs> & paths, BuildMode buildMode) override;
|
||||
void buildPaths(const std::vector<DerivedPath> & paths, BuildMode buildMode) override;
|
||||
|
||||
BuildResult buildDerivation(const StorePath & drvPath, const BasicDerivation & drv,
|
||||
BuildMode buildMode) override;
|
||||
|
@ -108,7 +108,7 @@ public:
|
|||
|
||||
void addSignatures(const StorePath & storePath, const StringSet & sigs) override;
|
||||
|
||||
void queryMissing(const std::vector<StorePathWithOutputs> & targets,
|
||||
void queryMissing(const std::vector<DerivedPath> & targets,
|
||||
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
|
||||
uint64_t & downloadSize, uint64_t & narSize) override;
|
||||
|
||||
|
|
|
@ -53,13 +53,6 @@ StorePath Store::followLinksToStorePath(std::string_view path) const
|
|||
}
|
||||
|
||||
|
||||
StorePathWithOutputs Store::followLinksToStorePathWithOutputs(std::string_view path) const
|
||||
{
|
||||
auto [path2, outputs] = nix::parsePathWithOutputs(path);
|
||||
return StorePathWithOutputs { followLinksToStorePath(path2), std::move(outputs) };
|
||||
}
|
||||
|
||||
|
||||
/* Store paths have the following form:
|
||||
|
||||
<realized-path> = <store>/<h>-<name>
|
||||
|
@ -536,10 +529,10 @@ void Store::queryPathInfo(const StorePath & storePath,
|
|||
|
||||
void Store::substitutePaths(const StorePathSet & paths)
|
||||
{
|
||||
std::vector<StorePathWithOutputs> paths2;
|
||||
std::vector<DerivedPath> paths2;
|
||||
for (auto & path : paths)
|
||||
if (!path.isDerivation())
|
||||
paths2.push_back({path});
|
||||
paths2.push_back(DerivedPath::Opaque{path});
|
||||
uint64_t downloadSize, narSize;
|
||||
StorePathSet willBuild, willSubstitute, unknown;
|
||||
queryMissing(paths2,
|
||||
|
@ -547,8 +540,8 @@ void Store::substitutePaths(const StorePathSet & paths)
|
|||
|
||||
if (!willSubstitute.empty())
|
||||
try {
|
||||
std::vector<StorePathWithOutputs> subs;
|
||||
for (auto & p : willSubstitute) subs.push_back({p});
|
||||
std::vector<DerivedPath> subs;
|
||||
for (auto & p : willSubstitute) subs.push_back(DerivedPath::Opaque{p});
|
||||
buildPaths(subs);
|
||||
} catch (Error & e) {
|
||||
logWarning(e.info());
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "realisation.hh"
|
||||
#include "path.hh"
|
||||
#include "derived-path.hh"
|
||||
#include "hash.hh"
|
||||
#include "content-address.hh"
|
||||
#include "serialise.hh"
|
||||
|
@ -261,11 +262,6 @@ public:
|
|||
|
||||
PathSet printStorePathSet(const StorePathSet & path) const;
|
||||
|
||||
/* Split a string specifying a derivation and a set of outputs
|
||||
(/nix/store/hash-foo!out1,out2,...) into the derivation path
|
||||
and the outputs. */
|
||||
StorePathWithOutputs parsePathWithOutputs(const string & s);
|
||||
|
||||
/* Display a set of paths in human-readable form (i.e., between quotes
|
||||
and separated by commas). */
|
||||
std::string showPaths(const StorePathSet & paths);
|
||||
|
@ -289,8 +285,6 @@ public:
|
|||
result. */
|
||||
StorePath followLinksToStorePath(std::string_view path) const;
|
||||
|
||||
StorePathWithOutputs followLinksToStorePathWithOutputs(std::string_view path) const;
|
||||
|
||||
/* Constructs a unique store path name. */
|
||||
StorePath makeStorePath(std::string_view type,
|
||||
std::string_view hash, std::string_view name) const;
|
||||
|
@ -500,7 +494,7 @@ public:
|
|||
recursively building any sub-derivations. For inputs that are
|
||||
not derivations, substitute them. */
|
||||
virtual void buildPaths(
|
||||
const std::vector<StorePathWithOutputs> & paths,
|
||||
const std::vector<DerivedPath> & paths,
|
||||
BuildMode buildMode = bmNormal);
|
||||
|
||||
/* Build a single non-materialized derivation (i.e. not from an
|
||||
|
@ -662,7 +656,7 @@ public:
|
|||
/* 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
|
||||
that will be substituted. */
|
||||
virtual void queryMissing(const std::vector<StorePathWithOutputs> & targets,
|
||||
virtual void queryMissing(const std::vector<DerivedPath> & targets,
|
||||
StorePathSet & willBuild, StorePathSet & willSubstitute, StorePathSet & unknown,
|
||||
uint64_t & downloadSize, uint64_t & narSize);
|
||||
|
||||
|
|
|
@ -86,9 +86,11 @@ namespace worker_proto {
|
|||
MAKE_WORKER_PROTO(, std::string);
|
||||
MAKE_WORKER_PROTO(, StorePath);
|
||||
MAKE_WORKER_PROTO(, ContentAddress);
|
||||
MAKE_WORKER_PROTO(, DerivedPath);
|
||||
MAKE_WORKER_PROTO(, Realisation);
|
||||
MAKE_WORKER_PROTO(, DrvOutput);
|
||||
|
||||
MAKE_WORKER_PROTO(template<typename T>, std::vector<T>);
|
||||
MAKE_WORKER_PROTO(template<typename T>, std::set<T>);
|
||||
|
||||
#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<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>
|
||||
std::set<T> read(const Store & store, Source & from, Phantom<std::set<T>> _)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "affinity.hh"
|
||||
#include "util.hh"
|
||||
#include "shared.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "eval.hh"
|
||||
#include "eval-inline.hh"
|
||||
#include "get-drvs.hh"
|
||||
|
@ -321,7 +322,8 @@ static void main_nix_build(int argc, char * * argv)
|
|||
|
||||
state->printStats();
|
||||
|
||||
auto buildPaths = [&](const std::vector<StorePathWithOutputs> & paths) {
|
||||
auto buildPaths = [&](const std::vector<StorePathWithOutputs> & paths0) {
|
||||
auto paths = toDerivedPaths(paths0);
|
||||
/* Note: we do this even when !printMissing to efficiently
|
||||
fetch binary cache data. */
|
||||
uint64_t downloadSize, narSize;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "globals.hh"
|
||||
#include "names.hh"
|
||||
#include "profiles.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "shared.hh"
|
||||
#include "store-api.hh"
|
||||
#include "local-fs-store.hh"
|
||||
|
@ -418,13 +419,13 @@ static void queryInstSources(EvalState & state,
|
|||
|
||||
static void printMissing(EvalState & state, DrvInfos & elems)
|
||||
{
|
||||
std::vector<StorePathWithOutputs> targets;
|
||||
std::vector<DerivedPath> targets;
|
||||
for (auto & i : elems) {
|
||||
Path drvPath = i.queryDrvPath();
|
||||
if (drvPath != "")
|
||||
targets.push_back({state.store->parseStorePath(drvPath)});
|
||||
targets.push_back(DerivedPath::Built{state.store->parseStorePath(drvPath)});
|
||||
else
|
||||
targets.push_back({state.store->parseStorePath(i.queryOutPath())});
|
||||
targets.push_back(DerivedPath::Opaque{state.store->parseStorePath(i.queryOutPath())});
|
||||
}
|
||||
|
||||
printMissing(state.store, targets);
|
||||
|
@ -693,17 +694,18 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs)
|
|||
if (globals.forceName != "")
|
||||
drv.setName(globals.forceName);
|
||||
|
||||
if (drv.queryDrvPath() != "") {
|
||||
std::vector<StorePathWithOutputs> paths{{globals.state->store->parseStorePath(drv.queryDrvPath())}};
|
||||
printMissing(globals.state->store, paths);
|
||||
if (globals.dryRun) return;
|
||||
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()));
|
||||
}
|
||||
std::vector<DerivedPath> paths {
|
||||
(drv.queryDrvPath() != "")
|
||||
? (DerivedPath) (DerivedPath::Built {
|
||||
globals.state->store->parseStorePath(drv.queryDrvPath())
|
||||
})
|
||||
: (DerivedPath) (DerivedPath::Opaque {
|
||||
globals.state->store->parseStorePath(drv.queryOutPath())
|
||||
}),
|
||||
};
|
||||
printMissing(globals.state->store, paths);
|
||||
if (globals.dryRun) return;
|
||||
globals.state->store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal);
|
||||
|
||||
debug(format("switching to new user environment"));
|
||||
Path generation = createGeneration(
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "util.hh"
|
||||
#include "derivations.hh"
|
||||
#include "store-api.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "local-fs-store.hh"
|
||||
#include "globals.hh"
|
||||
#include "shared.hh"
|
||||
|
@ -41,7 +42,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
|||
drvsToBuild.push_back({state.store->parseStorePath(i.queryDrvPath())});
|
||||
|
||||
debug(format("building user environment dependencies"));
|
||||
state.store->buildPaths(drvsToBuild, state.repair ? bmRepair : bmNormal);
|
||||
state.store->buildPaths(
|
||||
toDerivedPaths(drvsToBuild),
|
||||
state.repair ? bmRepair : bmNormal);
|
||||
|
||||
/* Construct the whole top level derivation. */
|
||||
StorePathSet references;
|
||||
|
@ -136,7 +139,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
|||
debug("building user environment");
|
||||
std::vector<StorePathWithOutputs> topLevelDrvs;
|
||||
topLevelDrvs.push_back({topLevelDrv});
|
||||
state.store->buildPaths(topLevelDrvs, state.repair ? bmRepair : bmNormal);
|
||||
state.store->buildPaths(
|
||||
toDerivedPaths(topLevelDrvs),
|
||||
state.repair ? bmRepair : bmNormal);
|
||||
|
||||
/* Switch the current user environment to the output path. */
|
||||
auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "worker-protocol.hh"
|
||||
#include "graphml.hh"
|
||||
#include "legacy.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
@ -62,7 +63,7 @@ static PathSet realisePath(StorePathWithOutputs path, bool build = true)
|
|||
auto store2 = std::dynamic_pointer_cast<LocalFSStore>(store);
|
||||
|
||||
if (path.path.isDerivation()) {
|
||||
if (build) store->buildPaths({path});
|
||||
if (build) store->buildPaths({path.toDerivedPath()});
|
||||
auto outputPaths = store->queryDerivationOutputMap(path.path);
|
||||
Derivation drv = store->derivationFromPath(path.path);
|
||||
rootNr++;
|
||||
|
@ -128,11 +129,13 @@ static void opRealise(Strings opFlags, Strings opArgs)
|
|||
|
||||
std::vector<StorePathWithOutputs> paths;
|
||||
for (auto & i : opArgs)
|
||||
paths.push_back(store->followLinksToStorePathWithOutputs(i));
|
||||
paths.push_back(followLinksToStorePathWithOutputs(*store, i));
|
||||
|
||||
uint64_t downloadSize, narSize;
|
||||
StorePathSet willBuild, willSubstitute, unknown;
|
||||
store->queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize, narSize);
|
||||
store->queryMissing(
|
||||
toDerivedPaths(paths),
|
||||
willBuild, willSubstitute, unknown, downloadSize, narSize);
|
||||
|
||||
if (ignoreUnknown) {
|
||||
std::vector<StorePathWithOutputs> paths2;
|
||||
|
@ -148,7 +151,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
|
|||
if (dryRun) return;
|
||||
|
||||
/* Build all paths at the same time to exploit parallelism. */
|
||||
store->buildPaths(paths, buildMode);
|
||||
store->buildPaths(toDerivedPaths(paths), buildMode);
|
||||
|
||||
if (!ignoreUnknown)
|
||||
for (auto & i : paths) {
|
||||
|
@ -873,13 +876,13 @@ static void opServe(Strings opFlags, Strings opArgs)
|
|||
|
||||
std::vector<StorePathWithOutputs> paths;
|
||||
for (auto & s : readStrings<Strings>(in))
|
||||
paths.push_back(store->parsePathWithOutputs(s));
|
||||
paths.push_back(parsePathWithOutputs(*store, s));
|
||||
|
||||
getBuildSettings();
|
||||
|
||||
try {
|
||||
MonitorFdHup monitor(in.fd);
|
||||
store->buildPaths(paths);
|
||||
store->buildPaths(toDerivedPaths(paths));
|
||||
out << 0;
|
||||
} catch (Error & e) {
|
||||
assert(e.status);
|
||||
|
|
|
@ -61,12 +61,12 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
|||
for (const auto & [_i, buildable] : enumerate(buildables)) {
|
||||
auto i = _i;
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
std::string symlink = outLink;
|
||||
if (i) symlink += fmt("-%d", i);
|
||||
store2->addPermRoot(bo.path, absPath(symlink));
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
auto builtOutputs = store->queryDerivationOutputMap(bfd.drvPath);
|
||||
for (auto & output : builtOutputs) {
|
||||
std::string symlink = outLink;
|
||||
|
@ -75,12 +75,12 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
|
|||
store2->addPermRoot(output.second, absPath(symlink));
|
||||
}
|
||||
},
|
||||
}, buildable);
|
||||
}, buildable.raw());
|
||||
}
|
||||
|
||||
updateProfile(buildables);
|
||||
|
||||
if (json) logger->cout("%s", buildablesToJSON(buildables, store).dump());
|
||||
if (json) logger->cout("%s", derivedPathsWithHintsToJSON(buildables, store).dump());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ struct CmdBundle : InstallableCommand
|
|||
auto evalState = getEvalState();
|
||||
|
||||
auto app = installable->toApp(*evalState);
|
||||
store->buildPaths(app.context);
|
||||
store->buildPaths(toDerivedPaths(app.context));
|
||||
|
||||
auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
|
||||
const flake::LockFlags lockFlags{ .writeLockFile = false };
|
||||
|
@ -110,7 +110,7 @@ struct CmdBundle : InstallableCommand
|
|||
|
||||
StorePath outPath = store->parseStorePath(evalState->coerceToPath(*attr2->pos, *attr2->value, context2));
|
||||
|
||||
store->buildPaths({{drvPath}});
|
||||
store->buildPaths({ DerivedPath::Built { drvPath } });
|
||||
|
||||
auto outPathS = store->printStorePath(outPath);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "common-args.hh"
|
||||
#include "shared.hh"
|
||||
#include "store-api.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "derivations.hh"
|
||||
#include "affinity.hh"
|
||||
#include "progress-bar.hh"
|
||||
|
@ -159,7 +160,7 @@ StorePath getDerivationEnvironment(ref<Store> store, const StorePath & drvPath)
|
|||
auto shellDrvPath = writeDerivation(*store, drv);
|
||||
|
||||
/* Build the derivation. */
|
||||
store->buildPaths({{shellDrvPath}});
|
||||
store->buildPaths({DerivedPath::Built{shellDrvPath}});
|
||||
|
||||
for (auto & [_0, outputAndOptPath] : drv.outputsAndOptPaths(*store)) {
|
||||
auto & [_1, optPath] = outputAndOptPath;
|
||||
|
@ -264,7 +265,7 @@ struct Common : InstallableCommand, MixProfile
|
|||
for (auto & [installable_, dir_] : redirects) {
|
||||
auto dir = absPath(dir_);
|
||||
auto installable = parseInstallable(store, installable_);
|
||||
auto buildable = installable->toBuildable();
|
||||
auto buildable = installable->toDerivedPathWithHints();
|
||||
auto doRedirect = [&](const StorePath & path)
|
||||
{
|
||||
auto from = store->printStorePath(path);
|
||||
|
@ -276,14 +277,14 @@ struct Common : InstallableCommand, MixProfile
|
|||
}
|
||||
};
|
||||
std::visit(overloaded {
|
||||
[&](const BuildableOpaque & bo) {
|
||||
[&](const DerivedPathWithHints::Opaque & bo) {
|
||||
doRedirect(bo.path);
|
||||
},
|
||||
[&](const BuildableFromDrv & bfd) {
|
||||
[&](const DerivedPathWithHints::Built & bfd) {
|
||||
for (auto & [outputName, path] : bfd.outputs)
|
||||
if (path) doRedirect(*path);
|
||||
},
|
||||
}, buildable);
|
||||
}, buildable.raw());
|
||||
}
|
||||
|
||||
return rewriteStrings(script, rewrites);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "get-drvs.hh"
|
||||
#include "store-api.hh"
|
||||
#include "derivations.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "attr-path.hh"
|
||||
#include "fetchers.hh"
|
||||
#include "registry.hh"
|
||||
|
@ -292,7 +293,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
}
|
||||
};
|
||||
|
||||
std::vector<StorePathWithOutputs> drvPaths;
|
||||
std::vector<DerivedPath> drvPaths;
|
||||
|
||||
auto checkApp = [&](const std::string & attrPath, Value & v, const Pos & pos) {
|
||||
try {
|
||||
|
@ -461,7 +462,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
fmt("%s.%s.%s", name, attr.name, attr2.name),
|
||||
*attr2.value, *attr2.pos);
|
||||
if ((std::string) attr.name == settings.thisSystem.get())
|
||||
drvPaths.push_back({drvPath});
|
||||
drvPaths.push_back(DerivedPath::Built{drvPath});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,18 +30,18 @@ struct CmdLog : InstallableCommand
|
|||
|
||||
subs.push_front(store);
|
||||
|
||||
auto b = installable->toBuildable();
|
||||
auto b = installable->toDerivedPathWithHints();
|
||||
|
||||
RunPager pager;
|
||||
for (auto & sub : subs) {
|
||||
auto log = std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
return sub->getBuildLog(bo.path);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built bfd) {
|
||||
return sub->getBuildLog(bfd.drvPath);
|
||||
},
|
||||
}, b);
|
||||
}, b.raw());
|
||||
if (!log) continue;
|
||||
stopProgressBar();
|
||||
printInfo("got build log for '%s' from '%s'", installable->what(), sub->getUri());
|
||||
|
|
|
@ -233,7 +233,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
|||
{
|
||||
ProfileManifest manifest(*getEvalState(), *profile);
|
||||
|
||||
std::vector<StorePathWithOutputs> pathsToBuild;
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
|
||||
for (auto & installable : installables) {
|
||||
if (auto installable2 = std::dynamic_pointer_cast<InstallableFlake>(installable)) {
|
||||
|
@ -249,7 +249,7 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
|||
attrPath,
|
||||
};
|
||||
|
||||
pathsToBuild.push_back({drv.drvPath, StringSet{drv.outputName}});
|
||||
pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, StringSet{drv.outputName}});
|
||||
|
||||
manifest.elements.emplace_back(std::move(element));
|
||||
} else {
|
||||
|
@ -259,17 +259,20 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
|
|||
ProfileElement element;
|
||||
|
||||
std::visit(overloaded {
|
||||
[&](BuildableOpaque bo) {
|
||||
pathsToBuild.push_back({bo.path, {}});
|
||||
[&](DerivedPathWithHints::Opaque bo) {
|
||||
pathsToBuild.push_back(bo);
|
||||
element.storePaths.insert(bo.path);
|
||||
},
|
||||
[&](BuildableFromDrv bfd) {
|
||||
[&](DerivedPathWithHints::Built 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)) {
|
||||
pathsToBuild.push_back({bfd.drvPath, {output.first}});
|
||||
pathsToBuild.push_back(DerivedPath::Built{bfd.drvPath, {output.first}});
|
||||
element.storePaths.insert(output.second);
|
||||
}
|
||||
},
|
||||
}, buildable);
|
||||
}, buildable.raw());
|
||||
|
||||
manifest.elements.emplace_back(std::move(element));
|
||||
}
|
||||
|
@ -388,7 +391,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
|||
auto matchers = getMatchers(store);
|
||||
|
||||
// FIXME: code duplication
|
||||
std::vector<StorePathWithOutputs> pathsToBuild;
|
||||
std::vector<DerivedPath> pathsToBuild;
|
||||
|
||||
for (size_t i = 0; i < manifest.elements.size(); ++i) {
|
||||
auto & element(manifest.elements[i]);
|
||||
|
@ -423,7 +426,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
|||
attrPath,
|
||||
};
|
||||
|
||||
pathsToBuild.push_back({drv.drvPath, StringSet{"out"}}); // FIXME
|
||||
pathsToBuild.push_back(DerivedPath::Built{drv.drvPath, {"out"}}); // FIXME
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ struct CmdRun : InstallableCommand, RunCommon
|
|||
|
||||
auto app = installable->toApp(*state);
|
||||
|
||||
state->store->buildPaths(app.context);
|
||||
state->store->buildPaths(toDerivedPaths(app.context));
|
||||
|
||||
Strings allArgs{app.program};
|
||||
for (auto & i : args) allArgs.push_back(i);
|
||||
|
|
Loading…
Reference in a new issue