@@ -137,12 +137,40 @@ struct DummyStoreImpl : DummyStore
137137 void queryPathInfoUncached (
138138 const StorePath & path, Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override
139139 {
140- bool visited = contents.cvisit (path, [&](const auto & kv) {
141- callback (std::make_shared<ValidPathInfo>(StorePath{kv.first }, kv.second .info ));
142- });
140+ if (path.isDerivation ()) {
141+ if (auto accessor_ = getMemoryFSAccessor (path)) {
142+ ref<MemorySourceAccessor> accessor = ref{std::move (accessor_)};
143+ /* compute path info on demand */
144+ auto narHash =
145+ hashPath ({accessor, CanonPath::root}, FileSerialisationMethod::NixArchive, HashAlgorithm::SHA256);
146+ auto info = std::make_shared<ValidPathInfo>(path, UnkeyedValidPathInfo{narHash.hash });
147+ info->narSize = narHash.numBytesDigested ;
148+ info->ca = ContentAddress{
149+ .method = ContentAddressMethod::Raw::Text,
150+ .hash = hashString (
151+ HashAlgorithm::SHA256,
152+ std::get<MemorySourceAccessor::File::Regular>(accessor->root ->raw ).contents ),
153+ };
154+ callback (std::move (info));
155+ return ;
156+ }
157+ } else {
158+ if (contents.cvisit (path, [&](const auto & kv) {
159+ callback (std::make_shared<ValidPathInfo>(StorePath{kv.first }, kv.second .info ));
160+ }))
161+ return ;
162+ }
143163
144- if (!visited)
145- callback (nullptr );
164+ callback (nullptr );
165+ }
166+
167+ /* *
168+ * Do this to avoid `queryPathInfoUncached` computing `PathInfo`
169+ * that we don't need just to return a `bool`.
170+ */
171+ bool isValidPathUncached (const StorePath & path) override
172+ {
173+ return path.isDerivation () ? derivations.contains (path) : Store::isValidPathUncached (path);
146174 }
147175
148176 /* *
@@ -169,18 +197,25 @@ struct DummyStoreImpl : DummyStore
169197 if (checkSigs)
170198 throw Error (" checking signatures is not supported for '%s' store" , config->getHumanReadableURI ());
171199
172- auto temp = make_ref<MemorySourceAccessor>();
173- MemorySink tempSink{*temp };
200+ auto accessor = make_ref<MemorySourceAccessor>();
201+ MemorySink tempSink{*accessor };
174202 parseDump (tempSink, source);
175203 auto path = info.path ;
176204
177- auto accessor = make_ref<MemorySourceAccessor>(std::move (*temp));
178- contents.insert (
179- {path,
180- PathInfoAndContents{
181- std::move (info),
182- accessor,
183- }});
205+ if (info.path .isDerivation ()) {
206+ warn (" back compat supporting `addToStore` for inserting derivations in dummy store" );
207+ writeDerivation (
208+ parseDerivation (*this , accessor->readFile (CanonPath::root), Derivation::nameFromPath (info.path )));
209+ return ;
210+ }
211+
212+ contents.insert ({
213+ path,
214+ PathInfoAndContents{
215+ std::move (info),
216+ accessor,
217+ },
218+ });
184219 wholeStoreView->addObject (path.to_string (), accessor);
185220 }
186221
@@ -193,6 +228,9 @@ struct DummyStoreImpl : DummyStore
193228 const StorePathSet & references = StorePathSet(),
194229 RepairFlag repair = NoRepair) override
195230 {
231+ if (isDerivation (name))
232+ throw Error (" Do not insert derivation into dummy store with `addToStoreFromDump`" );
233+
196234 if (config->readOnly )
197235 unsupported (" addToStoreFromDump" );
198236
@@ -239,17 +277,47 @@ struct DummyStoreImpl : DummyStore
239277
240278 auto path = info.path ;
241279 auto accessor = make_ref<MemorySourceAccessor>(std::move (*temp));
242- contents.insert (
243- {path,
244- PathInfoAndContents{
245- std::move (info),
246- accessor,
247- }});
280+ contents.insert ({
281+ path,
282+ PathInfoAndContents{
283+ std::move (info),
284+ accessor,
285+ },
286+ });
248287 wholeStoreView->addObject (path.to_string (), accessor);
249288
250289 return path;
251290 }
252291
292+ StorePath writeDerivation (const Derivation & drv, RepairFlag repair = NoRepair) override
293+ {
294+ auto drvPath = ::nix::writeDerivation (*this , drv, repair, /* readonly=*/ true );
295+
296+ if (!derivations.contains (drvPath) || repair) {
297+ if (config->readOnly )
298+ unsupported (" writeDerivation" );
299+ derivations.insert ({drvPath, drv});
300+ }
301+
302+ return drvPath;
303+ }
304+
305+ Derivation readDerivation (const StorePath & drvPath) override
306+ {
307+ if (std::optional res = getConcurrent (derivations, drvPath))
308+ return *res;
309+ else
310+ throw Error (" derivation '%s' is not valid" , printStorePath (drvPath));
311+ }
312+
313+ /* *
314+ * No such thing as an "invalid derivation" with the dummy store
315+ */
316+ Derivation readInvalidDerivation (const StorePath & drvPath) override
317+ {
318+ return readDerivation (drvPath);
319+ }
320+
253321 void registerDrvOutput (const Realisation & output) override
254322 {
255323 auto ref = make_ref<UnkeyedRealisation>(output);
@@ -273,13 +341,28 @@ struct DummyStoreImpl : DummyStore
273341 callback (nullptr );
274342 }
275343
276- std::shared_ptr<SourceAccessor> getFSAccessor (const StorePath & path, bool requireValidPath) override
344+ std::shared_ptr<MemorySourceAccessor> getMemoryFSAccessor (const StorePath & path, bool requireValidPath = true )
277345 {
278- std::shared_ptr<SourceAccessor> res;
279- contents.cvisit (path, [&](const auto & kv) { res = kv.second .contents .get_ptr (); });
346+ std::shared_ptr<MemorySourceAccessor> res;
347+ if (path.isDerivation ())
348+ derivations.cvisit (path, [&](const auto & kv) {
349+ /* compute path info on demand */
350+ auto res2 = make_ref<MemorySourceAccessor>();
351+ res2->root = MemorySourceAccessor::File::Regular{
352+ .contents = kv.second .unparse (*this , false ),
353+ };
354+ res = std::move (res2).get_ptr ();
355+ });
356+ else
357+ contents.cvisit (path, [&](const auto & kv) { res = kv.second .contents .get_ptr (); });
280358 return res;
281359 }
282360
361+ std::shared_ptr<SourceAccessor> getFSAccessor (const StorePath & path, bool requireValidPath = true ) override
362+ {
363+ return getMemoryFSAccessor (path, requireValidPath);
364+ }
365+
283366 ref<SourceAccessor> getFSAccessor (bool requireValidPath) override
284367 {
285368 return wholeStoreView;
0 commit comments