libstore: break up QueryMissingContext::doPath

std::visit makes coroutines nearly impossible to use correctly.

Change-Id: I085c08b595a5d4a43208eb97f023aa00b48bff45
This commit is contained in:
eldritch horrors 2024-11-17 14:43:57 +01:00
parent 74d820e5e8
commit a911b44a31

View file

@ -182,105 +182,112 @@ struct QueryMissingContext
if (!state->done.insert(req.to_string(store)).second) return; if (!state->done.insert(req.to_string(store)).second) return;
} }
std::visit(overloaded { std::visit(
[&](const DerivedPath::Built & bfd) { overloaded{
auto drvPathP = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath); [&](const DerivedPath::Built & bfd) { doPathBuilt(bfd); },
if (!drvPathP) { [&](const DerivedPath::Opaque & bo) { doPathOpaque(bo); },
// TODO make work in this case. },
warn("Ignoring dynamic derivation %s while querying missing paths; not yet implemented", bfd.drvPath->to_string(store)); req.raw()
return; );
} }
auto & drvPath = drvPathP->path;
if (!store.isValidPath(drvPath)) { void doPathBuilt(const DerivedPath::Built & bfd)
// FIXME: we could try to substitute the derivation. {
auto state(state_.lock()); auto drvPathP = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath);
state->unknown.insert(drvPath); if (!drvPathP) {
return; // 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;
StorePathSet invalid; if (!store.isValidPath(drvPath)) {
/* true for regular derivations, and CA derivations for which we // FIXME: we could try to substitute the derivation.
have a trust mapping for all wanted outputs. */ auto state(state_.lock());
auto knownOutputPaths = true; state->unknown.insert(drvPath);
for (auto & [outputName, pathOpt] : store.queryPartialDerivationOutputMap(drvPath)) { return;
if (!pathOpt) { }
StorePathSet invalid;
/* 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] : store.queryPartialDerivationOutputMap(drvPath)) {
if (!pathOpt) {
knownOutputPaths = false;
break;
}
if (bfd.outputs.contains(outputName) && !store.isValidPath(*pathOpt))
invalid.insert(*pathOpt);
}
if (knownOutputPaths && invalid.empty()) return;
auto drv = make_ref<Derivation>(store.derivationFromPath(drvPath));
ParsedDerivation parsedDrv(StorePath(drvPath), *drv);
if (!knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
experimentalFeatureSettings.require(Xp::CaDerivations);
// If there are unknown output paths, attempt to find if the
// paths are known to substituters through a realisation.
auto outputHashes = staticOutputHashes(store, *drv);
knownOutputPaths = true;
for (auto [outputName, hash] : outputHashes) {
if (!bfd.outputs.contains(outputName))
continue;
bool found = false;
for (auto &sub : getDefaultSubstituters()) {
auto realisation = sub->queryRealisation({hash, outputName});
if (!realisation)
continue;
found = true;
if (!store.isValidPath(realisation->outPath))
invalid.insert(realisation->outPath);
break;
}
if (!found) {
// Some paths did not have a realisation, this must be built.
knownOutputPaths = false; knownOutputPaths = false;
break; break;
} }
if (bfd.outputs.contains(outputName) && !store.isValidPath(*pathOpt))
invalid.insert(*pathOpt);
} }
if (knownOutputPaths && invalid.empty()) return; }
auto drv = make_ref<Derivation>(store.derivationFromPath(drvPath)); if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
ParsedDerivation parsedDrv(StorePath(drvPath), *drv); auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
for (auto & output : invalid)
pool.enqueue([=, this] { checkOutput(drvPath, drv, output, drvState); });
} else
mustBuildDrv(drvPath, *drv);
}
if (!knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) { void doPathOpaque(const DerivedPath::Opaque & bo)
experimentalFeatureSettings.require(Xp::CaDerivations); {
if (store.isValidPath(bo.path)) return;
// If there are unknown output paths, attempt to find if the SubstitutablePathInfos infos;
// paths are known to substituters through a realisation. store.querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos);
auto outputHashes = staticOutputHashes(store, *drv);
knownOutputPaths = true;
for (auto [outputName, hash] : outputHashes) { if (infos.empty()) {
if (!bfd.outputs.contains(outputName)) auto state(state_.lock());
continue; state->unknown.insert(bo.path);
return;
}
bool found = false; auto info = infos.find(bo.path);
for (auto &sub : getDefaultSubstituters()) { assert(info != infos.end());
auto realisation = sub->queryRealisation({hash, outputName});
if (!realisation)
continue;
found = true;
if (!store.isValidPath(realisation->outPath))
invalid.insert(realisation->outPath);
break;
}
if (!found) {
// Some paths did not have a realisation, this must be built.
knownOutputPaths = false;
break;
}
}
}
if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) { {
auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size())); auto state(state_.lock());
for (auto & output : invalid) state->willSubstitute.insert(bo.path);
pool.enqueue([=, this] { checkOutput(drvPath, drv, output, drvState); }); state->downloadSize += info->second.downloadSize;
} else state->narSize += info->second.narSize;
mustBuildDrv(drvPath, *drv); }
}, for (auto & ref : info->second.references)
[&](const DerivedPath::Opaque & bo) { pool.enqueue([this, path{DerivedPath::Opaque { ref }}] { doPath(path); });
if (store.isValidPath(bo.path)) return;
SubstitutablePathInfos infos;
store.querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos);
if (infos.empty()) {
auto state(state_.lock());
state->unknown.insert(bo.path);
return;
}
auto info = infos.find(bo.path);
assert(info != infos.end());
{
auto state(state_.lock());
state->willSubstitute.insert(bo.path);
state->downloadSize += info->second.downloadSize;
state->narSize += info->second.narSize;
}
for (auto & ref : info->second.references)
pool.enqueue([this, path{DerivedPath::Opaque { ref }}] { doPath(path); });
},
}, req.raw());
} }
}; };
} }