From f05d5f89ff4ec52ed2f6d576b2b2323b5292f815 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 20 Apr 2017 14:58:16 +0200 Subject: [PATCH] Read per-user settings from ~/.config/nix/nix.conf --- doc/manual/command-ref/conf-file.xml | 36 +++++++++++++++++++++------- src/libstore/globals.cc | 12 +++++----- src/libstore/globals.hh | 4 ---- src/libstore/remote-store.cc | 2 +- src/libutil/config.cc | 13 ++++++++-- src/libutil/config.hh | 10 ++++++-- src/libutil/util.cc | 12 ++++++++++ src/libutil/util.hh | 5 +++- 8 files changed, 70 insertions(+), 24 deletions(-) diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml index 79e18de9b..616983bc7 100644 --- a/doc/manual/command-ref/conf-file.xml +++ b/doc/manual/command-ref/conf-file.xml @@ -17,13 +17,32 @@ Description -A number of persistent settings of Nix are stored in the file -sysconfdir/nix/nix.conf or -$NIX_CONF_DIR/nix.conf if NIX_CONF_DIR is set. -This file is a list of name = +Nix reads settings from two configuration files: + + + + + The system-wide configuration file + sysconfdir/nix/nix.conf + (i.e. /etc/nix/nix.conf on most systems), or + $NIX_CONF_DIR/nix.conf if + NIX_CONF_DIR is set. + + + + The user configuration file + $XDG_CONFIG_HOME/nix/nix.conf, or + ~/.config/nix/nix.conf if + XDG_CONFIG_HOME is not set. + + + + +The configuration files consist of +name = value pairs, one per line. -Comments start with a # character. Here is an example -configuration file: +Comments start with a # character. Here is an +example configuration file: gc-keep-outputs = true # Nice for developers @@ -31,8 +50,9 @@ gc-keep-derivations = true # Idem env-keep-derivations = false -You can override settings using the -flag, e.g. --option gc-keep-outputs false. +You can override settings on the command line using the + flag, e.g. --option gc-keep-outputs +false. The following settings are currently available: diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index bb61daa51..6b9d07746 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -53,19 +53,19 @@ Settings::Settings() void Settings::loadConfFile() { applyConfigFile(nixConfDir + "/nix.conf"); + + /* We only want to send overrides to the daemon, i.e. stuff from + ~/.nix/nix.conf or the command line. */ + resetOverriden(); + + applyConfigFile(getConfigDir() + "/nix/nix.conf"); } void Settings::set(const string & name, const string & value) { - overrides[name] = value; Config::set(name, value); } -StringMap Settings::getOverrides() -{ - return overrides; -} - unsigned int Settings::getDefaultCores() { return std::max(1U, std::thread::hardware_concurrency()); diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index de64e9826..d3ecaadb6 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -15,8 +15,6 @@ extern bool useCaseHack; // FIXME class Settings : public Config { - StringMap overrides; - unsigned int getDefaultCores(); public: @@ -27,8 +25,6 @@ public: void set(const string & name, const string & value); - StringMap getOverrides(); - Path nixPrefix; /* The directory where we store sources and derived files. */ diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index da3c8eb8d..bc9ef3d47 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -166,7 +166,7 @@ void RemoteStore::setOptions(Connection & conn) << settings.useSubstitutes; if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 12) { - StringMap overrides = settings.getOverrides(); + auto overrides = settings.getSettings(true); conn.to << overrides.size(); for (auto & i : overrides) conn.to << i.first << i.second; diff --git a/src/libutil/config.cc b/src/libutil/config.cc index e7a810cec..bf1372997 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -9,6 +9,7 @@ void Config::set(const std::string & name, const std::string & value) if (i == _settings.end()) throw UsageError("unknown setting '%s'", name); i->second.setting->set(value); + i->second.setting->overriden = true; } void Config::addSetting(AbstractSetting * setting) @@ -22,6 +23,7 @@ void Config::addSetting(AbstractSetting * setting) auto i = initials.find(setting->name); if (i != initials.end()) { setting->set(i->second); + setting->overriden = true; initials.erase(i); set = true; } @@ -34,6 +36,7 @@ void Config::addSetting(AbstractSetting * setting) alias, setting->name); else { setting->set(i->second); + setting->overriden = true; initials.erase(i); set = true; } @@ -47,11 +50,11 @@ void Config::warnUnknownSettings() warn("unknown setting '%s'", i.first); } -StringMap Config::getSettings() +StringMap Config::getSettings(bool overridenOnly) { StringMap res; for (auto & opt : _settings) - if (!opt.second.isAlias) + if (!opt.second.isAlias && (!overridenOnly || opt.second.setting->overriden)) res.emplace(opt.first, opt.second.setting->to_string()); return res; } @@ -94,6 +97,12 @@ void Config::applyConfigFile(const Path & path, bool fatal) } catch (SysError &) { } } +void Config::resetOverriden() +{ + for (auto & s : _settings) + s.second.setting->overriden = false; +} + AbstractSetting::AbstractSetting( const std::string & name, const std::string & description, diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 6c8612f67..952bf04b8 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -51,9 +51,11 @@ public: void warnUnknownSettings(); - StringMap getSettings(); + StringMap getSettings(bool overridenOnly = false); void applyConfigFile(const Path & path, bool fatal = false); + + void resetOverriden(); }; class AbstractSetting @@ -68,6 +70,8 @@ public: int created = 123; + bool overriden = false; + protected: AbstractSetting( @@ -78,7 +82,7 @@ protected: virtual ~AbstractSetting() { // Check against a gcc miscompilation causing our constructor - // not to run. + // not to run (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80431). assert(created == 123); } @@ -88,6 +92,8 @@ protected: bool parseBool(const std::string & str); std::string printBool(bool b); + + bool isOverriden() { return overriden; } }; struct DefaultSettingTag { }; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 0bd51afd1..37dfccd06 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -429,6 +429,18 @@ Path getCacheDir() } +Path getConfigDir() +{ + Path configDir = getEnv("XDG_CONFIG_HOME"); + if (configDir.empty()) { + Path homeDir = getEnv("HOME"); + if (homeDir.empty()) throw Error("$XDG_CONFIG_HOME and $HOME are not set"); + configDir = homeDir + "/.config"; + } + return configDir; +} + + Paths createDirs(const Path & path) { Paths created; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 0e6941e4a..121423cda 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -110,9 +110,12 @@ void deletePath(const Path & path, unsigned long long & bytesFreed); Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); -/* Return the path to $XDG_CACHE_HOME/.cache. */ +/* Return $XDG_CACHE_HOME or $HOME/.cache. */ Path getCacheDir(); +/* Return $XDG_CONFIG_HOME or $HOME/.config. */ +Path getConfigDir(); + /* Create a directory and all its parents, if necessary. Returns the list of created directories, in order of creation. */ Paths createDirs(const Path & path);