From a7c841f704201c0fcffe3ed82314f1a10408dc95 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 24 Jan 2024 11:05:26 -0500 Subject: [PATCH] Make store setting and store flags use `StoreReference` --- src/libcmd/command.cc | 14 ++-- src/libcmd/command.hh | 2 +- src/libcmd/common-eval-args.cc | 4 +- src/libcmd/common-eval-args.hh | 3 +- src/libexpr/flake/flake.cc | 2 + src/libexpr/primops/fetchClosure.cc | 15 +++-- src/libexpr/primops/fetchTree.cc | 2 + src/libfetchers/unix/git.cc | 1 + src/libstore-c/nix_api_store.cc | 13 ++-- src/libstore/daemon.cc | 16 ++--- src/libstore/derivations.cc | 6 +- src/libstore/globals.cc | 64 +++++++++++++++++++ src/libstore/globals.hh | 16 +++-- src/libstore/legacy-ssh-store.cc | 4 +- src/libstore/nar-info.cc | 1 + src/libstore/ssh-store-config.hh | 2 +- src/libstore/ssh-store.cc | 4 +- src/libstore/store-api.cc | 4 +- src/libstore/store-api.hh | 11 ++-- src/libstore/store-reference.cc | 20 ++++++ src/libstore/store-reference.hh | 12 ++++ src/libstore/unix/local-overlay-store.cc | 2 +- src/libstore/unix/local-overlay-store.hh | 8 +-- src/libutil/experimental-features.hh | 2 +- src/libutil/json-avoids-null.hh | 57 +++++++++++++++++ src/libutil/json-impls.hh | 2 +- src/libutil/json-utils.hh | 35 +--------- src/nix-copy-closure/nix-copy-closure.cc | 10 ++- src/nix/flake.cc | 10 +-- src/nix/main.cc | 5 +- src/nix/make-content-addressed.cc | 2 +- src/nix/sigs.cc | 6 +- src/nix/unix/daemon.cc | 6 +- src/nix/verify.cc | 6 +- tests/unit/libstore-support/tests/libstore.hh | 7 +- 35 files changed, 269 insertions(+), 105 deletions(-) create mode 100644 src/libutil/json-avoids-null.hh diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 543250da3..5b6820841 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -75,28 +75,32 @@ CopyCommand::CopyCommand() .longName = "from", .description = "URL of the source Nix store.", .labels = {"store-uri"}, - .handler = {&srcUri}, + .handler = {[&](std::string storeUri) { + srcUri = StoreReference::parse(storeUri); + }}, }); addFlag({ .longName = "to", .description = "URL of the destination Nix store.", .labels = {"store-uri"}, - .handler = {&dstUri}, + .handler = {[&](std::string storeUri) { + dstUri = StoreReference::parse(storeUri); + }}, }); } ref CopyCommand::createStore() { - return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri); + return !srcUri ? StoreCommand::createStore() : openStore(*srcUri); } ref CopyCommand::getDstStore() { - if (srcUri.empty() && dstUri.empty()) + if (!srcUri && !dstUri) throw UsageError("you must pass '--from' and/or '--to'"); - return dstUri.empty() ? openStore() : openStore(dstUri); + return !dstUri ? openStore() : openStore(*dstUri); } EvalCommand::EvalCommand() diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 4a72627ed..4628832b6 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -62,7 +62,7 @@ private: */ struct CopyCommand : virtual StoreCommand { - std::string srcUri, dstUri; + std::optional srcUri, dstUri; CopyCommand(); diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc index 155b43b70..084c5eb00 100644 --- a/src/libcmd/common-eval-args.cc +++ b/src/libcmd/common-eval-args.cc @@ -164,7 +164,9 @@ MixEvalArgs::MixEvalArgs() )", .category = category, .labels = {"store-url"}, - .handler = {&evalStoreUrl}, + .handler = {[&](std::string s) { + evalStoreUrl = StoreReference::parse(s); + }}, }); } diff --git a/src/libcmd/common-eval-args.hh b/src/libcmd/common-eval-args.hh index 75cb19334..fd06e1415 100644 --- a/src/libcmd/common-eval-args.hh +++ b/src/libcmd/common-eval-args.hh @@ -5,6 +5,7 @@ #include "canon-path.hh" #include "common-args.hh" #include "search-path.hh" +#include "store-reference.hh" #include @@ -25,7 +26,7 @@ struct MixEvalArgs : virtual Args, virtual MixRepair LookupPath lookupPath; - std::optional evalStoreUrl; + std::optional evalStoreUrl; private: struct AutoArgExpr { std::string expr; }; diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc index 3af9ef14e..e9cb6a61b 100644 --- a/src/libexpr/flake/flake.cc +++ b/src/libexpr/flake/flake.cc @@ -1,3 +1,5 @@ +#include + #include "terminal.hh" #include "flake.hh" #include "eval.hh" diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc index fc5bb3145..114422a8f 100644 --- a/src/libexpr/primops/fetchClosure.cc +++ b/src/libexpr/primops/fetchClosure.cc @@ -182,23 +182,26 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg .pos = state.positions[pos] }); - auto parsedURL = parseURL(*fromStoreUrl); + auto parsedURL = StoreReference::parse(*fromStoreUrl); - if (parsedURL.scheme != "http" && - parsedURL.scheme != "https" && - !(getEnv("_NIX_IN_TEST").has_value() && parsedURL.scheme == "file")) + auto * storeVariant = std::get_if(&parsedURL.variant); + + if (!storeVariant || + (storeVariant->scheme != "http" && + storeVariant->scheme != "https" && + !(getEnv("_NIX_IN_TEST").has_value() && storeVariant->scheme == "file"))) throw Error({ .msg = HintFmt("'fetchClosure' only supports http:// and https:// stores"), .pos = state.positions[pos] }); - if (!parsedURL.query.empty()) + if (!parsedURL.params.empty()) throw Error({ .msg = HintFmt("'fetchClosure' does not support URL query parameters (in '%s')", *fromStoreUrl), .pos = state.positions[pos] }); - auto fromStore = openStore(parsedURL.to_string()); + auto fromStore = openStore(parsedURL); if (toPath) runFetchClosureWithRewrite(state, pos, *fromStore, *fromPath, *toPath, v); diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index fa462dc33..557aa78d2 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -15,6 +15,8 @@ #include #include +#include + namespace nix { void emitTreeAttrs( diff --git a/src/libfetchers/unix/git.cc b/src/libfetchers/unix/git.cc index fa7ef3621..7544c4c09 100644 --- a/src/libfetchers/unix/git.cc +++ b/src/libfetchers/unix/git.cc @@ -13,6 +13,7 @@ #include "git-utils.hh" #include "logging.hh" #include "finally.hh" +#include "json-utils.hh" #include "fetch-settings.hh" diff --git a/src/libstore-c/nix_api_store.cc b/src/libstore-c/nix_api_store.cc index 4fe25c7d4..2f8616c41 100644 --- a/src/libstore-c/nix_api_store.cc +++ b/src/libstore-c/nix_api_store.cc @@ -49,14 +49,15 @@ Store * nix_store_open(nix_c_context * context, const char * uri, const char *** if (uri_str.empty()) return new Store{nix::openStore()}; - if (!params) - return new Store{nix::openStore(uri_str)}; + auto base_uri = nix::StoreReference::parse(uri_str); - nix::Store::Params params_map; - for (size_t i = 0; params[i] != nullptr; i++) { - params_map[params[i][0]] = params[i][1]; + if (params) { + for (size_t i = 0; params[i] != nullptr; i++) { + base_uri.params[params[i][0]] = params[i][1]; + } } - return new Store{nix::openStore(uri_str, params_map)}; + + return new Store{nix::openStore(std::move(base_uri))}; } NIXC_CATCH_ERRS_NULL } diff --git a/src/libstore/daemon.cc b/src/libstore/daemon.cc index 47d6d5541..029669461 100644 --- a/src/libstore/daemon.cc +++ b/src/libstore/daemon.cc @@ -215,22 +215,22 @@ struct ClientSettings auto & name(i.first); auto & value(i.second); - auto setSubstituters = [&](Setting & res) { + auto setSubstituters = [&](Setting> & res) { if (name != res.name && res.aliases.count(name) == 0) return false; - StringSet trusted = settings.trustedSubstituters; + std::set trusted = settings.trustedSubstituters; for (auto & s : settings.substituters.get()) trusted.insert(s); - Strings subs; + std::vector subs; auto ss = tokenizeString(value); - for (auto & s : ss) - if (trusted.count(s)) - subs.push_back(s); - else if (!hasSuffix(s, "/") && trusted.count(s + "/")) - subs.push_back(s + "/"); + for (auto & s : ss) { + auto ref = StoreReference::parse(s); + if (trusted.count(ref)) + subs.push_back(ref); else warn("ignoring untrusted substituter '%s', you are not a trusted user.\n" "Run `man nix.conf` for more information on the `substituters` configuration option.", s); + } res = subs; return true; }; diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index e13705911..99c2e08db 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -1,3 +1,6 @@ +#include +#include + #include "derivations.hh" #include "downstream-placeholder.hh" #include "store-api.hh" @@ -7,8 +10,7 @@ #include "split.hh" #include "common-protocol.hh" #include "common-protocol-impl.hh" -#include -#include +#include "json-utils.hh" namespace nix { diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index d9cab2fb8..d81229e27 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -35,6 +35,10 @@ namespace nix { +DECLARE_CONFIG_SERIALISER(StoreReference) +DECLARE_CONFIG_SERIALISER(std::optional) +DECLARE_CONFIG_SERIALISER(std::set) +DECLARE_CONFIG_SERIALISER(std::vector) /* The default location of the daemon socket, relative to nixStateDir. The socket is in a directory to allow you to control access to the @@ -319,6 +323,66 @@ template<> void BaseSetting::convertToArg(Args & args, const std::s }); } +template<> StoreReference BaseSetting::parse(const std::string & str) const +{ + return StoreReference::parse(str); +} + +template<> std::string BaseSetting::to_string() const +{ + return value.render(); +} + +template<> std::optional BaseSetting>::parse(const std::string & str) const +{ + if (str == "") + return std::nullopt; + else + return StoreReference::parse(str); +} + +template<> std::string BaseSetting>::to_string() const +{ + return value ? value->render() : ""; +} + +template<> std::set BaseSetting>::parse(const std::string & str) const +{ + std::set res; + for (const auto & s : tokenizeString>(str)) + res.insert(StoreReference::parse(s)); + return res; +} + +template<> std::string BaseSetting>::to_string() const +{ + std::set strings; + for (const auto & ref : value) + strings.insert(ref.render()); + return concatStringsSep(" ", strings); +} + +template<> std::vector BaseSetting>::parse(const std::string & str) const +{ + std::vector res; + for (const auto & s : tokenizeString>(str)) + res.push_back(StoreReference::parse(s)); + return res; +} + +template<> std::string BaseSetting>::to_string() const +{ + std::vector strings; + for (const auto & ref : value) + strings.push_back(ref.render()); + return concatStringsSep(" ", strings); +} + +template class BaseSetting; +template class BaseSetting>; +template class BaseSetting>; +template class BaseSetting>; + unsigned int MaxBuildJobsSetting::parse(const std::string & str) const { if (str == "auto") return std::max(1U, std::thread::hardware_concurrency()); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index dc18a11fc..cf0e2fbea 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -5,6 +5,7 @@ #include "config.hh" #include "environment-variables.hh" #include "experimental-features.hh" +#include "store-reference.hh" #include "users.hh" #include @@ -116,7 +117,7 @@ public: */ Path nixDaemonSocketFile; - Setting storeUri{this, getEnv("NIX_REMOTE").value_or("auto"), "store", + Setting storeUri{this, StoreReference::parse(getEnv("NIX_REMOTE").value_or("auto")), "store", R"( The [URL of the Nix store](@docroot@/store/types/index.md#store-url-format) to use for most operations. @@ -904,9 +905,16 @@ public: // Don't document the machine-specific default value false}; - Setting substituters{ + Setting> substituters{ this, - Strings{"https://cache.nixos.org/"}, + { + { + .variant = StoreReference::Specified { + .scheme = "https", + .authority = "cache.nixos.org", + }, + }, + }, "substituters", R"( A list of [URLs of Nix stores](@docroot@/store/types/index.md#store-url-format) to be used as substituters, separated by whitespace. @@ -925,7 +933,7 @@ public: )", {"binary-caches"}}; - Setting trustedSubstituters{ + Setting> trustedSubstituters{ this, {}, "trusted-substituters", R"( A list of [Nix store URLs](@docroot@/store/types/index.md#store-url-format), separated by whitespace. diff --git a/src/libstore/legacy-ssh-store.cc b/src/libstore/legacy-ssh-store.cc index c75d50ade..ae11ca702 100644 --- a/src/libstore/legacy-ssh-store.cc +++ b/src/libstore/legacy-ssh-store.cc @@ -68,9 +68,9 @@ ref LegacySSHStore::openConnection() Strings command = remoteProgram.get(); command.push_back("--serve"); command.push_back("--write"); - if (remoteStore.get() != "") { + if (std::optional rs = remoteStore.get()) { command.push_back("--store"); - command.push_back(remoteStore.get()); + command.push_back(rs->render()); } conn->sshConn = master.startCommand(std::move(command)); conn->to = FdSink(conn->sshConn->in.get()); diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc index 0d219a489..53c8a5510 100644 --- a/src/libstore/nar-info.cc +++ b/src/libstore/nar-info.cc @@ -1,6 +1,7 @@ #include "globals.hh" #include "nar-info.hh" #include "store-api.hh" +#include "json-utils.hh" namespace nix { diff --git a/src/libstore/ssh-store-config.hh b/src/libstore/ssh-store-config.hh index 09f9f23a7..841d4dbd8 100644 --- a/src/libstore/ssh-store-config.hh +++ b/src/libstore/ssh-store-config.hh @@ -18,7 +18,7 @@ struct CommonSSHStoreConfig : virtual StoreConfig const Setting compress{this, false, "compress", "Whether to enable SSH compression."}; - const Setting remoteStore{this, "", "remote-store", + const Setting> remoteStore{this, std::nullopt, "remote-store", R"( [Store URL](@docroot@/store/types/index.md#store-url-format) to be used on the remote machine. The default is `auto` diff --git a/src/libstore/ssh-store.cc b/src/libstore/ssh-store.cc index 246abaac2..41f731124 100644 --- a/src/libstore/ssh-store.cc +++ b/src/libstore/ssh-store.cc @@ -228,9 +228,9 @@ ref SSHStore::openConnection() auto conn = make_ref(); Strings command = remoteProgram.get(); command.push_back("--stdio"); - if (remoteStore.get() != "") { + if (std::optional rs = remoteStore.get()) { command.push_back("--store"); - command.push_back(remoteStore.get()); + command.push_back(rs->render()); } command.insert(command.end(), extraRemoteProgramArgs.begin(), extraRemoteProgramArgs.end()); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 7c2b3815f..8f9ec205f 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -1330,9 +1330,9 @@ std::list> getDefaultSubstituters() static auto stores([]() { std::list> stores; - StringSet done; + std::set done; - auto addStore = [&](const std::string & uri) { + auto addStore = [&](const StoreReference & uri) { if (!done.insert(uri).second) return; try { stores.push_back(openStore(uri)); diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 430d9a5ab..5bc097abf 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -863,13 +863,10 @@ OutputPathMap resolveDerivedPath(Store &, const DerivedPath::Built &, Store * ev */ ref openStore(StoreReference && storeURI); - -/** - * Opens the store at `uri`, where `uri` is in the format expected by `StoreReference::parse` - - */ -ref openStore(const std::string & uri = settings.storeUri.get(), - const Store::Params & extraParams = Store::Params()); +static inline ref openStore(const StoreReference & storeURI = settings.storeUri.get()) +{ + return openStore(StoreReference { storeURI }); +} /** diff --git a/src/libstore/store-reference.cc b/src/libstore/store-reference.cc index b4968dfad..64a7f6287 100644 --- a/src/libstore/store-reference.cc +++ b/src/libstore/store-reference.cc @@ -1,4 +1,5 @@ #include +#include #include "error.hh" #include "url.hh" @@ -114,3 +115,22 @@ std::pair splitUriAndParams(const std::stri } } + +namespace nlohmann { + +using namespace nix; + +// TODO support something structured + +StoreReference adl_serializer::from_json(const json & json) +{ + auto s = json.get(); + return StoreReference::parse(s); +} + +void adl_serializer::to_json(json & json, StoreReference ref) +{ + json = ref.render(); +} + +} diff --git a/src/libstore/store-reference.hh b/src/libstore/store-reference.hh index e99335c0d..88f35b719 100644 --- a/src/libstore/store-reference.hh +++ b/src/libstore/store-reference.hh @@ -4,6 +4,8 @@ #include #include "types.hh" +#include "json-impls.hh" +#include "json-avoids-null.hh" namespace nix { @@ -89,4 +91,14 @@ struct StoreReference */ std::pair splitUriAndParams(const std::string & uri); +/** + * It is always rendered as a string + */ +template<> +struct json_avoids_null : std::true_type +{ +}; + } + +JSON_IMPL(StoreReference) diff --git a/src/libstore/unix/local-overlay-store.cc b/src/libstore/unix/local-overlay-store.cc index 598415db8..aedec9a53 100644 --- a/src/libstore/unix/local-overlay-store.cc +++ b/src/libstore/unix/local-overlay-store.cc @@ -26,7 +26,7 @@ LocalOverlayStore::LocalOverlayStore(const Params & params) , Store(params) , LocalFSStore(params) , LocalStore(params) - , lowerStore(openStore(percentDecode(lowerStoreUri.get())).dynamic_pointer_cast()) + , lowerStore(openStore(lowerStoreUri.get()).dynamic_pointer_cast()) { if (checkMount.get()) { std::smatch match; diff --git a/src/libstore/unix/local-overlay-store.hh b/src/libstore/unix/local-overlay-store.hh index 35a301013..ec6564b19 100644 --- a/src/libstore/unix/local-overlay-store.hh +++ b/src/libstore/unix/local-overlay-store.hh @@ -13,7 +13,7 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig , LocalStoreConfig(params) { } - const Setting lowerStoreUri{(StoreConfig*) this, "", "lower-store", + const Setting lowerStoreUri{this, StoreReference{.variant = StoreReference::Auto{}}, "lower-store", R"( [Store URL](@docroot@/command-ref/new-cli/nix3-help-stores.md#store-url-format) for the lower store. The default is `auto` (i.e. use the Nix daemon or `/nix/store` directly). @@ -22,12 +22,12 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig Must be used as OverlayFS lower layer for this store's store dir. )"}; - const PathSetting upperLayer{(StoreConfig*) this, "", "upper-layer", + const PathSetting upperLayer{this, "", "upper-layer", R"( Directory containing the OverlayFS upper layer for this store's store dir. )"}; - Setting checkMount{(StoreConfig*) this, true, "check-mount", + Setting checkMount{this, true, "check-mount", R"( Check that the overlay filesystem is correctly mounted. @@ -38,7 +38,7 @@ struct LocalOverlayStoreConfig : virtual LocalStoreConfig default, but can be disabled if needed. )"}; - const PathSetting remountHook{(StoreConfig*) this, "", "remount-hook", + const PathSetting remountHook{this, "", "remount-hook", R"( Script or other executable to run when overlay filesystem needs remounting. diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index 1da2a3ff5..83e43c4cf 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -3,7 +3,7 @@ #include "comparator.hh" #include "error.hh" -#include "json-utils.hh" +#include "json-avoids-null.hh" #include "types.hh" namespace nix { diff --git a/src/libutil/json-avoids-null.hh b/src/libutil/json-avoids-null.hh new file mode 100644 index 000000000..47f35d8b3 --- /dev/null +++ b/src/libutil/json-avoids-null.hh @@ -0,0 +1,57 @@ +#pragma once +///@file + +#include +#include + +#include "types.hh" + +namespace nix { + +/** + * For `adl_serializer>` below, we need to track what + * types are not already using `null`. Only for them can we use `null` + * to represent `std::nullopt`. + */ +template +struct json_avoids_null; + +/** + * Handle numbers in default impl + */ +template +struct json_avoids_null : std::bool_constant::value> +{ +}; + +template<> +struct json_avoids_null : std::false_type +{ +}; + +template<> +struct json_avoids_null : std::true_type +{ +}; + +template<> +struct json_avoids_null : std::true_type +{ +}; + +template +struct json_avoids_null> : std::true_type +{ +}; + +template +struct json_avoids_null> : std::true_type +{ +}; + +template +struct json_avoids_null> : std::true_type +{ +}; + +} diff --git a/src/libutil/json-impls.hh b/src/libutil/json-impls.hh index b26163a04..9dd344c50 100644 --- a/src/libutil/json-impls.hh +++ b/src/libutil/json-impls.hh @@ -1,7 +1,7 @@ #pragma once ///@file -#include "nlohmann/json_fwd.hpp" +#include // Following https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types #define JSON_IMPL(TYPE) \ diff --git a/src/libutil/json-utils.hh b/src/libutil/json-utils.hh index 08c98cc8c..ea8b828f5 100644 --- a/src/libutil/json-utils.hh +++ b/src/libutil/json-utils.hh @@ -2,10 +2,9 @@ ///@file #include -#include -#include #include "types.hh" +#include "json-avoids-null.hh" namespace nix { @@ -39,38 +38,6 @@ Strings getStringList(const nlohmann::json & value); StringMap getStringMap(const nlohmann::json & value); StringSet getStringSet(const nlohmann::json & value); -/** - * For `adl_serializer>` below, we need to track what - * types are not already using `null`. Only for them can we use `null` - * to represent `std::nullopt`. - */ -template -struct json_avoids_null; - -/** - * Handle numbers in default impl - */ -template -struct json_avoids_null : std::bool_constant::value> {}; - -template<> -struct json_avoids_null : std::false_type {}; - -template<> -struct json_avoids_null : std::true_type {}; - -template<> -struct json_avoids_null : std::true_type {}; - -template -struct json_avoids_null> : std::true_type {}; - -template -struct json_avoids_null> : std::true_type {}; - -template -struct json_avoids_null> : std::true_type {}; - } namespace nlohmann { diff --git a/src/nix-copy-closure/nix-copy-closure.cc b/src/nix-copy-closure/nix-copy-closure.cc index b64af758f..89ee63f81 100644 --- a/src/nix-copy-closure/nix-copy-closure.cc +++ b/src/nix-copy-closure/nix-copy-closure.cc @@ -47,7 +47,15 @@ static int main_nix_copy_closure(int argc, char ** argv) if (sshHost.empty()) throw UsageError("no host name specified"); - auto remoteUri = "ssh://" + sshHost + (gzip ? "?compress=true" : ""); + StoreReference remoteUri{ + .variant = + StoreReference::Specified{ + .scheme = "ssh", + .authority = sshHost, + }, + .params = gzip ? (StoreReference::Params{{"compress", "true"}}) : (StoreReference::Params{}), + }; + auto to = toMode ? openStore(remoteUri) : openStore(); auto from = toMode ? openStore() : openStore(remoteUri); diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 78a8a55c3..bdac1b4d9 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -1006,7 +1006,7 @@ struct CmdFlakeClone : FlakeCommand struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun { - std::string dstUri; + std::optional dstUri; CmdFlakeArchive() { @@ -1014,7 +1014,9 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun .longName = "to", .description = "URI of the destination Nix store", .labels = {"store-uri"}, - .handler = {&dstUri} + .handler = {[&](std::string s) { + dstUri = StoreReference::parse(s); + }}, }); } @@ -1075,8 +1077,8 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun traverse(*flake.lockFile.root); } - if (!dryRun && !dstUri.empty()) { - ref dstStore = dstUri.empty() ? openStore() : openStore(dstUri); + if (!dryRun && dstUri) { + ref dstStore = openStore(*dstUri); copyPaths(*store, *dstStore, sources); } } diff --git a/src/nix/main.cc b/src/nix/main.cc index bc13a4df5..667a3db17 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -18,6 +18,7 @@ #include "terminal.hh" #include "users.hh" #include "network-proxy.hh" +#include "json-utils.hh" #include #include @@ -224,7 +225,7 @@ static void showHelp(std::vector subcommand, NixArgs & toplevel) evalSettings.restrictEval = false; evalSettings.pureEval = false; - EvalState state({}, openStore("dummy://")); + EvalState state({}, openStore({ .variant = StoreReference::Specified { .scheme = "dummy" } })); auto vGenerateManpage = state.allocValue(); state.eval(state.parseExprFromString( @@ -400,7 +401,7 @@ void mainWrapped(int argc, char * * argv) Xp::FetchTree, }; evalSettings.pureEval = false; - EvalState state({}, openStore("dummy://")); + EvalState state({}, openStore({ .variant = StoreReference::Specified { .scheme = "dummy" } })); auto res = nlohmann::json::object(); res["builtins"] = ({ auto builtinsJson = nlohmann::json::object(); diff --git a/src/nix/make-content-addressed.cc b/src/nix/make-content-addressed.cc index d9c988a9f..dcd7860b9 100644 --- a/src/nix/make-content-addressed.cc +++ b/src/nix/make-content-addressed.cc @@ -30,7 +30,7 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand, void run(ref srcStore, StorePaths && storePaths) override { - auto dstStore = dstUri.empty() ? openStore() : openStore(dstUri); + auto dstStore = !dstUri ? openStore() : openStore(*dstUri); auto remappings = makeContentAddressed(*srcStore, *dstStore, StorePathSet(storePaths.begin(), storePaths.end())); diff --git a/src/nix/sigs.cc b/src/nix/sigs.cc index 1e277cbbe..000a73c80 100644 --- a/src/nix/sigs.cc +++ b/src/nix/sigs.cc @@ -11,7 +11,7 @@ using namespace nix; struct CmdCopySigs : StorePathsCommand { - Strings substituterUris; + std::vector substituterUris; CmdCopySigs() { @@ -20,7 +20,9 @@ struct CmdCopySigs : StorePathsCommand .shortName = 's', .description = "Copy signatures from the specified store.", .labels = {"store-uri"}, - .handler = {[&](std::string s) { substituterUris.push_back(s); }}, + .handler = {[&](std::string s) { + substituterUris.push_back(StoreReference::parse(s)); + }}, }); } diff --git a/src/nix/unix/daemon.cc b/src/nix/unix/daemon.cc index de77a7b6b..5a230f33c 100644 --- a/src/nix/unix/daemon.cc +++ b/src/nix/unix/daemon.cc @@ -234,10 +234,10 @@ static PeerInfo getPeerInfo(int remote) */ static ref openUncachedStore() { - Store::Params params; // FIXME: get params from somewhere + StoreReference ref = settings.storeUri.get(); // Disable caching since the client already does that. - params["path-info-cache-size"] = "0"; - return openStore(settings.storeUri, params); + ref.params["path-info-cache-size"] = "0"; + return openStore(std::move(ref)); } /** diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 2a0cbd19f..13c2761df 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -15,7 +15,7 @@ struct CmdVerify : StorePathsCommand { bool noContents = false; bool noTrust = false; - Strings substituterUris; + std::vector substituterUris; size_t sigsNeeded = 0; CmdVerify() @@ -37,7 +37,9 @@ struct CmdVerify : StorePathsCommand .shortName = 's', .description = "Use signatures from the specified store.", .labels = {"store-uri"}, - .handler = {[&](std::string s) { substituterUris.push_back(s); }} + .handler = {[&](std::string s) { + substituterUris.push_back(StoreReference::parse(s)); + }} }); addFlag({ diff --git a/tests/unit/libstore-support/tests/libstore.hh b/tests/unit/libstore-support/tests/libstore.hh index 267188224..c57bc40d8 100644 --- a/tests/unit/libstore-support/tests/libstore.hh +++ b/tests/unit/libstore-support/tests/libstore.hh @@ -16,7 +16,12 @@ class LibStoreTest : public virtual ::testing::Test { protected: LibStoreTest() - : store(openStore("dummy://")) + : store(openStore({ + .variant = StoreReference::Specified { + .scheme = "dummy", + .authority = "", + }, + })) { } ref store;