diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libmain/shared.cc | 2 | ||||
-rw-r--r-- | src/libstore/gc.cc | 11 | ||||
-rw-r--r-- | src/libstore/globals.cc | 39 | ||||
-rw-r--r-- | src/libstore/globals.hh | 52 | ||||
-rw-r--r-- | src/libstore/local.mk | 3 | ||||
-rw-r--r-- | src/libstore/remote-store.cc | 2 | ||||
-rw-r--r-- | src/libutil/config.cc | 100 | ||||
-rw-r--r-- | src/libutil/config.hh | 64 | ||||
-rw-r--r-- | src/libutil/json.cc | 43 | ||||
-rw-r--r-- | src/libutil/json.hh | 11 | ||||
-rw-r--r-- | src/libutil/util.cc | 19 | ||||
-rw-r--r-- | src/libutil/util.hh | 7 | ||||
-rw-r--r-- | src/nix-daemon/nix-daemon.cc | 50 | ||||
-rw-r--r-- | src/nix/show-config.cc | 3 |
14 files changed, 264 insertions, 142 deletions
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 4747b9bf9b4c..d6c1c0c9cb49 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -259,7 +259,7 @@ int handleExceptions(const string & programName, std::function<void()> fun) condition is discharged before we reach printMsg() below, since otherwise it will throw an (uncaught) exception. */ - interruptThrown = true; + setInterruptThrown(); throw; } } catch (Exit & e) { diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 0b03d61a789a..b6d462d2bffb 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -426,22 +426,27 @@ void LocalStore::findRuntimeRoots(PathSet & roots) throw SysError("iterating /proc"); } +#if !defined(__linux__) try { - auto lsofRegex = std::regex(R"(^n(/.*)$)"); + printError("RUN LSOF %s", LSOF); + std::regex lsofRegex(R"(^n(/.*)$)"); auto lsofLines = - tokenizeString<std::vector<string>>(runProgram("lsof", true, { "-n", "-w", "-F", "n" }), "\n"); + tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n"); for (const auto & line : lsofLines) { - auto match = std::smatch{}; + std::smatch match; if (std::regex_match(line, match, lsofRegex)) paths.emplace(match[1]); } } catch (ExecError & e) { /* lsof not installed, lsof failed */ } +#endif +#if defined(__linux__) readFileRoots("/proc/sys/kernel/modprobe", paths); readFileRoots("/proc/sys/kernel/fbsplash", paths); readFileRoots("/proc/sys/kernel/poweroff_cmd", paths); +#endif for (auto & i : paths) if (isInStore(i)) { diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index bb61daa51642..953bf6aaaa0a 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()); @@ -73,7 +73,7 @@ unsigned int Settings::getDefaultCores() const string nixVersion = PACKAGE_VERSION; -template<> void Setting<SandboxMode>::set(const std::string & str) +template<> void BaseSetting<SandboxMode>::set(const std::string & str) { if (str == "true") value = smEnabled; else if (str == "relaxed") value = smRelaxed; @@ -81,7 +81,7 @@ template<> void Setting<SandboxMode>::set(const std::string & str) else throw UsageError("option '%s' has invalid value '%s'", name, str); } -template<> std::string Setting<SandboxMode>::to_string() +template<> std::string BaseSetting<SandboxMode>::to_string() { if (value == smEnabled) return "true"; else if (value == smRelaxed) return "relaxed"; @@ -89,27 +89,16 @@ template<> std::string Setting<SandboxMode>::to_string() else abort(); } -template<> void Setting<unsigned int, Settings::MaxBuildJobsTag>::set(const std::string & str) +template<> void BaseSetting<SandboxMode>::toJSON(JSONPlaceholder & out) { - if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency()); - else if (!string2Int(str, value)) - throw UsageError("configuration setting ‘%s’ should be ‘auto’ or an integer", name); + AbstractSetting::toJSON(out); } -template<> std::string Setting<unsigned int, Settings::MaxBuildJobsTag>::to_string() +void MaxBuildJobsSetting::set(const std::string & str) { - return std::to_string(value); -} - -template<> void Setting<bool, Settings::CaseHackTag>::set(const std::string & str) -{ - value = parseBool(str); - nix::useCaseHack = true; -} - -template<> std::string Setting<bool, Settings::CaseHackTag>::to_string() -{ - return printBool(value); + if (str == "auto") value = std::max(1U, std::thread::hardware_concurrency()); + else if (!string2Int(str, value)) + throw UsageError("configuration setting ‘%s’ should be ‘auto’ or an integer", name); } } diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index 72863920de99..b4f44de2e65d 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -13,9 +13,40 @@ typedef enum { smEnabled, smRelaxed, smDisabled } SandboxMode; extern bool useCaseHack; // FIXME -class Settings : public Config { +struct CaseHackSetting : public BaseSetting<bool> +{ + CaseHackSetting(Config * options, + const std::string & name, + const std::string & description, + const std::set<std::string> & aliases = {}) + : BaseSetting<bool>(useCaseHack, name, description, aliases) + { + options->addSetting(this); + } + + void set(const std::string & str) override + { + BaseSetting<bool>::set(str); + nix::useCaseHack = true; + } +}; - StringMap overrides; +struct MaxBuildJobsSetting : public BaseSetting<unsigned int> +{ + MaxBuildJobsSetting(Config * options, + unsigned int def, + const std::string & name, + const std::string & description, + const std::set<std::string> & aliases = {}) + : BaseSetting<unsigned int>(def, name, description, aliases) + { + options->addSetting(this); + } + + void set(const std::string & str) override; +}; + +class Settings : public Config { unsigned int getDefaultCores(); @@ -27,8 +58,6 @@ public: void set(const string & name, const string & value); - StringMap getOverrides(); - Path nixPrefix; /* The directory where we store sources and derived files. */ @@ -70,8 +99,7 @@ public: the log to show if a build fails. */ size_t logLines = 10; - struct MaxBuildJobsTag { }; - Setting<unsigned int, MaxBuildJobsTag> maxBuildJobs{this, 1, "build-max-jobs", + MaxBuildJobsSetting maxBuildJobs{this, 1, "build-max-jobs", "Maximum number of parallel build jobs. \"auto\" means use number of cores."}; Setting<unsigned int> buildCores{this, getDefaultCores(), "build-cores", @@ -216,8 +244,9 @@ public: Setting<Strings> secretKeyFiles{this, {}, "secret-key-files", "Secret keys with which to sign local builds."}; - Setting<size_t> binaryCachesParallelConnections{this, 25, "binary-caches-parallel-connections", - "Number of parallel connections to binary caches."}; + Setting<size_t> binaryCachesParallelConnections{this, 25, "http-connections", + "Number of parallel HTTP connections.", + {"binary-caches-parallel-connections"}}; Setting<bool> enableHttp2{this, true, "enable-http2", "Whether to enable HTTP/2 support."}; @@ -239,6 +268,10 @@ public: "Additional URIs of substituters.", {"extra-binary-caches"}}; + Setting<StringSet> trustedSubstituters{this, {}, "trusted-substituters", + "Disabled substituters that may be enabled via the substituters option by untrusted users.", + {"trusted-binary-caches"}}; + Setting<Strings> trustedUsers{this, {"root"}, "trusted-users", "Which users or groups are trusted to ask the daemon to do unsafe things."}; @@ -267,8 +300,7 @@ public: Setting<bool> enableImportFromDerivation{this, true, "allow-import-from-derivation", "Whether the evaluator allows importing the result of a derivation."}; - struct CaseHackTag { }; - Setting<bool, CaseHackTag> useCaseHack{this, nix::useCaseHack, "use-case-hack", + CaseHackSetting useCaseHack{this, "use-case-hack", "Whether to enable a Darwin-specific hack for dealing with file name collisions."}; Setting<unsigned long> connectTimeout{this, 0, "connect-timeout", diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 9d5c04dca0c5..4da20330cf3f 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -27,7 +27,8 @@ libstore_CXXFLAGS = \ -DNIX_CONF_DIR=\"$(sysconfdir)/nix\" \ -DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \ -DNIX_BIN_DIR=\"$(bindir)\" \ - -DBASH_PATH="\"$(bash)\"" + -DBASH_PATH="\"$(bash)\"" \ + -DLSOF=\"$(lsof)\" $(d)/local-store.cc: $(d)/schema.sql.hh diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index da3c8eb8d89d..bc9ef3d47c5e 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 e7a810cec4d2..62c6433c741b 100644 --- a/src/libutil/config.cc +++ b/src/libutil/config.cc @@ -1,5 +1,6 @@ #include "config.hh" #include "args.hh" +#include "json.hh" namespace nix { @@ -9,6 +10,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 +24,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 +37,7 @@ void Config::addSetting(AbstractSetting * setting) alias, setting->name); else { setting->set(i->second); + setting->overriden = true; initials.erase(i); set = true; } @@ -47,11 +51,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 +98,23 @@ void Config::applyConfigFile(const Path & path, bool fatal) } catch (SysError &) { } } +void Config::resetOverriden() +{ + for (auto & s : _settings) + s.second.setting->overriden = false; +} + +void Config::toJSON(JSONObject & out) +{ + for (auto & s : _settings) + if (!s.second.isAlias) { + JSONObject out2(out.object(s.first)); + out2.attr("description", s.second.setting->description); + JSONPlaceholder out3(out2.placeholder("value")); + s.second.setting->toJSON(out3); + } +} + AbstractSetting::AbstractSetting( const std::string & name, const std::string & description, @@ -102,83 +123,98 @@ AbstractSetting::AbstractSetting( { } -template<> void Setting<std::string>::set(const std::string & str) +void AbstractSetting::toJSON(JSONPlaceholder & out) +{ + out.write(to_string()); +} + +template<typename T> +void BaseSetting<T>::toJSON(JSONPlaceholder & out) +{ + out.write(value); +} + +template<> void BaseSetting<std::string>::set(const std::string & str) { value = str; } -template<> std::string Setting<std::string>::to_string() +template<> std::string BaseSetting<std::string>::to_string() { return value; } -template<typename T, typename Tag> -void Setting<T, Tag>::set(const std::string & str) +template<typename T> +void BaseSetting<T>::set(const std::string & str) { static_assert(std::is_integral<T>::value, "Integer required."); if (!string2Int(str, value)) throw UsageError("setting '%s' has invalid value '%s'", name, str); } -template<typename T, typename Tag> -std::string Setting<T, Tag>::to_string() +template<typename T> +std::string BaseSetting<T>::to_string() { static_assert(std::is_integral<T>::value, "Integer required."); return std::to_string(value); } -bool AbstractSetting::parseBool(const std::string & str) +template<> void BaseSetting<bool>::set(const std::string & str) { if (str == "true" || str == "yes" || str == "1") - return true; + value = true; else if (str == "false" || str == "no" || str == "0") - return false; + value = false; else throw UsageError("Boolean setting '%s' has invalid value '%s'", name, str); } -template<> void Setting<bool>::set(const std::string & str) +template<> std::string BaseSetting<bool>::to_string() { - value = parseBool(str); + return value ? "true" : "false"; } -std::string AbstractSetting::printBool(bool b) +template<> void BaseSetting<Strings>::set(const std::string & str) { - return b ? "true" : "false"; + value = tokenizeString<Strings>(str); } - -template<> std::string Setting<bool>::to_string() +template<> std::string BaseSetting<Strings>::to_string() { - return printBool(value); + return concatStringsSep(" ", value); } -template<> void Setting<Strings>::set(const std::string & str) +template<> void BaseSetting<Strings>::toJSON(JSONPlaceholder & out) { - value = tokenizeString<Strings>(str); + JSONList list(out.list()); + for (auto & s : value) + list.elem(s); } -template<> std::string Setting<Strings>::to_string() +template<> void BaseSetting<StringSet>::set(const std::string & str) { - return concatStringsSep(" ", value); + value = tokenizeString<StringSet>(str); } -template<> void Setting<StringSet>::set(const std::string & str) +template<> std::string BaseSetting<StringSet>::to_string() { - value = tokenizeString<StringSet>(str); + return concatStringsSep(" ", value); } -template<> std::string Setting<StringSet>::to_string() +template<> void BaseSetting<StringSet>::toJSON(JSONPlaceholder & out) { - return concatStringsSep(" ", value); + JSONList list(out.list()); + for (auto & s : value) + list.elem(s); } -template class Setting<int>; -template class Setting<unsigned int>; -template class Setting<long>; -template class Setting<unsigned long>; -template class Setting<long long>; -template class Setting<unsigned long long>; +template class BaseSetting<int>; +template class BaseSetting<unsigned int>; +template class BaseSetting<long>; +template class BaseSetting<unsigned long>; +template class BaseSetting<long long>; +template class BaseSetting<unsigned long long>; +template class BaseSetting<bool>; void PathSetting::set(const std::string & str) { diff --git a/src/libutil/config.hh b/src/libutil/config.hh index 6c8612f675c7..91962109100d 100644 --- a/src/libutil/config.hh +++ b/src/libutil/config.hh @@ -9,6 +9,8 @@ namespace nix { class Args; class AbstractSetting; +class JSONPlaceholder; +class JSONObject; /* A class to simplify providing configuration settings. The typical use is to inherit Config and add Setting<T> members: @@ -51,9 +53,13 @@ public: void warnUnknownSettings(); - StringMap getSettings(); + StringMap getSettings(bool overridenOnly = false); void applyConfigFile(const Path & path, bool fatal = false); + + void resetOverriden(); + + void toJSON(JSONObject & out); }; class AbstractSetting @@ -68,6 +74,8 @@ public: int created = 123; + bool overriden = false; + protected: AbstractSetting( @@ -78,7 +86,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); } @@ -86,15 +94,14 @@ protected: virtual std::string to_string() = 0; - bool parseBool(const std::string & str); - std::string printBool(bool b); -}; + virtual void toJSON(JSONPlaceholder & out); -struct DefaultSettingTag { }; + bool isOverriden() { return overriden; } +}; /* A setting of type T. */ -template<typename T, typename Tag = DefaultSettingTag> -class Setting : public AbstractSetting +template<typename T> +class BaseSetting : public AbstractSetting { protected: @@ -102,42 +109,59 @@ protected: public: - Setting(Config * options, - const T & def, + BaseSetting(const T & def, const std::string & name, const std::string & description, const std::set<std::string> & aliases = {}) : AbstractSetting(name, description, aliases) , value(def) - { - options->addSetting(this); - } + { } operator const T &() const { return value; } operator T &() { return value; } const T & get() const { return value; } bool operator ==(const T & v2) const { return value == v2; } bool operator !=(const T & v2) const { return value != v2; } - void operator =(const T & v) { value = v; } + void operator =(const T & v) { assign(v); } + virtual void assign(const T & v) { value = v; } void set(const std::string & str) override; std::string to_string() override; + + void toJSON(JSONPlaceholder & out) override; }; template<typename T> -std::ostream & operator <<(std::ostream & str, const Setting<T> & opt) +std::ostream & operator <<(std::ostream & str, const BaseSetting<T> & opt) { str << (const T &) opt; return str; } template<typename T> -bool operator ==(const T & v1, const Setting<T> & v2) { return v1 == (const T &) v2; } +bool operator ==(const T & v1, const BaseSetting<T> & v2) { return v1 == (const T &) v2; } + +template<typename T> +class Setting : public BaseSetting<T> +{ +public: + Setting(Config * options, + const T & def, + const std::string & name, + const std::string & description, + const std::set<std::string> & aliases = {}) + : BaseSetting<T>(def, name, description, aliases) + { + options->addSetting(this); + } + + void operator =(const T & v) { this->assign(v); } +}; /* A special setting for Paths. These are automatically canonicalised (e.g. "/foo//bar/" becomes "/foo/bar"). */ -class PathSetting : public Setting<Path> +class PathSetting : public BaseSetting<Path> { bool allowEmpty; @@ -149,15 +173,17 @@ public: const std::string & name, const std::string & description, const std::set<std::string> & aliases = {}) - : Setting<Path>(options, def, name, description, aliases) + : BaseSetting<Path>(def, name, description, aliases) , allowEmpty(allowEmpty) { - set(value); + options->addSetting(this); } void set(const std::string & str) override; Path operator +(const char * p) const { return value + p; } + + void operator =(const Path & v) { this->assign(v); } }; } diff --git a/src/libutil/json.cc b/src/libutil/json.cc index 6023d1d4fb84..b8b8ef9c8cca 100644 --- a/src/libutil/json.cc +++ b/src/libutil/json.cc @@ -19,49 +19,32 @@ void toJSON(std::ostream & str, const char * start, const char * end) str << '"'; } -void toJSON(std::ostream & str, const std::string & s) -{ - toJSON(str, s.c_str(), s.c_str() + s.size()); -} - void toJSON(std::ostream & str, const char * s) { if (!s) str << "null"; else toJSON(str, s, s + strlen(s)); } -void toJSON(std::ostream & str, unsigned long long n) -{ - str << n; -} - -void toJSON(std::ostream & str, unsigned long n) -{ - str << n; -} - -void toJSON(std::ostream & str, long n) -{ - str << n; -} +template<> void toJSON<int>(std::ostream & str, const int & n) { str << n; } +template<> void toJSON<unsigned int>(std::ostream & str, const unsigned int & n) { str << n; } +template<> void toJSON<long>(std::ostream & str, const long & n) { str << n; } +template<> void toJSON<unsigned long>(std::ostream & str, const unsigned long & n) { str << n; } +template<> void toJSON<long long>(std::ostream & str, const long long & n) { str << n; } +template<> void toJSON<unsigned long long>(std::ostream & str, const unsigned long long & n) { str << n; } +template<> void toJSON<float>(std::ostream & str, const float & n) { str << n; } -void toJSON(std::ostream & str, unsigned int n) +template<> void toJSON<std::string>(std::ostream & str, const std::string & s) { - str << n; -} - -void toJSON(std::ostream & str, int n) -{ - str << n; + toJSON(str, s.c_str(), s.c_str() + s.size()); } -void toJSON(std::ostream & str, double f) +template<> void toJSON<bool>(std::ostream & str, const bool & b) { - str << f; + str << (b ? "true" : "false"); } -void toJSON(std::ostream & str, bool b) +template<> void toJSON<std::nullptr_t>(std::ostream & str, const std::nullptr_t & b) { - str << (b ? "true" : "false"); + str << "null"; } JSONWriter::JSONWriter(std::ostream & str, bool indent) diff --git a/src/libutil/json.hh b/src/libutil/json.hh index 03eecb732586..595e9bbe3491 100644 --- a/src/libutil/json.hh +++ b/src/libutil/json.hh @@ -7,15 +7,10 @@ namespace nix { void toJSON(std::ostream & str, const char * start, const char * end); -void toJSON(std::ostream & str, const std::string & s); void toJSON(std::ostream & str, const char * s); -void toJSON(std::ostream & str, unsigned long long n); -void toJSON(std::ostream & str, unsigned long n); -void toJSON(std::ostream & str, long n); -void toJSON(std::ostream & str, unsigned int n); -void toJSON(std::ostream & str, int n); -void toJSON(std::ostream & str, double f); -void toJSON(std::ostream & str, bool b); + +template<typename T> +void toJSON(std::ostream & str, const T & n); class JSONWriter { diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 0bd51afd1a9f..88a2f752c023 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; @@ -934,7 +946,12 @@ void closeOnExec(int fd) bool _isInterrupted = false; -thread_local bool interruptThrown = false; +static thread_local bool interruptThrown = false; + +void setInterruptThrown() +{ + interruptThrown = true; +} void _interrupted() { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 0e6941e4a8db..ae40dcd4cd2d 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); @@ -264,7 +267,7 @@ void closeOnExec(int fd); extern bool _isInterrupted; -extern thread_local bool interruptThrown; +void setInterruptThrown(); void _interrupted(); diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 1389353bb5d8..07ad0b45b3e4 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -440,7 +440,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe settings.keepGoing = readInt(from); settings.tryFallback = readInt(from); verbosity = (Verbosity) readInt(from); - settings.maxBuildJobs = readInt(from); + settings.maxBuildJobs.assign(readInt(from)); settings.maxSilentTime = readInt(from); settings.useBuildHook = readInt(from) != 0; settings.verboseBuild = lvlError == (Verbosity) readInt(from); @@ -448,20 +448,56 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe readInt(from); // obsolete printBuildTrace settings.buildCores = readInt(from); settings.useSubstitutes = readInt(from); + + StringMap overrides; if (GET_PROTOCOL_MINOR(clientVersion) >= 12) { unsigned int n = readInt(from); for (unsigned int i = 0; i < n; i++) { string name = readString(from); string value = readString(from); - try { - if (trusted || name == "build-timeout") - settings.set(name, value); - } catch (UsageError & e) { - warn(e.what()); - } + overrides.emplace(name, value); } } + startWork(); + + for (auto & i : overrides) { + auto & name(i.first); + auto & value(i.second); + + auto setSubstituters = [&](Setting<Strings> & res) { + if (name != res.name && res.aliases.count(name) == 0) + return false; + StringSet trusted = settings.trustedSubstituters; + for (auto & s : settings.substituters.get()) + trusted.insert(s); + Strings subs; + auto ss = tokenizeString<Strings>(value); + for (auto & s : ss) + if (trusted.count(s)) + subs.push_back(s); + else + warn("ignoring untrusted substituter '%s'", s); + res = subs; + return true; + }; + + try { + if (trusted + || name == settings.buildTimeout.name + || name == settings.connectTimeout.name) + settings.set(name, value); + else if (setSubstituters(settings.substituters)) + ; + else if (setSubstituters(settings.extraSubstituters)) + ; + else + debug("ignoring untrusted setting '%s'", name); + } catch (UsageError & e) { + warn(e.what()); + } + } + stopWork(); break; } diff --git a/src/nix/show-config.cc b/src/nix/show-config.cc index ba39e2bb29b3..aade2adeace4 100644 --- a/src/nix/show-config.cc +++ b/src/nix/show-config.cc @@ -31,8 +31,7 @@ struct CmdShowConfig : Command if (json) { // FIXME: use appropriate JSON types (bool, ints, etc). JSONObject jsonObj(std::cout, true); - for (auto & s : settings.getSettings()) - jsonObj.attr(s.first, s.second); + settings.toJSON(jsonObj); } else { for (auto & s : settings.getSettings()) std::cout << s.first + " = " + s.second + "\n"; |