From a911b44a312f585301e822b8b6b85e95646735c5 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 17 Nov 2024 14:43:57 +0100 Subject: [PATCH] libstore: break up QueryMissingContext::doPath std::visit makes coroutines nearly impossible to use correctly. Change-Id: I085c08b595a5d4a43208eb97f023aa00b48bff45 --- lix/libstore/misc.cc | 179 ++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 86 deletions(-) diff --git a/lix/libstore/misc.cc b/lix/libstore/misc.cc index b9fd11078..6aef8329a 100644 --- a/lix/libstore/misc.cc +++ b/lix/libstore/misc.cc @@ -182,105 +182,112 @@ struct QueryMissingContext if (!state->done.insert(req.to_string(store)).second) return; } - std::visit(overloaded { - [&](const DerivedPath::Built & bfd) { - auto drvPathP = std::get_if(&*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; + std::visit( + overloaded{ + [&](const DerivedPath::Built & bfd) { doPathBuilt(bfd); }, + [&](const DerivedPath::Opaque & bo) { doPathOpaque(bo); }, + }, + req.raw() + ); + } - if (!store.isValidPath(drvPath)) { - // FIXME: we could try to substitute the derivation. - auto state(state_.lock()); - state->unknown.insert(drvPath); - return; - } + void doPathBuilt(const DerivedPath::Built & bfd) + { + auto drvPathP = std::get_if(&*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; - 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) { + if (!store.isValidPath(drvPath)) { + // FIXME: we could try to substitute the derivation. + auto state(state_.lock()); + state->unknown.insert(drvPath); + return; + } + + 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(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; break; } - if (bfd.outputs.contains(outputName) && !store.isValidPath(*pathOpt)) - invalid.insert(*pathOpt); } - if (knownOutputPaths && invalid.empty()) return; + } - auto drv = make_ref(store.derivationFromPath(drvPath)); - ParsedDerivation parsedDrv(StorePath(drvPath), *drv); + if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) { + auto drvState = make_ref>(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()) { - experimentalFeatureSettings.require(Xp::CaDerivations); + void doPathOpaque(const DerivedPath::Opaque & bo) + { + if (store.isValidPath(bo.path)) return; - // 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; + SubstitutablePathInfos infos; + store.querySubstitutablePathInfos({{bo.path, std::nullopt}}, infos); - for (auto [outputName, hash] : outputHashes) { - if (!bfd.outputs.contains(outputName)) - continue; + if (infos.empty()) { + auto state(state_.lock()); + state->unknown.insert(bo.path); + return; + } - 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; - break; - } - } - } + auto info = infos.find(bo.path); + assert(info != infos.end()); - if (knownOutputPaths && settings.useSubstitutes && parsedDrv.substitutesAllowed()) { - auto drvState = make_ref>(DrvState(invalid.size())); - for (auto & output : invalid) - pool.enqueue([=, this] { checkOutput(drvPath, drv, output, drvState); }); - } else - mustBuildDrv(drvPath, *drv); + { + auto state(state_.lock()); + state->willSubstitute.insert(bo.path); + state->downloadSize += info->second.downloadSize; + state->narSize += info->second.narSize; + } - }, - [&](const DerivedPath::Opaque & bo) { - - 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()); + for (auto & ref : info->second.references) + pool.enqueue([this, path{DerivedPath::Opaque { ref }}] { doPath(path); }); } }; }