diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index 65c332935..9347da86e 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -160,11 +160,14 @@ void Input::checkLocks(Input & input) const std::pair, Input> Input::getAccessor(ref store) const { + // FIXME: cache the accessor + if (!scheme) throw Error("cannot fetch unsupported input '%s'", attrsToJSON(toAttrs())); try { auto [accessor, final] = scheme->getAccessor(store, *this); + accessor->fingerprint = scheme->getFingerprint(store, *this); checkLocks(final); return {accessor, std::move(final)}; } catch (Error & e) { @@ -256,10 +259,7 @@ std::optional Input::getLastModified() const std::optional Input::getFingerprint(ref store) const { - if (auto rev = getRev()) - return rev->gitRev(); - assert(scheme); - return scheme->getFingerprint(store, *this); + return scheme ? scheme->getFingerprint(store, *this) : std::nullopt; } ParsedURL InputScheme::toURL(const Input & input) const @@ -293,4 +293,12 @@ void InputScheme::clone(const Input & input, const Path & destDir) const throw Error("do not know how to clone input '%s'", input.to_string()); } +std::optional InputScheme::getFingerprint(ref store, const Input & input) const +{ + if (auto rev = input.getRev()) + return rev->gitRev(); + else + return std::nullopt; +} + } diff --git a/src/libfetchers/fetchers.hh b/src/libfetchers/fetchers.hh index 4d1e829f0..a890a5ef0 100644 --- a/src/libfetchers/fetchers.hh +++ b/src/libfetchers/fetchers.hh @@ -141,8 +141,7 @@ struct InputScheme virtual std::optional isRelative(const Input & input) const { return std::nullopt; } - virtual std::optional getFingerprint(ref store, const Input & input) const - { return std::nullopt; } + virtual std::optional getFingerprint(ref store, const Input & input) const; }; void registerInputScheme(std::shared_ptr && fetcher); diff --git a/src/libfetchers/input-accessor.cc b/src/libfetchers/input-accessor.cc index f1a9a9e95..54b173cf6 100644 --- a/src/libfetchers/input-accessor.cc +++ b/src/libfetchers/input-accessor.cc @@ -1,6 +1,7 @@ #include "input-accessor.hh" #include "util.hh" #include "store-api.hh" +#include "cache.hh" #include @@ -96,6 +97,21 @@ StorePath InputAccessor::fetchToStore( // FIXME: add an optimisation for the case where the accessor is // an FSInputAccessor pointing to a store path. + std::optional cacheKey; + + if (!filter && fingerprint) { + cacheKey = *fingerprint + "|" + name + "|" + path.abs(); + if (auto storePathS = fetchers::getCache()->queryFact(*cacheKey)) { + if (auto storePath = store->maybeParseStorePath(*storePathS)) { + if (store->isValidPath(*storePath)) { + debug("store path cache hit for '%s'", showPath(path)); + return *storePath; + } + } + } + } else + debug("source path '%s' is uncacheable", showPath(path)); + auto source = sinkToSource([&](Sink & sink) { dumpPath(path, sink, filter ? *filter : defaultPathFilter); }); @@ -105,6 +121,9 @@ StorePath InputAccessor::fetchToStore( ? store->computeStorePathFromDump(*source, name).first : store->addToStoreFromDump(*source, name, FileIngestionMethod::Recursive, htSHA256, repair); + if (cacheKey) + fetchers::getCache()->upsertFact(*cacheKey, store->printStorePath(storePath)); + return storePath; } diff --git a/src/libfetchers/input-accessor.hh b/src/libfetchers/input-accessor.hh index bbb0554b6..86efdd046 100644 --- a/src/libfetchers/input-accessor.hh +++ b/src/libfetchers/input-accessor.hh @@ -21,6 +21,8 @@ struct InputAccessor : public std::enable_shared_from_this std::string displayPrefix, displaySuffix; + std::optional fingerprint; + InputAccessor(); virtual ~InputAccessor()