From 1042c10fd0417fe33dd879317f5d7a73aa6f7fe3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 25 Feb 2016 17:43:19 +0100 Subject: Add NAR / Store accessor abstraction This is primary to allow hydra-queue-runner to extract files like "nix-support/hydra-build-products" from NARs in binary caches. --- src/libstore/binary-cache-store.cc | 80 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 4 deletions(-) (limited to 'src/libstore/binary-cache-store.cc') diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc index dc086fe9c..6a4e3a560 100644 --- a/src/libstore/binary-cache-store.cc +++ b/src/libstore/binary-cache-store.cc @@ -1,12 +1,13 @@ -#include "binary-cache-store.hh" -#include "sync.hh" - #include "archive.hh" +#include "binary-cache-store.hh" #include "compression.hh" #include "derivations.hh" +#include "fs-accessor.hh" #include "globals.hh" #include "nar-info.hh" +#include "sync.hh" #include "worker-protocol.hh" +#include "nar-accessor.hh" #include @@ -122,7 +123,8 @@ NarInfo BinaryCacheStore::readNarInfo(const Path & storePath) auto narInfoFile = narInfoFileFor(storePath); auto narInfo = make_ref(getFile(narInfoFile), narInfoFile); - assert(narInfo->path == storePath); + if (narInfo->path != storePath) + throw Error(format("NAR info file for store path ‘%1%’ does not match ‘%2%’") % narInfo->path % storePath); stats.narInfoRead++; @@ -142,6 +144,9 @@ NarInfo BinaryCacheStore::readNarInfo(const Path & storePath) bool BinaryCacheStore::isValidPath(const Path & storePath) { + // FIXME: this only checks whether a .narinfo with a matching hash + // part exists. So ‘f4kb...-foo’ matches ‘f4kb...-bar’, even + // though they shouldn't. Not easily fixed. return fileExists(narInfoFileFor(storePath)); } @@ -344,4 +349,71 @@ void BinaryCacheStore::ensurePath(const Path & path) buildPaths({path}); } +/* Given requests for a path /nix/store//, this accessor will + first download the NAR for /nix/store/ from the binary cache, + build a NAR accessor for that NAR, and use that to access . */ +struct BinaryCacheStoreAccessor : public FSAccessor +{ + ref store; + + std::map> nars; + + BinaryCacheStoreAccessor(ref store) + : store(store) + { + } + + std::pair, Path> fetch(const Path & path_) + { + auto path = canonPath(path_); + + auto storePath = toStorePath(path); + std::string restPath = std::string(path, storePath.size()); + + if (!store->isValidPath(storePath)) + throw Error(format("path ‘%1%’ is not a valid store path") % storePath); + + auto i = nars.find(storePath); + if (i != nars.end()) return {i->second, restPath}; + + StringSink sink; + store->exportPath(storePath, false, sink); + + // FIXME: gratuitous string copying. + auto accessor = makeNarAccessor(make_ref(sink.s)); + nars.emplace(storePath, accessor); + return {accessor, restPath}; + } + + Stat stat(const Path & path) override + { + auto res = fetch(path); + return res.first->stat(res.second); + } + + StringSet readDirectory(const Path & path) override + { + auto res = fetch(path); + return res.first->readDirectory(res.second); + } + + std::string readFile(const Path & path) override + { + auto res = fetch(path); + return res.first->readFile(res.second); + } + + std::string readLink(const Path & path) override + { + auto res = fetch(path); + return res.first->readLink(res.second); + } +}; + +ref BinaryCacheStore::getFSAccessor() +{ + return make_ref(ref( + std::dynamic_pointer_cast(shared_from_this()))); +} + } -- cgit v1.2.3