From 9ac91e36a96533bcf2259ab31e995c07d640ca15 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Thu, 12 Feb 2026 19:37:24 -0500 Subject: [PATCH] libstore: make substitution use the per-store `getReadOnly` method This commit introduces a `getReadOnly` method on the store config that returns if the current store is read only or not. This is then used in subtitution, so we fail gracefully with a nice error message if only the individual store is read-only. As a bonus, it gets us one step closer to getting rid of the global because we can use the per-store method instead. Progress on #5638 --- src/libstore/build/substitution-goal.cc | 2 +- src/libstore/dummy-store.cc | 5 +++++ src/libstore/include/nix/store/dummy-store.hh | 2 ++ src/libstore/include/nix/store/local-store.hh | 2 ++ src/libstore/include/nix/store/store-api.hh | 6 ++++++ src/libstore/local-store.cc | 5 +++++ src/libstore/store-api.cc | 5 +++++ 7 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc index 541487bbc..d58bec885 100644 --- a/src/libstore/build/substitution-goal.cc +++ b/src/libstore/build/substitution-goal.cc @@ -37,7 +37,7 @@ Goal::Co PathSubstitutionGoal::init() co_return doneSuccess(BuildResult::Success{.status = BuildResult::Success::AlreadyValid}); } - if (settings.readOnlyMode) + if (worker.store.config.getReadOnly()) throw Error( "cannot substitute path '%s' - no write access to the Nix store", worker.store.printStorePath(storePath)); diff --git a/src/libstore/dummy-store.cc b/src/libstore/dummy-store.cc index ba42c773b..d45133e5a 100644 --- a/src/libstore/dummy-store.cc +++ b/src/libstore/dummy-store.cc @@ -119,6 +119,11 @@ ref DummyStoreConfig::openStore() const return openDummyStore(); } +bool DummyStoreConfig::getReadOnly() const +{ + return readOnly.get() || StoreConfig::getReadOnly(); +} + struct DummyStoreImpl : DummyStore { using Config = DummyStoreConfig; diff --git a/src/libstore/include/nix/store/dummy-store.hh b/src/libstore/include/nix/store/dummy-store.hh index febf351c9..59d1b1fdd 100644 --- a/src/libstore/include/nix/store/dummy-store.hh +++ b/src/libstore/include/nix/store/dummy-store.hh @@ -35,6 +35,8 @@ struct DummyStoreConfig : public std::enable_shared_from_this, No additional memory will be used, because no information needs to be stored. )"}; + bool getReadOnly() const override; + static const std::string name() { return "Dummy Store"; diff --git a/src/libstore/include/nix/store/local-store.hh b/src/libstore/include/nix/store/local-store.hh index f381f5088..7b6b45324 100644 --- a/src/libstore/include/nix/store/local-store.hh +++ b/src/libstore/include/nix/store/local-store.hh @@ -117,6 +117,8 @@ public: > While the filesystem the database resides on might appear to be read-only, consider whether another user or system might have write access to it. )"}; + bool getReadOnly() const override; + Setting ignoreGcDeleteFailure{ this, false, diff --git a/src/libstore/include/nix/store/store-api.hh b/src/libstore/include/nix/store/store-api.hh index 2fb8a4260..9961652e0 100644 --- a/src/libstore/include/nix/store/store-api.hh +++ b/src/libstore/include/nix/store/store-api.hh @@ -218,6 +218,12 @@ struct StoreConfig : public StoreConfigBase, public StoreDirConfig // Don't document the machine-specific default value false}; + /** + * Whether we're allowed to write to this store, also takes into account + * global `readOnly`'s mode setting, not just any per-store settings. + */ + virtual bool getReadOnly() const; + /** * Open a store of the type corresponding to this configuration * type. diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 8560284a3..addb8a9f2 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -473,6 +473,11 @@ StoreReference LocalStoreConfig::getReference() const }; } +bool LocalStoreConfig::getReadOnly() const +{ + return readOnly.get() || StoreConfig::getReadOnly(); +} + int LocalStore::getSchema() { int curSchema = 0; diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index bc7df176b..e46a5ca43 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -333,6 +333,11 @@ StoreReference StoreConfig::getReference() const return {.variant = StoreReference::Auto{}}; } +bool StoreConfig::getReadOnly() const +{ + return settings.readOnlyMode; +} + bool Store::PathInfoCacheValue::isKnownNow() { std::chrono::duration ttl = didExist() ? std::chrono::seconds(settings.ttlPositiveNarInfoCache)