From 1620ad4587f280187124891dff909402b20db014 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 24 Jun 2024 11:34:58 -0400 Subject: [PATCH 1/3] Split out `GlobalConfig` into its own header This makes it easier to understand the reach of global variables / global state in the config system. --- src/libcmd/repl.cc | 1 + src/libexpr/eval-settings.cc | 1 + src/libexpr/flake/config.cc | 1 + src/libfetchers/fetch-settings.cc | 1 + src/libmain/common-args.cc | 1 + src/libstore/build/derivation-goal.cc | 1 + src/libstore/filetransfer.cc | 1 + src/libstore/globals.cc | 1 + src/libstore/unix/build/hook-instance.cc | 1 + src/libutil-c/nix_api_util.cc | 2 +- src/libutil/archive.cc | 2 +- src/libutil/config-global.cc | 66 ++++++++++++++++++++++++ src/libutil/config-global.hh | 33 ++++++++++++ src/libutil/config.cc | 61 ---------------------- src/libutil/config.hh | 25 --------- src/libutil/fs-sink.cc | 2 +- src/libutil/logging.cc | 2 +- src/nix/config.cc | 1 + src/nix/develop.cc | 1 + src/nix/unix/daemon.cc | 1 + tests/functional/plugins/plugintest.cc | 2 +- tests/unit/libutil/nix_api_util.cc | 2 +- 22 files changed, 117 insertions(+), 92 deletions(-) create mode 100644 src/libutil/config-global.cc create mode 100644 src/libutil/config-global.hh diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 1e80d14e1..53dd94c7a 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -8,6 +8,7 @@ #include "ansicolor.hh" #include "shared.hh" +#include "config-global.hh" #include "eval.hh" #include "eval-cache.hh" #include "eval-inline.hh" diff --git a/src/libexpr/eval-settings.cc b/src/libexpr/eval-settings.cc index 85b1677ea..a642bb684 100644 --- a/src/libexpr/eval-settings.cc +++ b/src/libexpr/eval-settings.cc @@ -1,4 +1,5 @@ #include "users.hh" +#include "config-global.hh" #include "globals.hh" #include "profiles.hh" #include "eval.hh" diff --git a/src/libexpr/flake/config.cc b/src/libexpr/flake/config.cc index e0c5d4512..03430b0e3 100644 --- a/src/libexpr/flake/config.cc +++ b/src/libexpr/flake/config.cc @@ -1,4 +1,5 @@ #include "users.hh" +#include "config-global.hh" #include "globals.hh" #include "fetch-settings.hh" #include "flake.hh" diff --git a/src/libfetchers/fetch-settings.cc b/src/libfetchers/fetch-settings.cc index e7d5244dc..21c42567c 100644 --- a/src/libfetchers/fetch-settings.cc +++ b/src/libfetchers/fetch-settings.cc @@ -1,4 +1,5 @@ #include "fetch-settings.hh" +#include "config-global.hh" namespace nix { diff --git a/src/libmain/common-args.cc b/src/libmain/common-args.cc index 5b49aaabc..a94845ab8 100644 --- a/src/libmain/common-args.cc +++ b/src/libmain/common-args.cc @@ -1,5 +1,6 @@ #include "common-args.hh" #include "args/root.hh" +#include "config-global.hh" #include "globals.hh" #include "logging.hh" #include "loggers.hh" diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 146a060f3..64b8495e1 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -3,6 +3,7 @@ # include "hook-instance.hh" #endif #include "processes.hh" +#include "config-global.hh" #include "worker.hh" #include "builtins.hh" #include "builtins/buildenv.hh" diff --git a/src/libstore/filetransfer.cc b/src/libstore/filetransfer.cc index a54ebdcf3..cbbb0fe7a 100644 --- a/src/libstore/filetransfer.cc +++ b/src/libstore/filetransfer.cc @@ -1,5 +1,6 @@ #include "filetransfer.hh" #include "globals.hh" +#include "config-global.hh" #include "store-api.hh" #include "s3.hh" #include "compression.hh" diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 88f899dbf..8fec10d51 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -1,4 +1,5 @@ #include "globals.hh" +#include "config-global.hh" #include "current-process.hh" #include "archive.hh" #include "args.hh" diff --git a/src/libstore/unix/build/hook-instance.cc b/src/libstore/unix/build/hook-instance.cc index 5d045ec3d..dfc208798 100644 --- a/src/libstore/unix/build/hook-instance.cc +++ b/src/libstore/unix/build/hook-instance.cc @@ -1,4 +1,5 @@ #include "globals.hh" +#include "config-global.hh" #include "hook-instance.hh" #include "file-system.hh" #include "child.hh" diff --git a/src/libutil-c/nix_api_util.cc b/src/libutil-c/nix_api_util.cc index 0a9b49345..4f65a4c12 100644 --- a/src/libutil-c/nix_api_util.cc +++ b/src/libutil-c/nix_api_util.cc @@ -1,5 +1,5 @@ #include "nix_api_util.h" -#include "config.hh" +#include "config-global.hh" #include "error.hh" #include "nix_api_util_internal.h" #include "util.hh" diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index d20936de4..22be392d4 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -6,7 +6,7 @@ #include // for strcasecmp #include "archive.hh" -#include "config.hh" +#include "config-global.hh" #include "posix-source-accessor.hh" #include "source-path.hh" #include "file-system.hh" diff --git a/src/libutil/config-global.cc b/src/libutil/config-global.cc new file mode 100644 index 000000000..e8025b303 --- /dev/null +++ b/src/libutil/config-global.cc @@ -0,0 +1,66 @@ +#include "config-global.hh" + +namespace nix { + +bool GlobalConfig::set(const std::string & name, const std::string & value) +{ + for (auto & config : *configRegistrations) + if (config->set(name, value)) return true; + + unknownSettings.emplace(name, value); + + return false; +} + +void GlobalConfig::getSettings(std::map & res, bool overriddenOnly) +{ + for (auto & config : *configRegistrations) + config->getSettings(res, overriddenOnly); +} + +void GlobalConfig::resetOverridden() +{ + for (auto & config : *configRegistrations) + config->resetOverridden(); +} + +nlohmann::json GlobalConfig::toJSON() +{ + auto res = nlohmann::json::object(); + for (const auto & config : *configRegistrations) + res.update(config->toJSON()); + return res; +} + +std::string GlobalConfig::toKeyValue() +{ + std::string res; + std::map settings; + globalConfig.getSettings(settings); + for (const auto & s : settings) + res += fmt("%s = %s\n", s.first, s.second.value); + return res; +} + +void GlobalConfig::convertToArgs(Args & args, const std::string & category) +{ + for (auto & config : *configRegistrations) + config->convertToArgs(args, category); +} + +GlobalConfig globalConfig; + +GlobalConfig::ConfigRegistrations * GlobalConfig::configRegistrations; + +GlobalConfig::Register::Register(Config * config) +{ + if (!configRegistrations) + configRegistrations = new ConfigRegistrations; + configRegistrations->emplace_back(config); +} + +ExperimentalFeatureSettings experimentalFeatureSettings; + +static GlobalConfig::Register rSettings(&experimentalFeatureSettings); + +} diff --git a/src/libutil/config-global.hh b/src/libutil/config-global.hh new file mode 100644 index 000000000..1b7b69a0d --- /dev/null +++ b/src/libutil/config-global.hh @@ -0,0 +1,33 @@ +#pragma once +///@file + +#include "config.hh" + +namespace nix { + +struct GlobalConfig : public AbstractConfig +{ + typedef std::vector ConfigRegistrations; + static ConfigRegistrations * configRegistrations; + + bool set(const std::string & name, const std::string & value) override; + + void getSettings(std::map & res, bool overriddenOnly = false) override; + + void resetOverridden() override; + + nlohmann::json toJSON() override; + + std::string toKeyValue() override; + + void convertToArgs(Args & args, const std::string & category) override; + + struct Register + { + Register(Config * config); + }; +}; + +extern GlobalConfig globalConfig; + +} diff --git a/src/libutil/config.cc b/src/libutil/config.cc index efde8591b..192a4ecb9 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -443,67 +443,6 @@ void OptionalPathSetting::operator =(const std::optional & v) this->assign(v); } -bool GlobalConfig::set(const std::string & name, const std::string & value) -{ - for (auto & config : *configRegistrations) - if (config->set(name, value)) return true; - - unknownSettings.emplace(name, value); - - return false; -} - -void GlobalConfig::getSettings(std::map & res, bool overriddenOnly) -{ - for (auto & config : *configRegistrations) - config->getSettings(res, overriddenOnly); -} - -void GlobalConfig::resetOverridden() -{ - for (auto & config : *configRegistrations) - config->resetOverridden(); -} - -nlohmann::json GlobalConfig::toJSON() -{ - auto res = nlohmann::json::object(); - for (const auto & config : *configRegistrations) - res.update(config->toJSON()); - return res; -} - -std::string GlobalConfig::toKeyValue() -{ - std::string res; - std::map settings; - globalConfig.getSettings(settings); - for (const auto & s : settings) - res += fmt("%s = %s\n", s.first, s.second.value); - return res; -} - -void GlobalConfig::convertToArgs(Args & args, const std::string & category) -{ - for (auto & config : *configRegistrations) - config->convertToArgs(args, category); -} - -GlobalConfig globalConfig; - -GlobalConfig::ConfigRegistrations * GlobalConfig::configRegistrations; - -GlobalConfig::Register::Register(Config * config) -{ - if (!configRegistrations) - configRegistrations = new ConfigRegistrations; - configRegistrations->emplace_back(config); -} - -ExperimentalFeatureSettings experimentalFeatureSettings; - -static GlobalConfig::Register rSettings(&experimentalFeatureSettings); - bool ExperimentalFeatureSettings::isEnabled(const ExperimentalFeature & feature) const { auto & f = experimentalFeatures.get(); diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 07322b60d..1952ba1b8 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -375,31 +375,6 @@ public: void operator =(const std::optional & v); }; -struct GlobalConfig : public AbstractConfig -{ - typedef std::vector ConfigRegistrations; - static ConfigRegistrations * configRegistrations; - - bool set(const std::string & name, const std::string & value) override; - - void getSettings(std::map & res, bool overriddenOnly = false) override; - - void resetOverridden() override; - - nlohmann::json toJSON() override; - - std::string toKeyValue() override; - - void convertToArgs(Args & args, const std::string & category) override; - - struct Register - { - Register(Config * config); - }; -}; - -extern GlobalConfig globalConfig; - struct ExperimentalFeatureSettings : Config { diff --git a/src/libutil/fs-sink.cc b/src/libutil/fs-sink.cc index 91070ea89..a6a743737 100644 --- a/src/libutil/fs-sink.cc +++ b/src/libutil/fs-sink.cc @@ -1,7 +1,7 @@ #include #include "error.hh" -#include "config.hh" +#include "config-global.hh" #include "fs-sink.hh" #if _WIN32 diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 5fa01f0d9..55751b4cf 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -3,7 +3,7 @@ #include "environment-variables.hh" #include "terminal.hh" #include "util.hh" -#include "config.hh" +#include "config-global.hh" #include "source-path.hh" #include "position.hh" diff --git a/src/nix/config.cc b/src/nix/config.cc index 52706afcf..07f975a00 100644 --- a/src/nix/config.cc +++ b/src/nix/config.cc @@ -2,6 +2,7 @@ #include "common-args.hh" #include "shared.hh" #include "store-api.hh" +#include "config-global.hh" #include diff --git a/src/nix/develop.cc b/src/nix/develop.cc index 27287a1a8..a7acbff0b 100644 --- a/src/nix/develop.cc +++ b/src/nix/develop.cc @@ -1,3 +1,4 @@ +#include "config-global.hh" #include "eval.hh" #include "installable-flake.hh" #include "command-installable-value.hh" diff --git a/src/nix/unix/daemon.cc b/src/nix/unix/daemon.cc index f1fc51682..41ea1f5a4 100644 --- a/src/nix/unix/daemon.cc +++ b/src/nix/unix/daemon.cc @@ -10,6 +10,7 @@ #include "serialise.hh" #include "archive.hh" #include "globals.hh" +#include "config-global.hh" #include "derivations.hh" #include "finally.hh" #include "legacy.hh" diff --git a/tests/functional/plugins/plugintest.cc b/tests/functional/plugins/plugintest.cc index e02fd68d5..7433ad190 100644 --- a/tests/functional/plugins/plugintest.cc +++ b/tests/functional/plugins/plugintest.cc @@ -1,4 +1,4 @@ -#include "config.hh" +#include "config-global.hh" #include "primops.hh" using namespace nix; diff --git a/tests/unit/libutil/nix_api_util.cc b/tests/unit/libutil/nix_api_util.cc index d2999f55b..2b7e38225 100644 --- a/tests/unit/libutil/nix_api_util.cc +++ b/tests/unit/libutil/nix_api_util.cc @@ -1,4 +1,4 @@ -#include "config.hh" +#include "config-global.hh" #include "args.hh" #include "nix_api_util.h" #include "nix_api_util_internal.h" From b46e13840b948a363e2aa082f6064dfaeab58c06 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 24 Jun 2024 12:07:08 -0400 Subject: [PATCH 2/3] Format `config-global.{cc,hh}` Since the code is factored out, it is no longer avoding the formatter. --- src/libutil/config-global.cc | 3 ++- src/libutil/config-global.hh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libutil/config-global.cc b/src/libutil/config-global.cc index e8025b303..4c08898a4 100644 --- a/src/libutil/config-global.cc +++ b/src/libutil/config-global.cc @@ -5,7 +5,8 @@ namespace nix { bool GlobalConfig::set(const std::string & name, const std::string & value) { for (auto & config : *configRegistrations) - if (config->set(name, value)) return true; + if (config->set(name, value)) + return true; unknownSettings.emplace(name, value); diff --git a/src/libutil/config-global.hh b/src/libutil/config-global.hh index 1b7b69a0d..2caf51524 100644 --- a/src/libutil/config-global.hh +++ b/src/libutil/config-global.hh @@ -7,7 +7,7 @@ namespace nix { struct GlobalConfig : public AbstractConfig { - typedef std::vector ConfigRegistrations; + typedef std::vector ConfigRegistrations; static ConfigRegistrations * configRegistrations; bool set(const std::string & name, const std::string & value) override; From cb0c868da4ced09179182792b8be1d7259238f98 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 24 Jun 2024 11:55:36 -0400 Subject: [PATCH 3/3] Allow loading config files into other config objects This gives us some hope of moving away from global variables. --- src/libstore/globals.cc | 10 +++++----- src/libstore/globals.hh | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 8fec10d51..7e1d7ea6d 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -124,12 +124,12 @@ Settings::Settings() }; } -void loadConfFile() +void loadConfFile(AbstractConfig & config) { auto applyConfigFile = [&](const Path & path) { try { std::string contents = readFile(path); - globalConfig.applyConfig(contents, path); + config.applyConfig(contents, path); } catch (SystemError &) { } }; @@ -137,7 +137,7 @@ void loadConfFile() /* We only want to send overrides to the daemon, i.e. stuff from ~/.nix/nix.conf or the command line. */ - globalConfig.resetOverridden(); + config.resetOverridden(); auto files = settings.nixUserConfFiles; for (auto file = files.rbegin(); file != files.rend(); file++) { @@ -146,7 +146,7 @@ void loadConfFile() auto nixConfEnv = getEnv("NIX_CONFIG"); if (nixConfEnv.has_value()) { - globalConfig.applyConfig(nixConfEnv.value(), "NIX_CONFIG"); + config.applyConfig(nixConfEnv.value(), "NIX_CONFIG"); } } @@ -438,7 +438,7 @@ void initLibStore(bool loadConfig) { initLibUtil(); if (loadConfig) - loadConfFile(); + loadConfFile(globalConfig); preloadNSS(); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 843e77bcf..439e9f4fc 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -1284,7 +1284,13 @@ extern Settings settings; */ void initPlugins(); -void loadConfFile(); +/** + * Load the configuration (from `nix.conf`, `NIX_CONFIG`, etc.) into the + * given configuration object. + * + * Usually called with `globalConfig`. + */ +void loadConfFile(AbstractConfig & config); // Used by the Settings constructor std::vector getUserConfigFiles();