Merge branch 'register-settings' of https://github.com/shlevy/nix

This commit is contained in:
Eelco Dolstra 2018-02-19 13:58:34 +01:00
commit 75a1d96cfd
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
8 changed files with 65 additions and 32 deletions

View file

@ -757,9 +757,10 @@ builtins.fetchurl {
plugins may construct static instances of RegisterPrimOp to plugins may construct static instances of RegisterPrimOp to
add new primops or constants to the expression language, add new primops or constants to the expression language,
RegisterStoreImplementation to add new store implementations, RegisterStoreImplementation to add new store implementations,
and RegisterCommand to add new subcommands to the RegisterCommand to add new subcommands to the
<literal>nix</literal> command. See the constructors for those <literal>nix</literal> command, and RegisterSetting to add new
types for more details. nix config settings. See the constructors for those types for
more details.
</para> </para>
<para> <para>
Since these files are loaded into the same address space as Since these files are loaded into the same address space as

View file

@ -162,6 +162,22 @@ void initPlugins()
throw Error("could not dynamically open plugin file '%s%': %s%", file, dlerror()); throw Error("could not dynamically open plugin file '%s%': %s%", file, dlerror());
} }
} }
/* We handle settings registrations here, since plugins can add settings */
if (RegisterSetting::settingRegistrations) {
for (auto & registration : *RegisterSetting::settingRegistrations)
settings.addSetting(registration);
delete RegisterSetting::settingRegistrations;
}
settings.handleUnknownSettings();
}
RegisterSetting::SettingRegistrations * RegisterSetting::settingRegistrations;
RegisterSetting::RegisterSetting(AbstractSetting * s)
{
if (!settingRegistrations)
settingRegistrations = new SettingRegistrations;
settingRegistrations->emplace_back(s);
} }

View file

@ -386,5 +386,12 @@ void initPlugins();
extern const string nixVersion; extern const string nixVersion;
struct RegisterSetting
{
typedef std::vector<AbstractSetting *> SettingRegistrations;
static SettingRegistrations * settingRegistrations;
RegisterSetting(AbstractSetting * s);
};
} }

View file

@ -839,7 +839,7 @@ ref<Store> openStore(const std::string & uri_,
for (auto fun : *RegisterStoreImplementation::implementations) { for (auto fun : *RegisterStoreImplementation::implementations) {
auto store = fun(uri, params); auto store = fun(uri, params);
if (store) { if (store) {
store->warnUnknownSettings(); store->handleUnknownSettings();
return ref<Store>(store); return ref<Store>(store);
} }
} }

View file

@ -7,10 +7,12 @@ namespace nix {
void Config::set(const std::string & name, const std::string & value) void Config::set(const std::string & name, const std::string & value)
{ {
auto i = _settings.find(name); auto i = _settings.find(name);
if (i == _settings.end()) if (i == _settings.end()) {
throw UsageError("unknown setting '%s'", name); extras.emplace(name, value);
i->second.setting->set(value); } else {
i->second.setting->overriden = true; i->second.setting->set(value);
i->second.setting->overriden = true;
}
} }
void Config::addSetting(AbstractSetting * setting) void Config::addSetting(AbstractSetting * setting)
@ -21,34 +23,37 @@ void Config::addSetting(AbstractSetting * setting)
bool set = false; bool set = false;
auto i = initials.find(setting->name); auto i = extras.find(setting->name);
if (i != initials.end()) { if (i != extras.end()) {
setting->set(i->second); setting->set(i->second);
setting->overriden = true; setting->overriden = true;
initials.erase(i); extras.erase(i);
set = true; set = true;
} }
for (auto & alias : setting->aliases) { for (auto & alias : setting->aliases) {
auto i = initials.find(alias); auto i = extras.find(alias);
if (i != initials.end()) { if (i != extras.end()) {
if (set) if (set)
warn("setting '%s' is set, but it's an alias of '%s' which is also set", warn("setting '%s' is set, but it's an alias of '%s' which is also set",
alias, setting->name); alias, setting->name);
else { else {
setting->set(i->second); setting->set(i->second);
setting->overriden = true; setting->overriden = true;
initials.erase(i); extras.erase(i);
set = true; set = true;
} }
} }
} }
} }
void Config::warnUnknownSettings() void Config::handleUnknownSettings(bool fatal)
{ {
for (auto & i : initials) for (auto & s : extras)
warn("unknown setting '%s'", i.first); if (fatal)
throw UsageError("unknown setting '%s%'", s.first);
else
warn("unknown setting '%s'", s.first);
} }
StringMap Config::getSettings(bool overridenOnly) StringMap Config::getSettings(bool overridenOnly)
@ -60,7 +65,7 @@ StringMap Config::getSettings(bool overridenOnly)
return res; return res;
} }
void Config::applyConfigFile(const Path & path, bool fatal) void Config::applyConfigFile(const Path & path)
{ {
try { try {
string contents = readFile(path); string contents = readFile(path);
@ -97,7 +102,7 @@ void Config::applyConfigFile(const Path & path, bool fatal)
throw UsageError("illegal configuration line '%1%' in '%2%'", line, path); throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
auto p = absPath(tokens[1], dirOf(path)); auto p = absPath(tokens[1], dirOf(path));
if (pathExists(p)) { if (pathExists(p)) {
applyConfigFile(p, fatal); applyConfigFile(p);
} else if (!ignoreMissing) { } else if (!ignoreMissing) {
throw Error("file '%1%' included from '%2%' not found", p, path); throw Error("file '%1%' included from '%2%' not found", p, path);
} }
@ -112,12 +117,7 @@ void Config::applyConfigFile(const Path & path, bool fatal)
vector<string>::iterator i = tokens.begin(); vector<string>::iterator i = tokens.begin();
advance(i, 2); advance(i, 2);
try { set(name, concatStringsSep(" ", Strings(i, tokens.end()))); // FIXME: slow
set(name, concatStringsSep(" ", Strings(i, tokens.end()))); // FIXME: slow
} catch (UsageError & e) {
if (fatal) throw;
warn("in configuration file '%s': %s", path, e.what());
}
}; };
} catch (SysError &) { } } catch (SysError &) { }
} }

View file

@ -48,25 +48,25 @@ private:
Settings _settings; Settings _settings;
StringMap initials; StringMap extras;
public: public:
Config(const StringMap & initials) Config(const StringMap & initials)
: initials(initials) : extras(initials)
{ } { }
void set(const std::string & name, const std::string & value); void set(const std::string & name, const std::string & value);
void addSetting(AbstractSetting * setting); void addSetting(AbstractSetting * setting);
void warnUnknownSettings(); void handleUnknownSettings(bool fatal = false);
StringMap getSettings(bool overridenOnly = false); StringMap getSettings(bool overridenOnly = false);
const Settings & _getSettings() { return _settings; } const Settings & _getSettings() { return _settings; }
void applyConfigFile(const Path & path, bool fatal = false); void applyConfigFile(const Path & path);
void resetOverriden(); void resetOverriden();

View file

@ -2,6 +2,6 @@ source common.sh
set -o pipefail set -o pipefail
res=$(nix eval '(builtins.anotherNull)' --option plugin-files $PWD/plugins/libplugintest*) res=$(nix eval '(builtins.anotherNull)' --option setting-set true --option plugin-files $PWD/plugins/libplugintest*)
[ "$res"x = "nullx" ] [ "$res"x = "nullx" ]

View file

@ -1,10 +1,19 @@
#include "globals.hh"
#include "primops.hh" #include "primops.hh"
using namespace nix; using namespace nix;
static BaseSetting<bool> settingSet{false, "setting-set",
"Whether the plugin-defined setting was set"};
static RegisterSetting rs(&settingSet);
static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v) static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v)
{ {
mkNull(v); if (settingSet)
mkNull(v);
else
mkBool(v, false);
} }
static RegisterPrimOp r("anotherNull", 0, prim_anotherNull); static RegisterPrimOp rp("anotherNull", 0, prim_anotherNull);