diff --git a/src/libstore/dummy-store.cc b/src/libstore/dummy-store.cc index 1eb51fe3ebf..1be81dfbc3b 100644 --- a/src/libstore/dummy-store.cc +++ b/src/libstore/dummy-store.cc @@ -15,8 +15,7 @@ std::string DummyStoreConfig::doc() ; } -namespace { - +// Note: This class is used by DummyStoreImpl and needs to be visible class WholeStoreViewAccessor : public SourceAccessor { using BaseName = std::string; @@ -106,184 +105,167 @@ class WholeStoreViewAccessor : public SourceAccessor } }; -} // namespace - ref DummyStoreConfig::openStore() const { return openDummyStore(); } -struct DummyStoreImpl : DummyStore -{ - using Config = DummyStoreConfig; +// DummyStoreImpl method implementations - /** - * This view conceptually just borrows the file systems objects of - * each store object from `contents`, and combines them together - * into one store-wide source accessor. - * - * This is needed just in order to implement `Store::getFSAccessor`. - */ - ref wholeStoreView = make_ref(); +DummyStoreImpl::DummyStoreImpl(ref config) + : Store{*config} + , DummyStore{config} + , wholeStoreView(make_ref()) +{ + wholeStoreView->setPathDisplay(config->storeDir); +} - DummyStoreImpl(ref config) - : Store{*config} - , DummyStore{config} - { - wholeStoreView->setPathDisplay(config->storeDir); - } +void DummyStoreImpl::queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept +{ + bool visited = contents.cvisit( + path, [&](const auto & kv) { callback(std::make_shared(StorePath{kv.first}, kv.second.info)); }); - void queryPathInfoUncached( - const StorePath & path, Callback> callback) noexcept override - { - bool visited = contents.cvisit(path, [&](const auto & kv) { - callback(std::make_shared(StorePath{kv.first}, kv.second.info)); - }); + if (!visited) + callback(nullptr); +} - if (!visited) - callback(nullptr); - } +std::optional DummyStoreImpl::isTrustedClient() +{ + return Trusted; +} - /** - * The dummy store is incapable of *not* trusting! :) - */ - virtual std::optional isTrustedClient() override - { - return Trusted; - } +std::optional DummyStoreImpl::queryPathFromHashPart(const std::string & hashPart) +{ + unsupported("queryPathFromHashPart"); +} - std::optional queryPathFromHashPart(const std::string & hashPart) override - { - unsupported("queryPathFromHashPart"); - } +void DummyStoreImpl::addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) +{ + if (config->readOnly) + unsupported("addToStore"); + + if (repair) + throw Error("repairing is not supported for '%s' store", config->getHumanReadableURI()); + + if (checkSigs) + throw Error("checking signatures is not supported for '%s' store", config->getHumanReadableURI()); + + auto temp = make_ref(); + MemorySink tempSink{*temp}; + parseDump(tempSink, source); + auto path = info.path; + + auto accessor = make_ref(std::move(*temp)); + contents.insert( + {path, + PathInfoAndContents{ + std::move(info), + accessor, + }}); + wholeStoreView->addObject(path.to_string(), accessor); +} - void addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override - { - if (config->readOnly) - unsupported("addToStore"); +StorePath DummyStoreImpl::addToStoreFromDump( + Source & source, + std::string_view name, + FileSerialisationMethod dumpMethod, + ContentAddressMethod hashMethod, + HashAlgorithm hashAlgo, + const StorePathSet & references, + RepairFlag repair) +{ + if (config->readOnly) + unsupported("addToStoreFromDump"); - if (repair) - throw Error("repairing is not supported for '%s' store", config->getHumanReadableURI()); + if (repair) + throw Error("repairing is not supported for '%s' store", config->getHumanReadableURI()); - if (checkSigs) - throw Error("checking signatures is not supported for '%s' store", config->getHumanReadableURI()); + auto temp = make_ref(); - auto temp = make_ref(); + { MemorySink tempSink{*temp}; - parseDump(tempSink, source); - auto path = info.path; - - auto accessor = make_ref(std::move(*temp)); - contents.insert( - {path, - PathInfoAndContents{ - std::move(info), - accessor, - }}); - wholeStoreView->addObject(path.to_string(), accessor); - } - StorePath addToStoreFromDump( - Source & source, - std::string_view name, - FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive, - ContentAddressMethod hashMethod = FileIngestionMethod::NixArchive, - HashAlgorithm hashAlgo = HashAlgorithm::SHA256, - const StorePathSet & references = StorePathSet(), - RepairFlag repair = NoRepair) override - { - if (config->readOnly) - unsupported("addToStoreFromDump"); - - if (repair) - throw Error("repairing is not supported for '%s' store", config->getHumanReadableURI()); - - auto temp = make_ref(); - - { - MemorySink tempSink{*temp}; - - // TODO factor this out into `restorePath`, same todo on it. - switch (dumpMethod) { - case FileSerialisationMethod::NixArchive: - parseDump(tempSink, source); - break; - case FileSerialisationMethod::Flat: { - // Replace root dir with file so next part succeeds. - temp->root = MemorySourceAccessor::File::Regular{}; - tempSink.createRegularFile(CanonPath::root, [&](auto & sink) { source.drainInto(sink); }); - break; - } - } + // TODO factor this out into `restorePath`, same todo on it. + switch (dumpMethod) { + case FileSerialisationMethod::NixArchive: + parseDump(tempSink, source); + break; + case FileSerialisationMethod::Flat: { + // Replace root dir with file so next part succeeds. + temp->root = MemorySourceAccessor::File::Regular{}; + tempSink.createRegularFile(CanonPath::root, [&](auto & sink) { source.drainInto(sink); }); + break; + } } - - auto hash = hashPath({temp, CanonPath::root}, hashMethod.getFileIngestionMethod(), hashAlgo).first; - auto narHash = hashPath({temp, CanonPath::root}, FileIngestionMethod::NixArchive, HashAlgorithm::SHA256); - - auto info = ValidPathInfo::makeFromCA( - *this, - name, - ContentAddressWithReferences::fromParts( - hashMethod, - std::move(hash), - { - .others = references, - // caller is not capable of creating a self-reference, because - // this is content-addressed without modulus - .self = false, - }), - std::move(narHash.first)); - - info.narSize = narHash.second.value(); - - auto path = info.path; - auto accessor = make_ref(std::move(*temp)); - contents.insert( - {path, - PathInfoAndContents{ - std::move(info), - accessor, - }}); - wholeStoreView->addObject(path.to_string(), accessor); - - return path; } - void registerDrvOutput(const Realisation & output) override - { - unsupported("registerDrvOutput"); - } + auto hash = hashPath({temp, CanonPath::root}, hashMethod.getFileIngestionMethod(), hashAlgo).first; + auto narHash = hashPath({temp, CanonPath::root}, FileIngestionMethod::NixArchive, HashAlgorithm::SHA256); + + auto info = ValidPathInfo::makeFromCA( + *this, + name, + ContentAddressWithReferences::fromParts( + hashMethod, + std::move(hash), + { + .others = references, + // caller is not capable of creating a self-reference, because + // this is content-addressed without modulus + .self = false, + }), + std::move(narHash.first)); + + info.narSize = narHash.second.value(); + + auto path = info.path; + auto accessor = make_ref(std::move(*temp)); + contents.insert( + {path, + PathInfoAndContents{ + std::move(info), + accessor, + }}); + wholeStoreView->addObject(path.to_string(), accessor); + + return path; +} - void narFromPath(const StorePath & path, Sink & sink) override - { - bool visited = contents.cvisit(path, [&](const auto & kv) { - const auto & [info, accessor] = kv.second; - SourcePath sourcePath(accessor); - dumpPath(sourcePath, sink, FileSerialisationMethod::NixArchive); - }); +void DummyStoreImpl::registerDrvOutput(const Realisation & output) +{ + unsupported("registerDrvOutput"); +} - if (!visited) - throw Error("path '%s' is not valid", printStorePath(path)); - } +void DummyStoreImpl::narFromPath(const StorePath & path, Sink & sink) +{ + bool visited = contents.cvisit(path, [&](const auto & kv) { + const auto & [info, accessor] = kv.second; + SourcePath sourcePath(accessor); + dumpPath(sourcePath, sink, FileSerialisationMethod::NixArchive); + }); + + if (!visited) + throw Error("path '%s' is not valid", printStorePath(path)); +} - void - queryRealisationUncached(const DrvOutput &, Callback> callback) noexcept override - { - callback(nullptr); - } +void DummyStoreImpl::queryRealisationUncached( + const DrvOutput &, Callback> callback) noexcept +{ + callback(nullptr); +} - std::shared_ptr getFSAccessor(const StorePath & path, bool requireValidPath) override - { - std::shared_ptr res; - contents.cvisit(path, [&](const auto & kv) { res = kv.second.contents.get_ptr(); }); - return res; - } +std::shared_ptr DummyStoreImpl::getFSAccessor(const StorePath & path, bool requireValidPath) +{ + std::shared_ptr res; + contents.cvisit(path, [&](const auto & kv) { res = kv.second.contents.get_ptr(); }); + return res; +} - ref getFSAccessor(bool requireValidPath) override - { - return wholeStoreView; - } -}; +ref DummyStoreImpl::getFSAccessor(bool requireValidPath) +{ + return wholeStoreView; +} ref DummyStore::Config::openDummyStore() const { diff --git a/src/libstore/include/nix/store/dummy-store-impl.hh b/src/libstore/include/nix/store/dummy-store-impl.hh index e05bb94ff76..32678fb0b75 100644 --- a/src/libstore/include/nix/store/dummy-store-impl.hh +++ b/src/libstore/include/nix/store/dummy-store-impl.hh @@ -8,6 +8,7 @@ namespace nix { struct MemorySourceAccessor; +class WholeStoreViewAccessor; /** * Enough of the Dummy Store exposed for sake of writing unit tests @@ -37,4 +38,58 @@ struct DummyStore : virtual Store } }; +/** + * Full implementation of DummyStore. + * Exposed in the header so it can be inherited from in tests. + */ +class DummyStoreImpl : public DummyStore +{ +protected: + /** + * This view conceptually just borrows the file systems objects of + * each store object from `contents`, and combines them together + * into one store-wide source accessor. + * + * This is needed just in order to implement `Store::getFSAccessor`. + */ + ref wholeStoreView; + +public: + using Config = DummyStoreConfig; + + DummyStoreImpl(ref config); + + void queryPathInfoUncached( + const StorePath & path, Callback> callback) noexcept override; + + /** + * The dummy store is incapable of *not* trusting! :) + */ + virtual std::optional isTrustedClient() override; + + std::optional queryPathFromHashPart(const std::string & hashPart) override; + + void addToStore(const ValidPathInfo & info, Source & source, RepairFlag repair, CheckSigsFlag checkSigs) override; + + virtual StorePath addToStoreFromDump( + Source & source, + std::string_view name, + FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive, + ContentAddressMethod hashMethod = FileIngestionMethod::NixArchive, + HashAlgorithm hashAlgo = HashAlgorithm::SHA256, + const StorePathSet & references = StorePathSet(), + RepairFlag repair = NoRepair) override; + + void registerDrvOutput(const Realisation & output) override; + + void narFromPath(const StorePath & path, Sink & sink) override; + + void queryRealisationUncached( + const DrvOutput &, Callback> callback) noexcept override; + + std::shared_ptr getFSAccessor(const StorePath & path, bool requireValidPath) override; + + ref getFSAccessor(bool requireValidPath) override; +}; + } // namespace nix