From e07440665c80e941b1049b7e94a025853eba4dd2 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 6 Aug 2025 19:54:56 -0400 Subject: [PATCH] Move some `MixStoreDirMethods` members to the right `.cc` file I had not wanted to cause unncessary churn before, but now that we've bitten the bullet with the Big Reformat, I feel it is the right time. Future readers will appreciate that the declarations and definitions files are one-to-one as they should be, and `store-api.cc` is good to shrink in any event. I don't think there are outstanding PRs changing this code either. (I had some for a while, but they are all merged.) --- src/libstore/path.cc | 54 ---------- src/libstore/store-api.cc | 113 -------------------- src/libstore/store-dir-config.cc | 171 ++++++++++++++++++++++++++++++- 3 files changed, 170 insertions(+), 168 deletions(-) diff --git a/src/libstore/path.cc b/src/libstore/path.cc index 3f7745288..516b01571 100644 --- a/src/libstore/path.cc +++ b/src/libstore/path.cc @@ -74,58 +74,4 @@ StorePath StorePath::random(std::string_view name) return StorePath(Hash::random(HashAlgorithm::SHA1), name); } -StorePath MixStoreDirMethods::parseStorePath(std::string_view path) const -{ - // On Windows, `/nix/store` is not a canonical path. More broadly it - // is unclear whether this function should be using the native - // notion of a canonical path at all. For example, it makes to - // support remote stores whose store dir is a non-native path (e.g. - // Windows <-> Unix ssh-ing). - auto p = -#ifdef _WIN32 - path -#else - canonPath(std::string(path)) -#endif - ; - if (dirOf(p) != storeDir) - throw BadStorePath("path '%s' is not in the Nix store", p); - return StorePath(baseNameOf(p)); -} - -std::optional MixStoreDirMethods::maybeParseStorePath(std::string_view path) const -{ - try { - return parseStorePath(path); - } catch (Error &) { - return {}; - } -} - -bool MixStoreDirMethods::isStorePath(std::string_view path) const -{ - return (bool) maybeParseStorePath(path); -} - -StorePathSet MixStoreDirMethods::parseStorePathSet(const PathSet & paths) const -{ - StorePathSet res; - for (auto & i : paths) - res.insert(parseStorePath(i)); - return res; -} - -std::string MixStoreDirMethods::printStorePath(const StorePath & path) const -{ - return (storeDir + "/").append(path.to_string()); -} - -PathSet MixStoreDirMethods::printStorePathSet(const StorePathSet & paths) const -{ - PathSet res; - for (auto & i : paths) - res.insert(printStorePath(i)); - return res; -} - } // namespace nix diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 1465d9b42..468aeecf1 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -64,119 +64,6 @@ StorePath Store::followLinksToStorePath(std::string_view path) const return toStorePath(followLinksToStore(path)).first; } -/* -The exact specification of store paths is in `protocols/store-path.md` -in the Nix manual. These few functions implement that specification. - -If changes to these functions go beyond mere implementation changes i.e. -also update the user-visible behavior, please update the specification -to match. -*/ - -StorePath MixStoreDirMethods::makeStorePath(std::string_view type, std::string_view hash, std::string_view name) const -{ - /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ - auto s = std::string(type) + ":" + std::string(hash) + ":" + storeDir + ":" + std::string(name); - auto h = compressHash(hashString(HashAlgorithm::SHA256, s), 20); - return StorePath(h, name); -} - -StorePath MixStoreDirMethods::makeStorePath(std::string_view type, const Hash & hash, std::string_view name) const -{ - return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name); -} - -StorePath MixStoreDirMethods::makeOutputPath(std::string_view id, const Hash & hash, std::string_view name) const -{ - return makeStorePath("output:" + std::string{id}, hash, outputPathName(name, id)); -} - -/* Stuff the references (if any) into the type. This is a bit - hacky, but we can't put them in, say, (per the grammar above) - since that would be ambiguous. */ -static std::string makeType(const MixStoreDirMethods & store, std::string && type, const StoreReferences & references) -{ - for (auto & i : references.others) { - type += ":"; - type += store.printStorePath(i); - } - if (references.self) - type += ":self"; - return std::move(type); -} - -StorePath MixStoreDirMethods::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const -{ - if (info.method == FileIngestionMethod::Git - && !(info.hash.algo == HashAlgorithm::SHA1 || info.hash.algo == HashAlgorithm::SHA256)) { - throw Error( - "Git file ingestion must use SHA-1 or SHA-256 hash, but instead using: %s", printHashAlgo(info.hash.algo)); - } - - if (info.hash.algo == HashAlgorithm::SHA256 && info.method == FileIngestionMethod::NixArchive) { - return makeStorePath(makeType(*this, "source", info.references), info.hash, name); - } else { - if (!info.references.empty()) { - throw Error( - "fixed output derivation '%s' is not allowed to refer to other store paths.\nYou may need to use the 'unsafeDiscardReferences' derivation attribute, see the manual for more details.", - name); - } - // make a unique digest based on the parameters for creating this store object - auto payload = - "fixed:out:" + makeFileIngestionPrefix(info.method) + info.hash.to_string(HashFormat::Base16, true) + ":"; - auto digest = hashString(HashAlgorithm::SHA256, payload); - return makeStorePath("output:out", digest, name); - } -} - -StorePath -MixStoreDirMethods::makeFixedOutputPathFromCA(std::string_view name, const ContentAddressWithReferences & ca) const -{ - // New template - return std::visit( - overloaded{ - [&](const TextInfo & ti) { - assert(ti.hash.algo == HashAlgorithm::SHA256); - return makeStorePath( - makeType( - *this, - "text", - StoreReferences{ - .others = ti.references, - .self = false, - }), - ti.hash, - name); - }, - [&](const FixedOutputInfo & foi) { return makeFixedOutputPath(name, foi); }}, - ca.raw); -} - -std::pair MixStoreDirMethods::computeStorePath( - std::string_view name, - const SourcePath & path, - ContentAddressMethod method, - HashAlgorithm hashAlgo, - const StorePathSet & references, - PathFilter & filter) const -{ - auto [h, size] = hashPath(path, method.getFileIngestionMethod(), hashAlgo, filter); - if (settings.warnLargePathThreshold && size && *size >= settings.warnLargePathThreshold) - warn("hashed large path '%s' (%s)", path, renderSize(*size)); - return { - makeFixedOutputPathFromCA( - name, - ContentAddressWithReferences::fromParts( - method, - h, - { - .others = references, - .self = false, - })), - h, - }; -} - StorePath Store::addToStore( std::string_view name, const SourcePath & path, diff --git a/src/libstore/store-dir-config.cc b/src/libstore/store-dir-config.cc index 069c484ba..62f08d819 100644 --- a/src/libstore/store-dir-config.cc +++ b/src/libstore/store-dir-config.cc @@ -1,9 +1,178 @@ -#include "nix/store/store-dir-config.hh" +#include "nix/util/source-path.hh" #include "nix/util/util.hh" +#include "nix/store/store-dir-config.hh" +#include "nix/store/derivations.hh" #include "nix/store/globals.hh" namespace nix { +StorePath MixStoreDirMethods::parseStorePath(std::string_view path) const +{ + // On Windows, `/nix/store` is not a canonical path. More broadly it + // is unclear whether this function should be using the native + // notion of a canonical path at all. For example, it makes to + // support remote stores whose store dir is a non-native path (e.g. + // Windows <-> Unix ssh-ing). + auto p = +#ifdef _WIN32 + path +#else + canonPath(std::string(path)) +#endif + ; + if (dirOf(p) != storeDir) + throw BadStorePath("path '%s' is not in the Nix store", p); + return StorePath(baseNameOf(p)); +} + +std::optional MixStoreDirMethods::maybeParseStorePath(std::string_view path) const +{ + try { + return parseStorePath(path); + } catch (Error &) { + return {}; + } +} + +bool MixStoreDirMethods::isStorePath(std::string_view path) const +{ + return (bool) maybeParseStorePath(path); +} + +StorePathSet MixStoreDirMethods::parseStorePathSet(const PathSet & paths) const +{ + StorePathSet res; + for (auto & i : paths) + res.insert(parseStorePath(i)); + return res; +} + +std::string MixStoreDirMethods::printStorePath(const StorePath & path) const +{ + return (storeDir + "/").append(path.to_string()); +} + +PathSet MixStoreDirMethods::printStorePathSet(const StorePathSet & paths) const +{ + PathSet res; + for (auto & i : paths) + res.insert(printStorePath(i)); + return res; +} + +/* +The exact specification of store paths is in `protocols/store-path.md` +in the Nix manual. These few functions implement that specification. + +If changes to these functions go beyond mere implementation changes i.e. +also update the user-visible behavior, please update the specification +to match. +*/ + +StorePath MixStoreDirMethods::makeStorePath(std::string_view type, std::string_view hash, std::string_view name) const +{ + /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */ + auto s = std::string(type) + ":" + std::string(hash) + ":" + storeDir + ":" + std::string(name); + auto h = compressHash(hashString(HashAlgorithm::SHA256, s), 20); + return StorePath(h, name); +} + +StorePath MixStoreDirMethods::makeStorePath(std::string_view type, const Hash & hash, std::string_view name) const +{ + return makeStorePath(type, hash.to_string(HashFormat::Base16, true), name); +} + +StorePath MixStoreDirMethods::makeOutputPath(std::string_view id, const Hash & hash, std::string_view name) const +{ + return makeStorePath("output:" + std::string{id}, hash, outputPathName(name, id)); +} + +/* Stuff the references (if any) into the type. This is a bit + hacky, but we can't put them in, say, (per the grammar above) + since that would be ambiguous. */ +static std::string makeType(const MixStoreDirMethods & store, std::string && type, const StoreReferences & references) +{ + for (auto & i : references.others) { + type += ":"; + type += store.printStorePath(i); + } + if (references.self) + type += ":self"; + return std::move(type); +} + +StorePath MixStoreDirMethods::makeFixedOutputPath(std::string_view name, const FixedOutputInfo & info) const +{ + if (info.method == FileIngestionMethod::Git + && !(info.hash.algo == HashAlgorithm::SHA1 || info.hash.algo == HashAlgorithm::SHA256)) { + throw Error( + "Git file ingestion must use SHA-1 or SHA-256 hash, but instead using: %s", printHashAlgo(info.hash.algo)); + } + + if (info.hash.algo == HashAlgorithm::SHA256 && info.method == FileIngestionMethod::NixArchive) { + return makeStorePath(makeType(*this, "source", info.references), info.hash, name); + } else { + if (!info.references.empty()) { + throw Error( + "fixed output derivation '%s' is not allowed to refer to other store paths.\nYou may need to use the 'unsafeDiscardReferences' derivation attribute, see the manual for more details.", + name); + } + // make a unique digest based on the parameters for creating this store object + auto payload = + "fixed:out:" + makeFileIngestionPrefix(info.method) + info.hash.to_string(HashFormat::Base16, true) + ":"; + auto digest = hashString(HashAlgorithm::SHA256, payload); + return makeStorePath("output:out", digest, name); + } +} + +StorePath +MixStoreDirMethods::makeFixedOutputPathFromCA(std::string_view name, const ContentAddressWithReferences & ca) const +{ + // New template + return std::visit( + overloaded{ + [&](const TextInfo & ti) { + assert(ti.hash.algo == HashAlgorithm::SHA256); + return makeStorePath( + makeType( + *this, + "text", + StoreReferences{ + .others = ti.references, + .self = false, + }), + ti.hash, + name); + }, + [&](const FixedOutputInfo & foi) { return makeFixedOutputPath(name, foi); }}, + ca.raw); +} + +std::pair MixStoreDirMethods::computeStorePath( + std::string_view name, + const SourcePath & path, + ContentAddressMethod method, + HashAlgorithm hashAlgo, + const StorePathSet & references, + PathFilter & filter) const +{ + auto [h, size] = hashPath(path, method.getFileIngestionMethod(), hashAlgo, filter); + if (settings.warnLargePathThreshold && size && *size >= settings.warnLargePathThreshold) + warn("hashed large path '%s' (%s)", path, renderSize(*size)); + return { + makeFixedOutputPathFromCA( + name, + ContentAddressWithReferences::fromParts( + method, + h, + { + .others = references, + .self = false, + })), + h, + }; +} + StoreDirConfig::StoreDirConfig(const Params & params) : StoreDirConfigBase(params) , MixStoreDirMethods{storeDir_}