libstore: flatten {,Single}{Built,Derived}Path

only dynamic derivations could produce a non-opaque drvPath. since
dynamic derivations are no longer supported we can have drvPath be
opaque at all times, simplifying downstream code significantly and
making quite a few methods unnecessary. discardOutputPath was only
called on drvPath members anyway and thus reduces to a copy, other
operations at the very least are no longer recursive. some vestige
of dynamic derivations remains in DerivedPathMap though (for now).

Change-Id: Ifb4ad53a3c67800be5a62540068c8279d4ae0046
This commit is contained in:
eldritch horrors
2025-05-12 13:37:54 +02:00
parent 8a539424c8
commit 5f723e96e6
25 changed files with 67 additions and 274 deletions
+3 -7
View File
@@ -368,18 +368,14 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
}
}
std::function<void(ref<SingleDerivedPath>, const DerivedPathMap<StringSet>::ChildNode &)> accumDerivedPath;
accumDerivedPath = [&](ref<SingleDerivedPath> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
auto accumDerivedPath = [&](ref<SingleDerivedPath::Opaque> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
if (!inputNode.value.empty())
pathsToBuild.push_back(DerivedPath::Built {
.drvPath = inputDrv,
.outputs = OutputsSpec::Names { inputNode.value },
});
for (const auto & [outputName, childNode] : inputNode.childMap)
accumDerivedPath(
make_ref<SingleDerivedPath>(SingleDerivedPath::Built { inputDrv, outputName }),
childNode);
// only dynamic derivations have a non-empty childMap
assert(inputNode.childMap.empty());
};
// Build or fetch all dependencies of the derivation.
+2 -34
View File
@@ -34,16 +34,6 @@ CMP(SingleBuiltPath, BuiltPathBuilt, outputs)
#undef CMP
#undef CMP_ONE
StorePath SingleBuiltPath::outPath() const
{
return std::visit(
overloaded{
[](const SingleBuiltPath::Opaque & p) { return p.path; },
[](const SingleBuiltPath::Built & b) { return b.output.second; },
}, raw()
);
}
StorePathSet BuiltPath::outPaths() const
{
return std::visit(
@@ -59,28 +49,6 @@ StorePathSet BuiltPath::outPaths() const
);
}
SingleDerivedPath::Built SingleBuiltPath::Built::discardOutputPath() const
{
return SingleDerivedPath::Built {
.drvPath = make_ref<SingleDerivedPath>(drvPath->discardOutputPath()),
.output = output.first,
};
}
SingleDerivedPath SingleBuiltPath::discardOutputPath() const
{
return std::visit(
overloaded{
[](const SingleBuiltPath::Opaque & p) -> SingleDerivedPath {
return p;
},
[](const SingleBuiltPath::Built & b) -> SingleDerivedPath {
return b.discardOutputPath();
},
}, raw()
);
}
kj::Promise<Result<JSON>> BuiltPath::Built::toJSON(const Store & store) const
try {
JSON res;
@@ -141,7 +109,7 @@ try {
[&](const BuiltPath::Built & p) -> kj::Promise<Result<void>> {
try {
auto drvHashes = TRY_AWAIT(
staticOutputHashes(store, TRY_AWAIT(store.readDerivation(p.drvPath->outPath())))
staticOutputHashes(store, TRY_AWAIT(store.readDerivation(p.drvPath->path)))
);
for (auto& [outputName, outputPath] : p.outputs) {
if (experimentalFeatureSettings.isEnabled(
@@ -150,7 +118,7 @@ try {
if (!drvOutput)
throw Error(
"the derivation '%s' has unrealised output '%s' (derived-path.cc/toRealisedPaths)",
store.printStorePath(p.drvPath->outPath()), outputName);
store.printStorePath(p.drvPath->path), outputName);
auto thisRealisation = TRY_AWAIT(store.queryRealisation(
DrvOutput{*drvOutput, outputName}));
assert(thisRealisation); // Weve built it, so we must
+2 -8
View File
@@ -10,11 +10,9 @@ namespace nix {
struct SingleBuiltPath;
struct SingleBuiltPathBuilt {
ref<SingleBuiltPath> drvPath;
ref<DerivedPathOpaque> drvPath;
std::pair<std::string, StorePath> output;
SingleDerivedPathBuilt discardOutputPath() const;
std::string to_string(const Store & store) const;
static SingleBuiltPathBuilt parse(const Store & store, std::string_view, std::string_view);
kj::Promise<Result<JSON>> toJSON(const Store & store) const;
@@ -40,10 +38,6 @@ struct SingleBuiltPath : built_path::detail::SingleBuiltPathRaw {
return static_cast<const Raw &>(*this);
}
StorePath outPath() const;
SingleDerivedPath discardOutputPath() const;
static SingleBuiltPath parse(const Store & store, std::string_view);
kj::Promise<Result<JSON>> toJSON(const Store & store) const;
};
@@ -59,7 +53,7 @@ static inline ref<SingleBuiltPath> staticDrv(StorePath drvPath)
* See 'BuiltPath' for more an explanation.
*/
struct BuiltPathBuilt {
ref<SingleBuiltPath> drvPath;
ref<DerivedPathOpaque> drvPath;
std::map<std::string, StorePath> outputs;
std::string to_string(const Store & store) const;
+1 -2
View File
@@ -48,8 +48,7 @@ InstallableDerivedPath InstallableDerivedPath::parse(
},
// If the user did use ^, we just do exactly what is written.
[&](const ExtendedOutputsSpec::Explicit & outputSpec) -> DerivedPath {
auto drv = make_ref<SingleDerivedPath>(SingleDerivedPath::parse(*store, prefix));
drvRequireExperiment(*drv);
auto drv = make_ref<DerivedPathOpaque>(DerivedPathOpaque::parse(*store, prefix));
return DerivedPath::Built {
.drvPath = std::move(drv),
.outputs = outputSpec,
+2 -32
View File
@@ -524,36 +524,6 @@ ref<Installable> SourceExprCommand::parseInstallable(
return installables.front();
}
static kj::Promise<Result<SingleBuiltPath>> getBuiltPath(ref<Store> evalStore, ref<Store> store, const SingleDerivedPath & b)
try {
auto handlers = overloaded{
[&](const SingleDerivedPath::Opaque & bo) -> kj::Promise<Result<SingleBuiltPath>> {
return {SingleBuiltPath::Opaque { bo.path }};
},
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
[&](const SingleDerivedPath::Built & bfd) -> kj::Promise<Result<SingleBuiltPath>> {
try {
auto drvPath = TRY_AWAIT(getBuiltPath(evalStore, store, *bfd.drvPath));
// Resolving this instead of `bfd` will yield the same result, but avoid duplicative work.
SingleDerivedPath::Built truncatedBfd {
.drvPath = makeConstantStorePathRef(drvPath.outPath()),
.output = bfd.output,
};
auto outputPath = TRY_AWAIT(resolveDerivedPath(*store, truncatedBfd, &*evalStore));
co_return SingleBuiltPath::Built {
.drvPath = make_ref<SingleBuiltPath>(std::move(drvPath)),
.output = { bfd.output, outputPath },
};
} catch (...) {
co_return result::current_exception();
}
},
};
co_return TRY_AWAIT(std::visit(handlers, b.raw()));
} catch (...) {
co_return result::current_exception();
}
std::vector<BuiltPathWithResult> Installable::build(
EvalState & state,
ref<Store> evalStore,
@@ -642,7 +612,7 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
state.aio.blockOn(resolveDerivedPath(*store, bfd, &*evalStore));
res.push_back({aux.installable, {
.path = BuiltPath::Built {
.drvPath = make_ref<SingleBuiltPath>(state.aio.blockOn(getBuiltPath(evalStore, store, *bfd.drvPath))),
.drvPath = bfd.drvPath,
.outputs = outputs,
},
.info = aux.info}});
@@ -674,7 +644,7 @@ std::vector<std::pair<ref<Installable>, BuiltPathWithResult>> Installable::build
outputs.emplace(outputName, realisation.outPath);
res.push_back({aux.installable, {
.path = BuiltPath::Built {
.drvPath = make_ref<SingleBuiltPath>(state.aio.blockOn(getBuiltPath(evalStore, store, *bfd.drvPath))),
.drvPath = bfd.drvPath,
.outputs = outputs,
},
.info = aux.info,
+1 -1
View File
@@ -580,7 +580,7 @@ string_t AttrCursor::getStringWithContext(EvalState & state)
return d.drvPath;
},
[&](const NixStringContextElem::Built & b) -> const StorePath & {
return b.drvPath->getBaseStorePath();
return b.drvPath->path;
},
[&](const NixStringContextElem::Opaque & o) -> const StorePath & {
return o.path;
+5 -12
View File
@@ -922,18 +922,11 @@ std::string EvalState::mkSingleDerivedPathStringRaw(
return ctx.store->printStorePath(o.path);
},
[&](const SingleDerivedPath::Built & b) {
auto optStaticOutputPath = std::visit(overloaded {
[&](const SingleDerivedPath::Opaque & o) {
auto drv = aio.blockOn(ctx.store->readDerivation(o.path));
auto i = drv.outputs.find(b.output);
if (i == drv.outputs.end())
throw Error("derivation '%s' does not have output '%s'", b.drvPath->to_string(*ctx.store), b.output);
return i->second.path(*ctx.store, drv.name, b.output);
},
[&](const SingleDerivedPath::Built & o) -> std::optional<StorePath> {
return std::nullopt;
},
}, b.drvPath->raw());
auto drv = aio.blockOn(ctx.store->readDerivation(b.drvPath->path));
auto i = drv.outputs.find(b.output);
if (i == drv.outputs.end())
throw Error("derivation '%s' does not have output '%s'", b.drvPath->to_string(*ctx.store), b.output);
auto optStaticOutputPath = i->second.path(*ctx.store, drv.name, b.output);
return mkOutputStringRaw(b, optStaticOutputPath);
}
}, p.raw());
+1 -1
View File
@@ -58,7 +58,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context)
.drvPath = b.drvPath,
.outputs = OutputsSpec::Names { b.output },
});
return ensureValid(b.drvPath->getBaseStorePath());
return ensureValid(b.drvPath->path);
},
[&](const NixStringContextElem::Opaque & o) {
auto ctxS = ctx.store->printStorePath(o.path);
+2 -9
View File
@@ -26,7 +26,7 @@ NixStringContextElem NixStringContextElem::parse(std::string_view s0)
std::string output { s.substr(0, index) };
// Advance string to parse after the '!'
s = s.substr(index + 1);
auto drv = make_ref<SingleDerivedPath>(SingleDerivedPath::Opaque{StorePath{s}});
auto drv = make_ref<SingleDerivedPath::Opaque>(SingleDerivedPath::Opaque{StorePath{s}});
return SingleDerivedPath::Built{
.drvPath = std::move(drv),
.output = std::move(output),
@@ -59,14 +59,7 @@ std::string NixStringContextElem::to_string() const
res += '!';
res += b.output;
res += '!';
std::visit(overloaded {
[&](const SingleDerivedPath::Opaque & o2) {
res += o2.path.to_string();
},
[&](const SingleDerivedPath::Built & o) {
assert(false && "dynamic derivations shouldn't exist in string context any more");
},
}, b.drvPath->raw());
res += b.drvPath->path.to_string();
},
[&](const NixStringContextElem::Opaque & o) {
res += o.path.to_string();
+3 -7
View File
@@ -373,9 +373,7 @@ try {
/* The inputs must be built before we can build this goal. */
inputDrvOutputs.clear();
if (useDerivation) {
std::function<void(ref<SingleDerivedPath>, const DerivedPathMap<StringSet>::ChildNode &)> addWaiteeDerivedPath;
addWaiteeDerivedPath = [&](ref<SingleDerivedPath> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
auto addWaiteeDerivedPath = [&](ref<DerivedPathOpaque> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
if (!inputNode.value.empty())
dependencies.add(worker.goalFactory().makeGoal(
DerivedPath::Built {
@@ -383,10 +381,8 @@ try {
.outputs = inputNode.value,
},
buildMode == bmRepair ? bmRepair : bmNormal));
for (const auto & [outputName, childNode] : inputNode.childMap)
addWaiteeDerivedPath(
make_ref<SingleDerivedPath>(SingleDerivedPath::Built { inputDrv, outputName }),
childNode);
// only dynamic derivations have a non-empty childMap
assert(inputNode.childMap.empty());
};
for (const auto & [inputDrvPath, inputNode] : dynamic_cast<Derivation *>(drv.get())->inputDrvs.map) {
+1 -4
View File
@@ -201,10 +201,7 @@ std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>> Worker::makeGoal(const
{
return std::visit(overloaded {
[&](const DerivedPath::Built & bfd) -> std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>> {
if (auto bop = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath))
return makeDerivationGoal(bop->path, bfd.outputs, buildMode);
else
throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented.");
return makeDerivationGoal(bfd.drvPath->path, bfd.outputs, buildMode);
},
[&](const DerivedPath::Opaque & bo) -> std::pair<GoalPtr, kj::Promise<Result<Goal::WorkResult>>> {
return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair);
+4 -15
View File
@@ -931,7 +931,6 @@ try {
static bool tryResolveInput(
Store & store, StorePathSet & inputSrcs, StringMap & inputRewrites,
const DownstreamPlaceholder * placeholderOpt,
const StorePath & inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode,
const std::map<std::pair<StorePath, std::string>, StorePath> & inputDrvOutputs)
{
@@ -946,9 +945,7 @@ static bool tryResolveInput(
};
auto getPlaceholder = [&](const std::string & outputName) {
return placeholderOpt
? DownstreamPlaceholder::unknownDerivation(*placeholderOpt, outputName)
: DownstreamPlaceholder::unknownCaOutput(inputDrv, outputName);
return DownstreamPlaceholder::unknownCaOutput(inputDrv, outputName);
};
for (auto & outputName : inputNode.value) {
@@ -963,16 +960,8 @@ static bool tryResolveInput(
inputSrcs.insert(std::move(actualPath));
}
for (auto & [outputName, childNode] : inputNode.childMap) {
auto actualPathOpt = getOutput(outputName);
if (!actualPathOpt) return false;
auto actualPath = *actualPathOpt;
auto nextPlaceholder = getPlaceholder(outputName);
if (!tryResolveInput(store, inputSrcs, inputRewrites,
&nextPlaceholder, actualPath, childNode,
inputDrvOutputs))
return false;
}
// only dynamic drvs can have non-empty childMaps
assert(inputNode.childMap.empty());
return true;
}
@@ -987,7 +976,7 @@ try {
for (auto & [inputDrv, inputNode] : inputDrvs.map)
if (!tryResolveInput(store, resolved.inputSrcs, inputRewrites,
nullptr, inputDrv, inputNode, inputDrvOutputs))
inputDrv, inputNode, inputDrvOutputs))
co_return std::nullopt;
TRY_AWAIT(rewriteDerivation(store, resolved, inputRewrites));
+9 -25
View File
@@ -121,7 +121,7 @@ std::string DerivedPath::Built::to_string(const Store & store) const
std::string DerivedPath::Built::to_string_legacy(const Store & store) const
{
return drvPath->to_string_legacy(store)
return drvPath->to_string(store)
+ "!"
+ outputs.to_string();
}
@@ -162,26 +162,11 @@ DerivedPath::Opaque DerivedPath::Opaque::parse(const Store & store, std::string_
return {store.parseStorePath(s)};
}
void drvRequireExperiment(
const SingleDerivedPath & drv,
const ExperimentalFeatureSettings & xpSettings)
{
std::visit(overloaded {
[&](const SingleDerivedPath::Opaque &) {
// plain drv path; no experimental features required.
},
[&](const SingleDerivedPath::Built &) {
xpSettings.require(Xp::DynamicDerivations);
},
}, drv.raw());
}
SingleDerivedPath::Built SingleDerivedPath::Built::parse(
const Store & store, ref<SingleDerivedPath> drv,
const Store & store, ref<DerivedPathOpaque> drv,
OutputNameView output,
const ExperimentalFeatureSettings & xpSettings)
{
drvRequireExperiment(*drv, xpSettings);
return {
.drvPath = drv,
.output = std::string { output },
@@ -189,11 +174,10 @@ SingleDerivedPath::Built SingleDerivedPath::Built::parse(
}
DerivedPath::Built DerivedPath::Built::parse(
const Store & store, ref<SingleDerivedPath> drv,
const Store & store, ref<DerivedPathOpaque> drv,
OutputNameView outputsS,
const ExperimentalFeatureSettings & xpSettings)
{
drvRequireExperiment(*drv, xpSettings);
return {
.drvPath = drv,
.outputs = OutputsSpec::parse(outputsS),
@@ -210,7 +194,7 @@ static DerivedPathT parseDerivedPath(
return DerivedPathT::Opaque::parse(store, s);
} else {
auto path = DerivedPathT::Built::parse(store,
make_ref<SingleDerivedPath>(DerivedPathT::Opaque::parse(
make_ref<typename DerivedPathT::Opaque>(DerivedPathT::Opaque::parse(
store,
s.substr(0, n))),
s.substr(n + 1),
@@ -275,22 +259,22 @@ DerivedPath DerivedPath::fromSingle(const SingleDerivedPath & req)
const StorePath & SingleDerivedPath::Built::getBaseStorePath() const
{
return drvPath->getBaseStorePath();
return drvPath->path;
}
const StorePath & DerivedPath::Built::getBaseStorePath() const
{
return drvPath->getBaseStorePath();
return drvPath->path;
}
template<typename DP>
static inline const StorePath & getBaseStorePath_(const DP & derivedPath)
{
return std::visit(overloaded {
[&](const typename DP::Built & bfd) -> auto & {
return bfd.drvPath->getBaseStorePath();
[&](const typename DP::Built & bfd) -> const StorePath & {
return bfd.drvPath->path;
},
[&](const typename DP::Opaque & bo) -> auto & {
[&](const typename DP::Opaque & bo) -> const StorePath & {
return bo.path;
},
}, derivedPath.raw());
+6 -18
View File
@@ -43,7 +43,7 @@ struct SingleDerivedPath;
* path of the given output name.
*/
struct SingleDerivedPathBuilt {
ref<SingleDerivedPath> drvPath;
ref<DerivedPathOpaque> drvPath;
OutputName output;
/**
@@ -72,7 +72,7 @@ struct SingleDerivedPathBuilt {
* @param xpSettings Stop-gap to avoid globals during unit tests.
*/
static SingleDerivedPathBuilt parse(
const Store & store, ref<SingleDerivedPath> drvPath,
const Store & store, ref<DerivedPathOpaque> drvPath,
OutputNameView outputs,
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
kj::Promise<Result<JSON>> toJSON(Store & store) const;
@@ -150,9 +150,9 @@ struct SingleDerivedPath : derived_path::detail::SingleDerivedPathRaw {
kj::Promise<Result<JSON>> toJSON(Store & store) const;
};
static inline ref<SingleDerivedPath> makeConstantStorePathRef(StorePath drvPath)
static inline ref<DerivedPathOpaque> makeConstantStorePathRef(StorePath drvPath)
{
return make_ref<SingleDerivedPath>(SingleDerivedPath::Opaque { drvPath });
return make_ref<DerivedPathOpaque>(SingleDerivedPath::Opaque { drvPath });
}
/**
@@ -168,7 +168,7 @@ static inline ref<SingleDerivedPath> makeConstantStorePathRef(StorePath drvPath)
* output name.
*/
struct DerivedPathBuilt {
ref<SingleDerivedPath> drvPath;
ref<DerivedPathOpaque> drvPath;
OutputsSpec outputs;
/**
@@ -197,7 +197,7 @@ struct DerivedPathBuilt {
* @param xpSettings Stop-gap to avoid globals during unit tests.
*/
static DerivedPathBuilt parse(
const Store & store, ref<SingleDerivedPath>,
const Store & store, ref<DerivedPathOpaque>,
std::string_view,
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
kj::Promise<Result<JSON>> toJSON(Store & store) const;
@@ -282,16 +282,4 @@ struct DerivedPath : derived_path::detail::DerivedPathRaw {
typedef std::vector<DerivedPath> DerivedPaths;
/**
* Used by various parser functions to require experimental features as
* needed.
*
* Somewhat unfortunate this cannot just be an implementation detail for
* this module.
*
* @param xpSettings Stop-gap to avoid globals during unit tests.
*/
void drvRequireExperiment(
const SingleDerivedPath & drv,
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
}
+1 -26
View File
@@ -23,36 +23,11 @@ DownstreamPlaceholder DownstreamPlaceholder::unknownCaOutput(
};
}
DownstreamPlaceholder DownstreamPlaceholder::unknownDerivation(
const DownstreamPlaceholder & placeholder,
OutputNameView outputName,
const ExperimentalFeatureSettings & xpSettings)
{
xpSettings.require(Xp::DynamicDerivations);
auto compressed = compressHash(placeholder.hash, 20);
auto clearText = "nix-computed-output:"
+ compressed.to_string(Base::Base32, false)
+ ":" + std::string { outputName };
return DownstreamPlaceholder {
hashString(HashType::SHA256, clearText)
};
}
DownstreamPlaceholder DownstreamPlaceholder::fromSingleDerivedPathBuilt(
const SingleDerivedPath::Built & b,
const ExperimentalFeatureSettings & xpSettings)
{
return std::visit(overloaded {
[&](const SingleDerivedPath::Opaque & o) {
return DownstreamPlaceholder::unknownCaOutput(o.path, b.output, xpSettings);
},
[&](const SingleDerivedPath::Built & b2) {
return DownstreamPlaceholder::unknownDerivation(
DownstreamPlaceholder::fromSingleDerivedPathBuilt(b2, xpSettings),
b.output,
xpSettings);
},
}, b.drvPath->raw());
return DownstreamPlaceholder::unknownCaOutput(b.drvPath->path, b.output, xpSettings);
}
}
+1 -15
View File
@@ -61,24 +61,10 @@ public:
OutputNameView outputName,
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
/**
* Create a placehold for the output of an unknown derivation.
*
* The derivation is not yet known because it is a dynamic
* derivaiton --- it is itself an output of another derivation ---
* and we just have (another) placeholder for it.
*
* @param xpSettings Stop-gap to avoid globals during unit tests.
*/
static DownstreamPlaceholder unknownDerivation(
const DownstreamPlaceholder & drvPlaceholder,
OutputNameView outputName,
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
/**
* Convenience constructor that handles both cases (unknown
* content-addressed output and unknown derivation), delegating as
* needed to `unknownCaOutput` and `unknownDerivation`.
* needed to `unknownCaOutput`.
*
* Recursively builds up a placeholder from a
* `SingleDerivedPath::Built.drvPath` chain.
+4 -12
View File
@@ -150,17 +150,15 @@ struct QueryMissingContext
kj::Promise<Result<void>> queryMissing(const std::vector<DerivedPath> & targets);
void enqueueDerivedPaths(ref<SingleDerivedPath> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode)
void enqueueDerivedPaths(ref<DerivedPathOpaque> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode)
{
if (!inputNode.value.empty()) {
pool.enqueueWithAio([this, path{DerivedPath::Built{inputDrv, inputNode.value}}](
AsyncIoRoot & aio
) { doPath(aio, path); });
}
for (const auto & [outputName, childNode] : inputNode.childMap)
enqueueDerivedPaths(
make_ref<SingleDerivedPath>(SingleDerivedPath::Built { inputDrv, outputName }),
childNode);
// only dynamic derivations have a non-empty childMap
assert(inputNode.childMap.empty());
}
void mustBuildDrv(const StorePath & drvPath, const Derivation & drv)
@@ -234,13 +232,7 @@ struct QueryMissingContext
void doPathBuilt(AsyncIoRoot & aio, const DerivedPath::Built & bfd)
{
auto drvPathP = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath);
if (!drvPathP) {
// TODO make work in this case.
warn("Ignoring dynamic derivation %s while querying missing paths; not yet implemented", bfd.drvPath->to_string(store));
return;
}
auto & drvPath = drvPathP->path;
auto & drvPath = bfd.drvPath->path;
if (!aio.blockOn(store.isValidPath(drvPath))) {
// FIXME: we could try to substitute the derivation.
+12 -19
View File
@@ -50,25 +50,18 @@ StorePathWithOutputs::ParseResult StorePathWithOutputs::tryFromDerivedPath(const
return StorePathWithOutputs { bo.path };
},
[&](const DerivedPath::Built & bfd) -> StorePathWithOutputs::ParseResult {
return std::visit(overloaded {
[&](const SingleDerivedPath::Opaque & bo) -> StorePathWithOutputs::ParseResult {
return StorePathWithOutputs {
.path = bo.path,
// Use legacy encoding of wildcard as empty set
.outputs = std::visit(overloaded {
[&](const OutputsSpec::All &) -> StringSet {
return {};
},
[&](const OutputsSpec::Names & outputs) {
return static_cast<StringSet>(outputs);
},
}, bfd.outputs.raw),
};
},
[&](const SingleDerivedPath::Built &) -> StorePathWithOutputs::ParseResult {
return std::monostate {};
},
}, bfd.drvPath->raw());
return StorePathWithOutputs {
.path = bfd.drvPath->path,
// Use legacy encoding of wildcard as empty set
.outputs = std::visit(overloaded {
[&](const OutputsSpec::All &) -> StringSet {
return {};
},
[&](const OutputsSpec::Names & outputs) {
return static_cast<StringSet>(outputs);
},
}, bfd.outputs.raw),
};
},
}, p.raw());
}
+1 -1
View File
@@ -667,7 +667,7 @@ try {
// Do nothing, path is hopefully there already
},
[&](const DerivedPath::Built & bp) {
drvPaths2.insert(bp.drvPath->getBaseStorePath());
drvPaths2.insert(bp.drvPath->path);
},
}, i.raw());
}
+1 -1
View File
@@ -27,7 +27,7 @@ StringPairs resolveRewrites(
res.emplace(
DownstreamPlaceholder::fromSingleDerivedPathBuilt(
SingleDerivedPath::Built {
.drvPath = make_ref<SingleDerivedPath>(drvDep->drvPath->discardOutputPath()),
.drvPath = makeConstantStorePathRef(drvDep->drvPath->path),
.output = outputName,
}).render(),
store.printStorePath(outputPath)
+1 -1
View File
@@ -36,7 +36,7 @@ struct CmdLog : InstallableCommand
// For compat with CLI today, TODO revisit
auto oneUp = std::visit(overloaded {
[&](const DerivedPath::Opaque & bo) {
return make_ref<SingleDerivedPath>(bo);
return make_ref<SingleDerivedPath::Opaque>(bo);
},
[&](const DerivedPath::Built & bfd) {
return bfd.drvPath;
+1 -1
View File
@@ -78,7 +78,7 @@ TEST(NixStringContextElemTest, built_opaque) {
auto * p = std::get_if<NixStringContextElem::Built>(&elem.raw);
ASSERT_TRUE(p);
ASSERT_EQ(p->output, "foo");
ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque {
ASSERT_EQ(*p->drvPath, (SingleDerivedPath::Opaque {
.path = StorePath { built.substr(5) },
}));
ASSERT_EQ(elem.to_string(), built);
@@ -20,7 +20,7 @@ Gen<DerivedPath::Opaque> Arbitrary<DerivedPath::Opaque>::arbitrary()
Gen<SingleDerivedPath::Built> Arbitrary<SingleDerivedPath::Built>::arbitrary()
{
return gen::just(SingleDerivedPath::Built {
.drvPath = make_ref<SingleDerivedPath>(*gen::arbitrary<SingleDerivedPath>()),
.drvPath = make_ref<DerivedPathOpaque>(*gen::arbitrary<DerivedPathOpaque>()),
.output = (*gen::arbitrary<StorePathName>()).name,
});
}
@@ -28,7 +28,7 @@ Gen<SingleDerivedPath::Built> Arbitrary<SingleDerivedPath::Built>::arbitrary()
Gen<DerivedPath::Built> Arbitrary<DerivedPath::Built>::arbitrary()
{
return gen::just(DerivedPath::Built {
.drvPath = make_ref<SingleDerivedPath>(*gen::arbitrary<SingleDerivedPath>()),
.drvPath = make_ref<DerivedPathOpaque>(*gen::arbitrary<DerivedPathOpaque>()),
.outputs = *gen::arbitrary<OutputsSpec>(),
});
}
+1 -1
View File
@@ -38,7 +38,7 @@ TEST_F(DerivedPathTest, built_opaque) {
auto * p = std::get_if<DerivedPath::Built>(&elem);
ASSERT_TRUE(p);
ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "foo", "bar" }));
ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque {
ASSERT_EQ(*p->drvPath, (SingleDerivedPath::Opaque {
.path = store->parseStorePath(built.substr(0, 49)),
}));
ASSERT_EQ(elem.to_string(*store), built);
@@ -20,24 +20,4 @@ TEST(DownstreamPlaceholder, unknownCaOutput) {
"/0c6rn30q4frawknapgwq386zq358m8r6msvywcvc89n6m5p2dgbz");
}
TEST(DownstreamPlaceholder, unknownDerivation) {
/**
* Same reason as above
*/
ExperimentalFeatureSettings mockXpSettings;
mockXpSettings.experimentalFeatures.override(
ExperimentalFeatures{} | Xp::DynamicDerivations | Xp::CaDerivations
);
ASSERT_EQ(
DownstreamPlaceholder::unknownDerivation(
DownstreamPlaceholder::unknownCaOutput(
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv.drv" },
"out",
mockXpSettings),
"out",
mockXpSettings).render(),
"/0gn6agqxjyyalf0dpihgyf49xq5hqxgw100f0wydnj6yqrhqsb3w");
}
}