fetchOrSubstituteTree improvements

Caches tree in addition to lockedRef, and explicitly writes out the logic for different combinations of cached/uncached flakes and indirect/resolved/locked flakes. This eliminates uneccessary calls to lookupInFlakeCache, fetchTree, maybeLookupFlake, and flakeCache.push_back
This commit is contained in:
Matthew Kenigsberg 2020-06-01 01:39:15 -06:00
parent 89e0b3e2d6
commit ff1320b850

View file

@ -12,25 +12,10 @@ using namespace flake;
namespace flake { namespace flake {
/* If 'allowLookup' is true, then resolve 'flakeRef' using the typedef std::pair<Tree, FlakeRef> FetchedFlake;
registries. */ typedef std::vector<std::pair<FlakeRef, FetchedFlake>> FlakeCache;
static FlakeRef maybeLookupFlake(
ref<Store> store,
const FlakeRef & flakeRef,
bool allowLookup)
{
if (!flakeRef.input.isDirect()) {
if (allowLookup)
return flakeRef.resolve(store);
else
throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", flakeRef);
} else
return flakeRef;
}
typedef std::vector<std::pair<FlakeRef, FlakeRef>> FlakeCache; static std::optional<FetchedFlake> lookupInFlakeCache(
static FlakeRef lookupInFlakeCache(
const FlakeCache & flakeCache, const FlakeCache & flakeCache,
const FlakeRef & flakeRef) const FlakeRef & flakeRef)
{ {
@ -38,12 +23,12 @@ static FlakeRef lookupInFlakeCache(
for (auto & i : flakeCache) { for (auto & i : flakeCache) {
if (flakeRef == i.first) { if (flakeRef == i.first) {
debug("mapping '%s' to previously seen input '%s' -> '%s", debug("mapping '%s' to previously seen input '%s' -> '%s",
flakeRef, i.first, i.second); flakeRef, i.first, i.second.second);
return i.second; return i.second;
} }
} }
return flakeRef; return std::nullopt;
} }
static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree( static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
@ -52,17 +37,32 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
bool allowLookup, bool allowLookup,
FlakeCache & flakeCache) FlakeCache & flakeCache)
{ {
auto resolvedRef = lookupInFlakeCache(flakeCache, auto fetched = lookupInFlakeCache(flakeCache, originalRef);
maybeLookupFlake(state.store, FlakeRef resolvedRef = originalRef;
lookupInFlakeCache(flakeCache, originalRef), allowLookup));
auto [tree, lockedRef] = resolvedRef.fetchTree(state.store); if (!fetched) {
if (originalRef.input.isDirect()) {
fetched.emplace(originalRef.fetchTree(state.store));
} else {
if (allowLookup) {
resolvedRef = originalRef.resolve(state.store);
auto fetchedResolved = lookupInFlakeCache(flakeCache, originalRef);
if (!fetchedResolved) fetchedResolved.emplace(resolvedRef.fetchTree(state.store));
flakeCache.push_back({resolvedRef, fetchedResolved.value()});
fetched.emplace(fetchedResolved.value());
}
else {
throw Error("'%s' is an indirect flake reference, but registry lookups are not allowed", originalRef);
}
}
flakeCache.push_back({originalRef, fetched.value()});
}
auto [tree, lockedRef] = fetched.value();
debug("got tree '%s' from '%s'", debug("got tree '%s' from '%s'",
state.store->printStorePath(tree.storePath), lockedRef); state.store->printStorePath(tree.storePath), lockedRef);
flakeCache.push_back({originalRef, lockedRef});
flakeCache.push_back({resolvedRef, lockedRef});
if (state.allowedPaths) if (state.allowedPaths)
state.allowedPaths->insert(tree.actualPath); state.allowedPaths->insert(tree.actualPath);