Skip to content

Commit 3eb223f

Browse files
authored
Merge pull request #10915 from NixOS/dummy-memory
Use `MemorySourceAccessor` in `DummyStore` so writes work
2 parents 7ff6157 + d5ce8c3 commit 3eb223f

File tree

6 files changed

+117
-49
lines changed

6 files changed

+117
-49
lines changed

src/libfetchers-tests/git.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "nix/store/store-open.hh"
22
#include "nix/store/globals.hh"
3+
#include "nix/store/dummy-store.hh"
34
#include "nix/fetchers/fetch-settings.hh"
45
#include "nix/fetchers/fetchers.hh"
56
#include "nix/fetchers/git-utils.hh"
@@ -179,10 +180,11 @@ TEST_F(GitTest, submodulePeriodSupport)
179180
// 6) Commit the addition in super
180181
commitAll(super.get(), "Add submodule with branch='.'");
181182

182-
// TODO: Use dummy:// store with MemorySourceAccessor.
183-
Path storeTmpDir = createTempDir();
184-
auto storeTmpDirAutoDelete = AutoDelete(storeTmpDir, true);
185-
ref<Store> store = openStore(storeTmpDir);
183+
auto store = [] {
184+
auto cfg = make_ref<DummyStoreConfig>(StoreReference::Params{});
185+
cfg->readOnly = false;
186+
return cfg->openStore();
187+
}();
186188

187189
auto settings = fetchers::Settings{};
188190
auto input = fetchers::Input::fromAttrs(

src/libstore/dummy-store.cc

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,30 @@
11
#include "nix/store/store-registration.hh"
2+
#include "nix/util/archive.hh"
23
#include "nix/util/callback.hh"
4+
#include "nix/util/memory-source-accessor.hh"
5+
#include "nix/store/dummy-store.hh"
36

47
namespace nix {
58

6-
struct DummyStoreConfig : public std::enable_shared_from_this<DummyStoreConfig>, virtual StoreConfig
9+
std::string DummyStoreConfig::doc()
710
{
8-
using StoreConfig::StoreConfig;
9-
10-
DummyStoreConfig(std::string_view scheme, std::string_view authority, const Params & params)
11-
: StoreConfig(params)
12-
{
13-
if (!authority.empty())
14-
throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority);
15-
}
16-
17-
static const std::string name()
18-
{
19-
return "Dummy Store";
20-
}
21-
22-
static std::string doc()
23-
{
24-
return
11+
return
2512
#include "dummy-store.md"
26-
;
27-
}
28-
29-
static StringSet uriSchemes()
30-
{
31-
return {"dummy"};
32-
}
33-
34-
ref<Store> openStore() const override;
35-
36-
StoreReference getReference() const override
37-
{
38-
return {
39-
.variant =
40-
StoreReference::Specified{
41-
.scheme = *uriSchemes().begin(),
42-
},
43-
};
44-
}
45-
};
13+
;
14+
}
4615

4716
struct DummyStore : virtual Store
4817
{
4918
using Config = DummyStoreConfig;
5019

5120
ref<const Config> config;
5221

22+
ref<MemorySourceAccessor> contents;
23+
5324
DummyStore(ref<const Config> config)
5425
: Store{*config}
5526
, config(config)
27+
, contents(make_ref<MemorySourceAccessor>())
5628
{
5729
}
5830

@@ -80,16 +52,54 @@ struct DummyStore : virtual Store
8052
unsupported("addToStore");
8153
}
8254

83-
virtual StorePath addToStoreFromDump(
84-
Source & dump,
55+
StorePath addToStoreFromDump(
56+
Source & source,
8557
std::string_view name,
8658
FileSerialisationMethod dumpMethod = FileSerialisationMethod::NixArchive,
8759
ContentAddressMethod hashMethod = FileIngestionMethod::NixArchive,
8860
HashAlgorithm hashAlgo = HashAlgorithm::SHA256,
8961
const StorePathSet & references = StorePathSet(),
9062
RepairFlag repair = NoRepair) override
9163
{
92-
unsupported("addToStore");
64+
if (config->readOnly)
65+
unsupported("addToStoreFromDump");
66+
67+
auto temp = make_ref<MemorySourceAccessor>();
68+
69+
{
70+
MemorySink tempSink{*temp};
71+
72+
// TODO factor this out into `restorePath`, same todo on it.
73+
switch (dumpMethod) {
74+
case FileSerialisationMethod::NixArchive:
75+
parseDump(tempSink, source);
76+
break;
77+
case FileSerialisationMethod::Flat: {
78+
// Replace root dir with file so next part succeeds.
79+
temp->root = MemorySourceAccessor::File::Regular{};
80+
tempSink.createRegularFile(CanonPath::root, [&](auto & sink) { source.drainInto(sink); });
81+
break;
82+
}
83+
}
84+
}
85+
86+
auto hash = hashPath({temp, CanonPath::root}, hashMethod.getFileIngestionMethod(), hashAlgo).first;
87+
88+
auto desc = ContentAddressWithReferences::fromParts(
89+
hashMethod,
90+
hash,
91+
{
92+
.others = references,
93+
// caller is not capable of creating a self-reference, because
94+
// this is content-addressed without modulus
95+
.self = false,
96+
});
97+
98+
auto dstPath = makeFixedOutputPathFromCA(name, desc);
99+
100+
contents->open(CanonPath(printStorePath(dstPath)), std::move(temp->root));
101+
102+
return dstPath;
93103
}
94104

95105
void narFromPath(const StorePath & path, Sink & sink) override
@@ -105,7 +115,7 @@ struct DummyStore : virtual Store
105115

106116
virtual ref<SourceAccessor> getFSAccessor(bool requireValidPath) override
107117
{
108-
return makeEmptySourceAccessor();
118+
return this->contents;
109119
}
110120
};
111121

src/libstore/dummy-store.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ R"(
22

33
**Store URL format**: `dummy://`
44

5-
This store type represents a store that contains no store paths and
6-
cannot be written to. It's useful when you want to use the Nix
7-
evaluator when no actual Nix store exists, e.g.
5+
This store type represents a store in memory.
6+
Store objects can be read and written, but only so long as the store is open.
7+
Once the store is closed, all data will be forgoton.
8+
9+
It's useful when you want to use the Nix evaluator when no actual Nix store exists, e.g.
810

911
```console
1012
# nix eval --store dummy:// --expr '1 + 2'
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include "nix/store/store-api.hh"
2+
3+
namespace nix {
4+
5+
struct DummyStoreConfig : public std::enable_shared_from_this<DummyStoreConfig>, virtual StoreConfig
6+
{
7+
using StoreConfig::StoreConfig;
8+
9+
DummyStoreConfig(std::string_view scheme, std::string_view authority, const Params & params)
10+
: StoreConfig(params)
11+
{
12+
if (!authority.empty())
13+
throw UsageError("`%s` store URIs must not contain an authority part %s", scheme, authority);
14+
}
15+
16+
Setting<bool> readOnly{
17+
this,
18+
true,
19+
"read-only",
20+
R"(
21+
Make any sort of write fail instead of succeeding.
22+
No additional memory will be used, because no information needs to be stored.
23+
)"};
24+
25+
static const std::string name()
26+
{
27+
return "Dummy Store";
28+
}
29+
30+
static std::string doc();
31+
32+
static StringSet uriSchemes()
33+
{
34+
return {"dummy"};
35+
}
36+
37+
ref<Store> openStore() const override;
38+
39+
StoreReference getReference() const override
40+
{
41+
return {
42+
.variant =
43+
StoreReference::Specified{
44+
.scheme = *uriSchemes().begin(),
45+
},
46+
};
47+
}
48+
};
49+
50+
} // namespace nix

src/libstore/include/nix/store/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ headers = [ config_pub_h ] + files(
3434
'derived-path-map.hh',
3535
'derived-path.hh',
3636
'downstream-placeholder.hh',
37+
'dummy-store.hh',
3738
'export-import.hh',
3839
'filetransfer.hh',
3940
'gc-store.hh',

src/libutil/include/nix/util/memory-source-accessor.hh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#pragma once
2+
///@file
3+
14
#include "nix/util/source-path.hh"
25
#include "nix/util/fs-sink.hh"
36
#include "nix/util/variant-wrapper.hh"

0 commit comments

Comments
 (0)