Read per-user settings from ~/.config/nix/nix.conf
This commit is contained in:
		
							parent
							
								
									562585e901
								
							
						
					
					
						commit
						f05d5f89ff
					
				
					 8 changed files with 70 additions and 24 deletions
				
			
		|  | @ -17,13 +17,32 @@ | |||
| 
 | ||||
| <refsection><title>Description</title> | ||||
| 
 | ||||
| <para>A number of persistent settings of Nix are stored in the file | ||||
| <filename><replaceable>sysconfdir</replaceable>/nix/nix.conf</filename> or | ||||
| <filename>$NIX_CONF_DIR/nix.conf</filename> if <envar>NIX_CONF_DIR</envar> is set. | ||||
| This file is a list of <literal><replaceable>name</replaceable> = | ||||
| <para>Nix reads settings from two configuration files:</para> | ||||
| 
 | ||||
| <itemizedlist> | ||||
| 
 | ||||
|   <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. | ||||
| Comments start with a <literal>#</literal> character.  Here is an example | ||||
| configuration file:</para> | ||||
| Comments start with a <literal>#</literal> character.  Here is an | ||||
| example configuration file:</para> | ||||
| 
 | ||||
| <programlisting> | ||||
| gc-keep-outputs = true       # Nice for developers | ||||
|  | @ -31,8 +50,9 @@ gc-keep-derivations = true   # Idem | |||
| env-keep-derivations = false | ||||
| </programlisting> | ||||
| 
 | ||||
| <para>You can override settings using the <option>--option</option> | ||||
| flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para> | ||||
| <para>You can override settings on the command line using the | ||||
| <option>--option</option> flag, e.g. <literal>--option gc-keep-outputs | ||||
| false</literal>.</para> | ||||
| 
 | ||||
| <para>The following settings are currently available: | ||||
| 
 | ||||
|  |  | |||
|  | @ -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()); | ||||
|  |  | |||
|  | @ -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. */ | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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 { }; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue