mirror of
https://github.com/NixOS/nix.git
synced 2025-11-15 23:12:44 +01:00
81 lines
2.7 KiB
C++
81 lines
2.7 KiB
C++
#include "nix/fetchers/input-cache.hh"
|
|
#include "nix/fetchers/registry.hh"
|
|
#include "nix/util/sync.hh"
|
|
#include "nix/util/source-path.hh"
|
|
|
|
namespace nix::fetchers {
|
|
|
|
InputCache::CachedResult InputCache::getAccessor(ref<Store> store, const Input & originalInput, bool useRegistries)
|
|
{
|
|
auto fetched = lookup(originalInput);
|
|
Input resolvedInput = originalInput;
|
|
|
|
if (!fetched) {
|
|
if (originalInput.isDirect()) {
|
|
auto [accessor, lockedInput] = originalInput.getAccessor(store);
|
|
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
|
|
} else {
|
|
if (useRegistries) {
|
|
auto [res, extraAttrs] =
|
|
lookupInRegistries(store, originalInput, [](fetchers::Registry::RegistryType type) {
|
|
/* Only use the global registry and CLI flags
|
|
to resolve indirect flakerefs. */
|
|
return type == fetchers::Registry::Flag || type == fetchers::Registry::Global;
|
|
});
|
|
resolvedInput = std::move(res);
|
|
fetched = lookup(resolvedInput);
|
|
if (!fetched) {
|
|
auto [accessor, lockedInput] = resolvedInput.getAccessor(store);
|
|
fetched.emplace(CachedInput{.lockedInput = lockedInput, .accessor = accessor});
|
|
}
|
|
upsert(resolvedInput, *fetched);
|
|
} else {
|
|
throw Error(
|
|
"'%s' is an indirect flake reference, but registry lookups are not allowed",
|
|
originalInput.to_string());
|
|
}
|
|
}
|
|
upsert(originalInput, *fetched);
|
|
}
|
|
|
|
debug("got tree '%s' from '%s'", fetched->accessor, fetched->lockedInput.to_string());
|
|
|
|
return {fetched->accessor, resolvedInput, fetched->lockedInput};
|
|
}
|
|
|
|
struct InputCacheImpl : InputCache
|
|
{
|
|
Sync<std::map<Input, CachedInput>> cache_;
|
|
|
|
std::optional<CachedInput> lookup(const Input & originalInput) const override
|
|
{
|
|
auto cache(cache_.readLock());
|
|
auto i = cache->find(originalInput);
|
|
if (i == cache->end())
|
|
return std::nullopt;
|
|
debug(
|
|
"mapping '%s' to previously seen input '%s' -> '%s",
|
|
originalInput.to_string(),
|
|
i->first.to_string(),
|
|
i->second.lockedInput.to_string());
|
|
return i->second;
|
|
}
|
|
|
|
void upsert(Input key, CachedInput cachedInput) override
|
|
{
|
|
cache_.lock()->insert_or_assign(std::move(key), std::move(cachedInput));
|
|
}
|
|
|
|
void clear() override
|
|
{
|
|
cache_.lock()->clear();
|
|
}
|
|
};
|
|
|
|
ref<InputCache> InputCache::getCache()
|
|
{
|
|
static auto cache = make_ref<InputCacheImpl>();
|
|
return cache;
|
|
}
|
|
|
|
}
|