Read per-user settings from ~/.config/nix/nix.conf

This commit is contained in:
Eelco Dolstra 2017-04-20 14:58:16 +02:00
parent 562585e901
commit f05d5f89ff
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
8 changed files with 70 additions and 24 deletions

View file

@ -17,13 +17,32 @@
<refsection><title>Description</title> <refsection><title>Description</title>
<para>A number of persistent settings of Nix are stored in the file <para>Nix reads settings from two configuration files:</para>
<filename><replaceable>sysconfdir</replaceable>/nix/nix.conf</filename> or
<filename>$NIX_CONF_DIR/nix.conf</filename> if <envar>NIX_CONF_DIR</envar> is set. <itemizedlist>
This file is a list of <literal><replaceable>name</replaceable> =
<listitem>
<para>The system-wide configuration file
<filename><replaceable>sysconfdir</replaceable>/nix/nix.conf</filename>
(i.e. <filename>/etc/nix/nix.conf</filename> on most systems), or
<filename>$NIX_CONF_DIR/nix.conf</filename> if
<envar>NIX_CONF_DIR</envar> is set.</para>
</listitem>
<listitem>
<para>The user configuration file
<filename>$XDG_CONFIG_HOME/nix/nix.conf</filename>, or
<filename>~/.config/nix/nix.conf</filename> if
<envar>XDG_CONFIG_HOME</envar> is not set.</para>
</listitem>
</itemizedlist>
<para>The configuration files consist of
<literal><replaceable>name</replaceable> =
<replaceable>value</replaceable></literal> pairs, one per line. <replaceable>value</replaceable></literal> pairs, one per line.
Comments start with a <literal>#</literal> character. Here is an example Comments start with a <literal>#</literal> character. Here is an
configuration file:</para> example configuration file:</para>
<programlisting> <programlisting>
gc-keep-outputs = true # Nice for developers gc-keep-outputs = true # Nice for developers
@ -31,8 +50,9 @@ gc-keep-derivations = true # Idem
env-keep-derivations = false env-keep-derivations = false
</programlisting> </programlisting>
<para>You can override settings using the <option>--option</option> <para>You can override settings on the command line using the
flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> <option>--option</option> flag, e.g. <literal>--option gc-keep-outputs
false</literal>.</para>
<para>The following settings are currently available: <para>The following settings are currently available:

View file

@ -53,19 +53,19 @@ Settings::Settings()
void Settings::loadConfFile() void Settings::loadConfFile()
{ {
applyConfigFile(nixConfDir + "/nix.conf"); 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) void Settings::set(const string & name, const string & value)
{ {
overrides[name] = value;
Config::set(name, value); Config::set(name, value);
} }
StringMap Settings::getOverrides()
{
return overrides;
}
unsigned int Settings::getDefaultCores() unsigned int Settings::getDefaultCores()
{ {
return std::max(1U, std::thread::hardware_concurrency()); return std::max(1U, std::thread::hardware_concurrency());

View file

@ -15,8 +15,6 @@ extern bool useCaseHack; // FIXME
class Settings : public Config { class Settings : public Config {
StringMap overrides;
unsigned int getDefaultCores(); unsigned int getDefaultCores();
public: public:
@ -27,8 +25,6 @@ public:
void set(const string & name, const string & value); void set(const string & name, const string & value);
StringMap getOverrides();
Path nixPrefix; Path nixPrefix;
/* The directory where we store sources and derived files. */ /* The directory where we store sources and derived files. */

View file

@ -166,7 +166,7 @@ void RemoteStore::setOptions(Connection & conn)
<< settings.useSubstitutes; << settings.useSubstitutes;
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 12) { if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 12) {
StringMap overrides = settings.getOverrides(); auto overrides = settings.getSettings(true);
conn.to << overrides.size(); conn.to << overrides.size();
for (auto & i : overrides) for (auto & i : overrides)
conn.to << i.first << i.second; conn.to << i.first << i.second;

View file

@ -9,6 +9,7 @@ void Config::set(const std::string & name, const std::string & value)
if (i == _settings.end()) if (i == _settings.end())
throw UsageError("unknown setting '%s'", name); throw UsageError("unknown setting '%s'", name);
i->second.setting->set(value); i->second.setting->set(value);
i->second.setting->overriden = true;
} }
void Config::addSetting(AbstractSetting * setting) void Config::addSetting(AbstractSetting * setting)
@ -22,6 +23,7 @@ void Config::addSetting(AbstractSetting * setting)
auto i = initials.find(setting->name); auto i = initials.find(setting->name);
if (i != initials.end()) { if (i != initials.end()) {
setting->set(i->second); setting->set(i->second);
setting->overriden = true;
initials.erase(i); initials.erase(i);
set = true; set = true;
} }
@ -34,6 +36,7 @@ void Config::addSetting(AbstractSetting * setting)
alias, setting->name); alias, setting->name);
else { else {
setting->set(i->second); setting->set(i->second);
setting->overriden = true;
initials.erase(i); initials.erase(i);
set = true; set = true;
} }
@ -47,11 +50,11 @@ void Config::warnUnknownSettings()
warn("unknown setting '%s'", i.first); warn("unknown setting '%s'", i.first);
} }
StringMap Config::getSettings() StringMap Config::getSettings(bool overridenOnly)
{ {
StringMap res; StringMap res;
for (auto & opt : _settings) 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()); res.emplace(opt.first, opt.second.setting->to_string());
return res; return res;
} }
@ -94,6 +97,12 @@ void Config::applyConfigFile(const Path & path, bool fatal)
} catch (SysError &) { } } catch (SysError &) { }
} }
void Config::resetOverriden()
{
for (auto & s : _settings)
s.second.setting->overriden = false;
}
AbstractSetting::AbstractSetting( AbstractSetting::AbstractSetting(
const std::string & name, const std::string & name,
const std::string & description, const std::string & description,

View file

@ -51,9 +51,11 @@ public:
void warnUnknownSettings(); void warnUnknownSettings();
StringMap getSettings(); StringMap getSettings(bool overridenOnly = false);
void applyConfigFile(const Path & path, bool fatal = false); void applyConfigFile(const Path & path, bool fatal = false);
void resetOverriden();
}; };
class AbstractSetting class AbstractSetting
@ -68,6 +70,8 @@ public:
int created = 123; int created = 123;
bool overriden = false;
protected: protected:
AbstractSetting( AbstractSetting(
@ -78,7 +82,7 @@ protected:
virtual ~AbstractSetting() virtual ~AbstractSetting()
{ {
// Check against a gcc miscompilation causing our constructor // 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); assert(created == 123);
} }
@ -88,6 +92,8 @@ protected:
bool parseBool(const std::string & str); bool parseBool(const std::string & str);
std::string printBool(bool b); std::string printBool(bool b);
bool isOverriden() { return overriden; }
}; };
struct DefaultSettingTag { }; struct DefaultSettingTag { };

View file

@ -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 createDirs(const Path & path)
{ {
Paths created; Paths created;

View file

@ -110,9 +110,12 @@ void deletePath(const Path & path, unsigned long long & bytesFreed);
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); 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(); Path getCacheDir();
/* Return $XDG_CONFIG_HOME or $HOME/.config. */
Path getConfigDir();
/* Create a directory and all its parents, if necessary. Returns the /* Create a directory and all its parents, if necessary. Returns the
list of created directories, in order of creation. */ list of created directories, in order of creation. */
Paths createDirs(const Path & path); Paths createDirs(const Path & path);