1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00

Merge pull request #10915 from NixOS/dummy-memory

Use `MemorySourceAccessor` in `DummyStore` so writes work
This commit is contained in:
Robert Hensing 2025-09-17 22:33:17 +02:00 committed by GitHub
commit 3eb223f4bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 117 additions and 49 deletions

View file

@ -1,5 +1,6 @@
#include "nix/store/store-open.hh" #include "nix/store/store-open.hh"
#include "nix/store/globals.hh" #include "nix/store/globals.hh"
#include "nix/store/dummy-store.hh"
#include "nix/fetchers/fetch-settings.hh" #include "nix/fetchers/fetch-settings.hh"
#include "nix/fetchers/fetchers.hh" #include "nix/fetchers/fetchers.hh"
#include "nix/fetchers/git-utils.hh" #include "nix/fetchers/git-utils.hh"
@ -179,10 +180,11 @@ TEST_F(GitTest, submodulePeriodSupport)
// 6) Commit the addition in super // 6) Commit the addition in super
commitAll(super.get(), "Add submodule with branch='.'"); commitAll(super.get(), "Add submodule with branch='.'");
// TODO: Use dummy:// store with MemorySourceAccessor. auto store = [] {
Path storeTmpDir = createTempDir(); auto cfg = make_ref<DummyStoreConfig>(StoreReference::Params{});
auto storeTmpDirAutoDelete = AutoDelete(storeTmpDir, true); cfg->readOnly = false;
ref<Store> store = openStore(storeTmpDir); return cfg->openStore();
}();
auto settings = fetchers::Settings{}; auto settings = fetchers::Settings{};
auto input = fetchers::Input::fromAttrs( auto input = fetchers::Input::fromAttrs(

View file

@ -1,48 +1,17 @@
#include "nix/store/store-registration.hh" #include "nix/store/store-registration.hh"
#include "nix/util/archive.hh"
#include "nix/util/callback.hh" #include "nix/util/callback.hh"
#include "nix/util/memory-source-accessor.hh"
#include "nix/store/dummy-store.hh"
namespace nix { namespace nix {
struct DummyStoreConfig : public std::enable_shared_from_this<DummyStoreConfig>, virtual StoreConfig std::string DummyStoreConfig::doc()
{ {
using StoreConfig::StoreConfig; return
DummyStoreConfig(std::string_view scheme, std::string_view authority, const Params & params)
: StoreConfig(params)
{
if (!authority.empty())
throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority);
}
static const std::string name()
{
return "Dummy Store";
}
static std::string doc()
{
return
#include "dummy-store.md" #include "dummy-store.md"
; ;
} }
static StringSet uriSchemes()
{
return {"dummy"};
}
ref<Store> openStore() const override;
StoreReference getReference() const override
{
return {
.variant =
StoreReference::Specified{
.scheme = *uriSchemes().begin(),
},
};
}
};
struct DummyStore : virtual Store struct DummyStore : virtual Store
{ {
@ -50,9 +19,12 @@ struct DummyStore : virtual Store
ref<const Config> config; ref<const Config> config;
ref<MemorySourceAccessor> contents;
DummyStore(ref<const Config> config) DummyStore(ref<const Config> config)
: Store{*config} : Store{*config}
, config(config) , config(config)
, contents(make_ref<MemorySourceAccessor>())
{ {
} }
@ -80,8 +52,8 @@ struct DummyStore : virtual Store
unsupported("addToStore"); unsupported("addToStore");
} }
virtual StorePath addToStoreFromDump( StorePath addToStoreFromDump(
Source & dump, Source & source,
std::string_view name, std::string_view name,
FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive, FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive,
ContentAddressMethod hashMethod = FileIngestionMethod::NixArchive, ContentAddressMethod hashMethod = FileIngestionMethod::NixArchive,
@ -89,7 +61,45 @@ struct DummyStore : virtual Store
const StorePathSet & references = StorePathSet(), const StorePathSet & references = StorePathSet(),
RepairFlag repair = NoRepair) override RepairFlag repair = NoRepair) override
{ {
unsupported("addToStore"); if (config->readOnly)
unsupported("addToStoreFromDump");
auto temp = make_ref<MemorySourceAccessor>();
{
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;
}
}
}
auto hash = hashPath({temp, CanonPath::root}, hashMethod.getFileIngestionMethod(), hashAlgo).first;
auto desc = ContentAddressWithReferences::fromParts(
hashMethod,
hash,
{
.others = references,
// caller is not capable of creating a self-reference, because
// this is content-addressed without modulus
.self = false,
});
auto dstPath = makeFixedOutputPathFromCA(name, desc);
contents->open(CanonPath(printStorePath(dstPath)), std::move(temp->root));
return dstPath;
} }
void narFromPath(const StorePath & path, Sink & sink) override void narFromPath(const StorePath & path, Sink & sink) override
@ -105,7 +115,7 @@ struct DummyStore : virtual Store
virtual ref<SourceAccessor> getFSAccessor(bool requireValidPath) override virtual ref<SourceAccessor> getFSAccessor(bool requireValidPath) override
{ {
return makeEmptySourceAccessor(); return this->contents;
} }
}; };

View file

@ -2,9 +2,11 @@ R"(
**Store URL format**: `dummy://` **Store URL format**: `dummy://`
This store type represents a store that contains no store paths and This store type represents a store in memory.
cannot be written to. It's useful when you want to use the Nix Store objects can be read and written, but only so long as the store is open.
evaluator when no actual Nix store exists, e.g. Once the store is closed, all data will be forgoton.
It's useful when you want to use the Nix evaluator when no actual Nix store exists, e.g.
```console ```console
# nix eval --store dummy:// --expr '1 + 2' # nix eval --store dummy:// --expr '1 + 2'

View file

@ -0,0 +1,50 @@
#include "nix/store/store-api.hh"
namespace nix {
struct DummyStoreConfig : public std::enable_shared_from_this<DummyStoreConfig>, virtual StoreConfig
{
using StoreConfig::StoreConfig;
DummyStoreConfig(std::string_view scheme, std::string_view authority, const Params & params)
: StoreConfig(params)
{
if (!authority.empty())
throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority);
}
Setting<bool> readOnly{
this,
true,
"read-only",
R"(
Make any sort of write fail instead of succeeding.
No additional memory will be used, because no information needs to be stored.
)"};
static const std::string name()
{
return "Dummy Store";
}
static std::string doc();
static StringSet uriSchemes()
{
return {"dummy"};
}
ref<Store> openStore() const override;
StoreReference getReference() const override
{
return {
.variant =
StoreReference::Specified{
.scheme = *uriSchemes().begin(),
},
};
}
};
} // namespace nix

View file

@ -34,6 +34,7 @@ headers = [ config_pub_h ] + files(
'derived-path-map.hh', 'derived-path-map.hh',
'derived-path.hh', 'derived-path.hh',
'downstream-placeholder.hh', 'downstream-placeholder.hh',
'dummy-store.hh',
'export-import.hh', 'export-import.hh',
'filetransfer.hh', 'filetransfer.hh',
'gc-store.hh', 'gc-store.hh',

View file

@ -1,3 +1,6 @@
#pragma once
///@file
#include "nix/util/source-path.hh" #include "nix/util/source-path.hh"
#include "nix/util/fs-sink.hh" #include "nix/util/fs-sink.hh"
#include "nix/util/variant-wrapper.hh" #include "nix/util/variant-wrapper.hh"