#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, 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> cache_; std::optional 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::getCache() { static auto cache = make_ref(); return cache; } }