libfetchers: asyncify getRegistries, lookupInRegistries

Change-Id: I5a668ad05440e2d7d574e8a470c269b670282c6f
This commit is contained in:
eldritch horrors
2025-02-08 17:26:19 +00:00
parent 07691dd851
commit 1ce46c318c
6 changed files with 56 additions and 32 deletions
+1 -1
View File
@@ -363,7 +363,7 @@ void completeFlakeRef(
Args::completeDir(completions, 0, prefix);
/* Look for registry entries that match the prefix. */
for (auto & registry : fetchers::getRegistries(store)) {
for (auto & registry : aio.blockOn(fetchers::getRegistries(store))) {
for (auto & entry : registry->entries) {
auto from = entry.from.to_string();
if (!prefix.starts_with("flake:") && from.starts_with("flake:")) {
+1 -1
View File
@@ -44,7 +44,7 @@ bool FlakeRef::operator ==(const FlakeRef & other) const
kj::Promise<Result<FlakeRef>> FlakeRef::resolve(ref<Store> store) const
try {
auto [input2, extraAttrs] = lookupInRegistries(store, input);
auto [input2, extraAttrs] = TRY_AWAIT(lookupInRegistries(store, input));
co_return FlakeRef(
std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir)
);
+1 -1
View File
@@ -186,7 +186,7 @@ static void fetchTree(
}
if (!evalSettings.pureEval && !input.isDirect())
input = lookupInRegistries(state.ctx.store, input).first;
input = state.aio.blockOn(lookupInRegistries(state.ctx.store, input)).first;
if (evalSettings.pureEval && !input.isLocked()) {
state.ctx.errors.make<EvalError>("in pure evaluation mode, 'fetchTree' requires a locked input").atPos(pos).debugThrow();
+50 -26
View File
@@ -1,5 +1,7 @@
#include "lix/libfetchers/registry.hh"
#include "lix/libfetchers/fetchers.hh"
#include "lix/libutil/async.hh"
#include "lix/libutil/types.hh"
#include "lix/libutil/users.hh"
#include "lix/libstore/globals.hh"
#include "lix/libstore/store-api.hh"
@@ -7,7 +9,10 @@
#include "lix/libfetchers/fetch-settings.hh"
#include <memory>
#include <mutex>
#include <nlohmann/json.hpp>
#include <shared_mutex>
namespace nix::fetchers {
@@ -153,45 +158,62 @@ void overrideRegistry(
flagRegistry->add(from, to, extraAttrs);
}
static std::shared_ptr<Registry> getGlobalRegistry(ref<Store> store)
{
static auto reg = [&]() {
static kj::Promise<Result<std::shared_ptr<Registry>>> getGlobalRegistry(ref<Store> store)
try {
static std::shared_mutex mtx;
static std::shared_ptr<Registry> reg;
if (std::shared_lock l(mtx); reg) {
co_return reg;
}
std::scoped_lock l(mtx);
if (!reg) {
auto path = fetchSettings.flakeRegistry.get();
if (path == "") {
return std::make_shared<Registry>(Registry::Global); // empty registry
reg = std::make_shared<Registry>(Registry::Global); // empty registry
} else if (path == "vendored") {
return Registry::read(settings.nixDataDir + "/flake-registry.json", Registry::Global);
reg = Registry::read(settings.nixDataDir + "/flake-registry.json", Registry::Global);
} else {
if (!path.starts_with("/")) {
warn(
"config option flake-registry referring to a URL is deprecated and will be "
"removed in Lix 3.0; yours is: `%s'",
path
);
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");
path = store->toRealPath(storePath);
}
reg = Registry::read(path, Registry::Global);
}
};
if (!path.starts_with("/")) {
warn("config option flake-registry referring to a URL is deprecated and will be removed in Lix 3.0; yours is: `%s'", path);
auto storePath = downloadFile(store, path, "flake-registry.json", false).storePath;
if (auto store2 = store.dynamic_pointer_cast<LocalFSStore>())
store2->addPermRoot(storePath, getCacheDir() + "/nix/flake-registry.json");
path = store->toRealPath(storePath);
}
return Registry::read(path, Registry::Global);
}();
return reg;
co_return reg;
} catch (...) {
co_return result::current_exception();
}
Registries getRegistries(ref<Store> store)
{
kj::Promise<Result<Registries>> getRegistries(ref<Store> store)
try {
Registries registries;
registries.push_back(getFlagRegistry());
registries.push_back(getUserRegistry());
registries.push_back(getSystemRegistry());
registries.push_back(getGlobalRegistry(store));
return registries;
registries.push_back(TRY_AWAIT(getGlobalRegistry(store)));
co_return registries;
} catch (...) {
co_return result::current_exception();
}
std::pair<Input, Attrs> lookupInRegistries(
kj::Promise<Result<std::pair<Input, Attrs>>> lookupInRegistries(
ref<Store> store,
const Input & _input)
{
try {
Attrs extraAttrs;
int n = 0;
Input input(_input);
@@ -201,7 +223,7 @@ std::pair<Input, Attrs> lookupInRegistries(
n++;
if (n > 100) throw Error("cycle detected in flake registry for '%s'", input.to_string());
for (auto & registry : getRegistries(store)) {
for (auto & registry : TRY_AWAIT(getRegistries(store))) {
// FIXME: O(n)
for (auto & entry : registry->entries) {
if (entry.exact) {
@@ -227,7 +249,9 @@ std::pair<Input, Attrs> lookupInRegistries(
debug("looked up '%s' -> '%s'", _input.to_string(), input.to_string());
return {input, extraAttrs};
co_return {input, extraAttrs};
} catch (...) {
co_return result::current_exception();
}
}
+2 -2
View File
@@ -54,14 +54,14 @@ std::shared_ptr<Registry> getCustomRegistry(const Path & p);
Path getUserRegistryPath();
Registries getRegistries(ref<Store> store);
kj::Promise<Result<Registries>> getRegistries(ref<Store> store);
void overrideRegistry(
const Input & from,
const Input & to,
const Attrs & extraAttrs);
std::pair<Input, Attrs> lookupInRegistries(
kj::Promise<Result<std::pair<Input, Attrs>>> lookupInRegistries(
ref<Store> store,
const Input & input);
+1 -1
View File
@@ -69,7 +69,7 @@ struct CmdRegistryList : StoreCommand
{
using namespace fetchers;
auto registries = getRegistries(store);
auto registries = aio().blockOn(getRegistries(store));
for (auto & registry : registries) {
for (auto & entry : registry->entries) {