From 3a64d3c0da2b169383256fd3198cf7d18f8ab163 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Sun, 28 Sep 2025 17:42:19 +0300 Subject: [PATCH 1/2] libstore: Call canonPath for constructing LocalFSStoreConfig::rootDir This mirrors what OptionalPathSetting does. Otherwise we run into an assertion failure for relative paths specified as the authority + path: nix build nixpkgs#hello --store "local://a/b" nix: ../posix-source-accessor.cc:13: nix::PosixSourceAccessor::PosixSourceAccessor(std::filesystem::__cxx11::path&&): Assertion `root.empty() || root.is_absolute()' failed. This is now diagnosed properly: error: not an absolute path: 'a/b' Just as you'd specify the root via a query parameter: nix build nixpkgs#hello --store "local?root=a/b" --- src/libstore/local-fs-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc index 66ae85d89..b16fc86e9 100644 --- a/src/libstore/local-fs-store.cc +++ b/src/libstore/local-fs-store.cc @@ -24,7 +24,7 @@ LocalFSStoreConfig::LocalFSStoreConfig(PathView rootDir, const Params & params) // FIXME don't duplicate description once we don't have root setting , rootDir{ this, - !rootDir.empty() && params.count("root") == 0 ? (std::optional{rootDir}) : std::nullopt, + !rootDir.empty() && params.count("root") == 0 ? (std::optional{canonPath(rootDir)}) : std::nullopt, "root", "Directory prefixed to all other paths."} { From 0866ba0b4ad14ddc1aa7ad7d3211ab4a981b9c5d Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Sun, 28 Sep 2025 18:38:57 +0300 Subject: [PATCH 2/2] libstore: Deduplicate LocalFSStoreConfig::rootDir initializers Co-authored-by: John Ericson --- .../include/nix/store/local-fs-store.hh | 14 +++++++++++++- src/libstore/local-fs-store.cc | 18 +++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/libstore/include/nix/store/local-fs-store.hh b/src/libstore/include/nix/store/local-fs-store.hh index f7d6d65b1..08f8e1656 100644 --- a/src/libstore/include/nix/store/local-fs-store.hh +++ b/src/libstore/include/nix/store/local-fs-store.hh @@ -9,6 +9,18 @@ namespace nix { struct LocalFSStoreConfig : virtual StoreConfig { +private: + static OptionalPathSetting makeRootDirSetting(LocalFSStoreConfig & self, std::optional defaultValue) + { + return { + &self, + std::move(defaultValue), + "root", + "Directory prefixed to all other paths.", + }; + } + +public: using StoreConfig::StoreConfig; /** @@ -20,7 +32,7 @@ struct LocalFSStoreConfig : virtual StoreConfig */ LocalFSStoreConfig(PathView path, const Params & params); - OptionalPathSetting rootDir{this, std::nullopt, "root", "Directory prefixed to all other paths."}; + OptionalPathSetting rootDir = makeRootDirSetting(*this, std::nullopt); private: diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc index b16fc86e9..28069dcaf 100644 --- a/src/libstore/local-fs-store.cc +++ b/src/libstore/local-fs-store.cc @@ -20,13 +20,17 @@ Path LocalFSStoreConfig::getDefaultLogDir() LocalFSStoreConfig::LocalFSStoreConfig(PathView rootDir, const Params & params) : StoreConfig(params) - // Default `?root` from `rootDir` if non set - // FIXME don't duplicate description once we don't have root setting - , rootDir{ - this, - !rootDir.empty() && params.count("root") == 0 ? (std::optional{canonPath(rootDir)}) : std::nullopt, - "root", - "Directory prefixed to all other paths."} + /* Default `?root` from `rootDir` if non set + * NOTE: We would like to just do rootDir.set(...), which would take care of + * all normalization and error checking for us. Unfortunately we cannot do + * that because of the complicated initialization order of other fields with + * the virtual class hierarchy of nix store configs, and the design of the + * settings system. As such, we have no choice but to redefine the field and + * manually repeat the same normalization logic. + */ + , rootDir{makeRootDirSetting( + *this, + !rootDir.empty() && params.count("root") == 0 ? std::optional{canonPath(rootDir)} : std::nullopt)} { }