mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-25 15:26:17 +02:00
Merge pull request #11014 from obsidiansystems/plugins-libmain
Move plugins infra to `libnixmain`
This commit is contained in:
commit
b230c01f73
20 changed files with 365 additions and 131 deletions
|
@ -26,6 +26,7 @@ subproject('external-api-docs')
|
|||
subproject('libutil-c')
|
||||
subproject('libstore-c')
|
||||
subproject('libexpr-c')
|
||||
subproject('libmain-c')
|
||||
|
||||
# Language Bindings
|
||||
subproject('perl')
|
||||
|
|
|
@ -29,6 +29,7 @@ in
|
|||
nix-flake-tests = callPackage ../tests/unit/libflake/package.nix { };
|
||||
|
||||
nix-main = callPackage ../src/libmain/package.nix { };
|
||||
nix-main-c = callPackage ../src/libmain-c/package.nix { };
|
||||
|
||||
nix-cmd = callPackage ../src/libcmd/package.nix { };
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ let
|
|||
"nix-flake"
|
||||
"nix-flake-tests"
|
||||
"nix-main"
|
||||
"nix-main-c"
|
||||
"nix-cmd"
|
||||
"nix-ng"
|
||||
];
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "machines.hh"
|
||||
#include "shared.hh"
|
||||
#include "plugin.hh"
|
||||
#include "pathlocks.hh"
|
||||
#include "globals.hh"
|
||||
#include "serialise.hh"
|
||||
|
|
1
src/libmain-c/.version
Symbolic link
1
src/libmain-c/.version
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../.version
|
1
src/libmain-c/build-utils-meson
Symbolic link
1
src/libmain-c/build-utils-meson
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../build-utils-meson
|
84
src/libmain-c/meson.build
Normal file
84
src/libmain-c/meson.build
Normal file
|
@ -0,0 +1,84 @@
|
|||
project('nix-main-c', 'cpp',
|
||||
version : files('.version'),
|
||||
default_options : [
|
||||
'cpp_std=c++2a',
|
||||
# TODO(Qyriad): increase the warning level
|
||||
'warning_level=1',
|
||||
'debug=true',
|
||||
'optimization=2',
|
||||
'errorlogs=true', # Please print logs for tests that fail
|
||||
],
|
||||
meson_version : '>= 1.1',
|
||||
license : 'LGPL-2.1-or-later',
|
||||
)
|
||||
|
||||
cxx = meson.get_compiler('cpp')
|
||||
|
||||
subdir('build-utils-meson/deps-lists')
|
||||
|
||||
configdata = configuration_data()
|
||||
|
||||
deps_private_maybe_subproject = [
|
||||
dependency('nix-util'),
|
||||
dependency('nix-store'),
|
||||
dependency('nix-main'),
|
||||
]
|
||||
deps_public_maybe_subproject = [
|
||||
dependency('nix-util-c'),
|
||||
dependency('nix-store-c'),
|
||||
]
|
||||
subdir('build-utils-meson/subprojects')
|
||||
|
||||
# TODO rename, because it will conflict with downstream projects
|
||||
configdata.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||
|
||||
config_h = configure_file(
|
||||
configuration : configdata,
|
||||
output : 'config-main.h',
|
||||
)
|
||||
|
||||
add_project_arguments(
|
||||
# TODO(Qyriad): Yes this is how the autoconf+Make system did it.
|
||||
# It would be nice for our headers to be idempotent instead.
|
||||
|
||||
# From C++ libraries, only for internals
|
||||
'-include', 'config-util.hh',
|
||||
'-include', 'config-store.hh',
|
||||
'-include', 'config-main.hh',
|
||||
|
||||
# From C libraries, for our public, installed headers too
|
||||
'-include', 'config-util.h',
|
||||
'-include', 'config-store.h',
|
||||
'-include', 'config-main.h',
|
||||
language : 'cpp',
|
||||
)
|
||||
|
||||
subdir('build-utils-meson/diagnostics')
|
||||
|
||||
sources = files(
|
||||
'nix_api_main.cc',
|
||||
)
|
||||
|
||||
include_dirs = [include_directories('.')]
|
||||
|
||||
headers = [config_h] + files(
|
||||
'nix_api_main.h',
|
||||
)
|
||||
|
||||
subdir('build-utils-meson/export-all-symbols')
|
||||
|
||||
this_library = library(
|
||||
'nixmainc',
|
||||
sources,
|
||||
dependencies : deps_public + deps_private + deps_other,
|
||||
include_directories : include_dirs,
|
||||
link_args: linker_export_flags,
|
||||
prelink : true, # For C++ static initializers
|
||||
install : true,
|
||||
)
|
||||
|
||||
install_headers(headers, subdir : 'nix', preserve_path : true)
|
||||
|
||||
libraries_private = []
|
||||
|
||||
subdir('build-utils-meson/export')
|
16
src/libmain-c/nix_api_main.cc
Normal file
16
src/libmain-c/nix_api_main.cc
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "nix_api_store.h"
|
||||
#include "nix_api_store_internal.h"
|
||||
#include "nix_api_util.h"
|
||||
#include "nix_api_util_internal.h"
|
||||
|
||||
#include "plugin.hh"
|
||||
|
||||
nix_err nix_init_plugins(nix_c_context * context)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
nix::initPlugins();
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
40
src/libmain-c/nix_api_main.h
Normal file
40
src/libmain-c/nix_api_main.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef NIX_API_MAIN_H
|
||||
#define NIX_API_MAIN_H
|
||||
/**
|
||||
* @defgroup libmain libmain
|
||||
* @brief C bindings for nix libmain
|
||||
*
|
||||
* libmain has misc utilities for CLI commands
|
||||
* @{
|
||||
*/
|
||||
/** @file
|
||||
* @brief Main entry for the libmain C bindings
|
||||
*/
|
||||
|
||||
#include "nix_api_util.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// cffi start
|
||||
|
||||
/**
|
||||
* @brief Loads the plugins specified in Nix's plugin-files setting.
|
||||
*
|
||||
* Call this once, after calling your desired init functions and setting
|
||||
* relevant settings.
|
||||
*
|
||||
* @param[out] context Optional, stores error information
|
||||
* @return NIX_OK if the initialization was successful, an error code otherwise.
|
||||
*/
|
||||
nix_err nix_init_plugins(nix_c_context * context);
|
||||
|
||||
// cffi end
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif // NIX_API_MAIN_H
|
83
src/libmain-c/package.nix
Normal file
83
src/libmain-c/package.nix
Normal file
|
@ -0,0 +1,83 @@
|
|||
{ lib
|
||||
, stdenv
|
||||
, mkMesonDerivation
|
||||
, releaseTools
|
||||
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
|
||||
, nix-util-c
|
||||
, nix-store
|
||||
, nix-store-c
|
||||
, nix-main
|
||||
|
||||
# Configuration Options
|
||||
|
||||
, version
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) fileset;
|
||||
in
|
||||
|
||||
mkMesonDerivation (finalAttrs: {
|
||||
pname = "nix-main-c";
|
||||
inherit version;
|
||||
|
||||
workDir = ./.;
|
||||
fileset = fileset.unions [
|
||||
../../build-utils-meson
|
||||
./build-utils-meson
|
||||
../../.version
|
||||
./.version
|
||||
./meson.build
|
||||
# ./meson.options
|
||||
(fileset.fileFilter (file: file.hasExt "cc") ./.)
|
||||
(fileset.fileFilter (file: file.hasExt "hh") ./.)
|
||||
(fileset.fileFilter (file: file.hasExt "h") ./.)
|
||||
];
|
||||
|
||||
outputs = [ "out" "dev" ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
propagatedBuildInputs = [
|
||||
nix-util-c
|
||||
nix-store
|
||||
nix-store-c
|
||||
nix-main
|
||||
];
|
||||
|
||||
preConfigure =
|
||||
# "Inline" .version so it's not a symlink, and includes the suffix.
|
||||
# Do the meson utils, without modification.
|
||||
''
|
||||
chmod u+w ./.version
|
||||
echo ${version} > ../../.version
|
||||
'';
|
||||
|
||||
mesonFlags = [
|
||||
];
|
||||
|
||||
env = lib.optionalAttrs (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) {
|
||||
LDFLAGS = "-fuse-ld=gold";
|
||||
};
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||
|
||||
meta = {
|
||||
platforms = lib.platforms.unix ++ lib.platforms.windows;
|
||||
};
|
||||
|
||||
})
|
|
@ -5,6 +5,7 @@
|
|||
#include "logging.hh"
|
||||
#include "loggers.hh"
|
||||
#include "util.hh"
|
||||
#include "plugin.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ subdir('build-utils-meson/diagnostics')
|
|||
sources = files(
|
||||
'common-args.cc',
|
||||
'loggers.cc',
|
||||
'plugin.cc',
|
||||
'progress-bar.cc',
|
||||
'shared.cc',
|
||||
)
|
||||
|
@ -79,6 +80,7 @@ include_dirs = [include_directories('.')]
|
|||
headers = [config_h] + files(
|
||||
'common-args.hh',
|
||||
'loggers.hh',
|
||||
'plugin.hh',
|
||||
'progress-bar.hh',
|
||||
'shared.hh',
|
||||
)
|
||||
|
|
117
src/libmain/plugin.cc
Normal file
117
src/libmain/plugin.cc
Normal file
|
@ -0,0 +1,117 @@
|
|||
#ifndef _WIN32
|
||||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "config-global.hh"
|
||||
#include "signals.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct PluginFilesSetting : public BaseSetting<Paths>
|
||||
{
|
||||
bool pluginsLoaded = false;
|
||||
|
||||
PluginFilesSetting(
|
||||
Config * options,
|
||||
const Paths & def,
|
||||
const std::string & name,
|
||||
const std::string & description,
|
||||
const std::set<std::string> & aliases = {})
|
||||
: BaseSetting<Paths>(def, true, name, description, aliases)
|
||||
{
|
||||
options->addSetting(this);
|
||||
}
|
||||
|
||||
Paths parse(const std::string & str) const override;
|
||||
};
|
||||
|
||||
Paths PluginFilesSetting::parse(const std::string & str) const
|
||||
{
|
||||
if (pluginsLoaded)
|
||||
throw UsageError(
|
||||
"plugin-files set after plugins were loaded, you may need to move the flag before the subcommand");
|
||||
return BaseSetting<Paths>::parse(str);
|
||||
}
|
||||
|
||||
struct PluginSettings : Config
|
||||
{
|
||||
PluginFilesSetting pluginFiles{
|
||||
this,
|
||||
{},
|
||||
"plugin-files",
|
||||
R"(
|
||||
A list of plugin files to be loaded by Nix. Each of these files will
|
||||
be dlopened by Nix. If they contain the symbol `nix_plugin_entry()`,
|
||||
this symbol will be called. Alternatively, they can affect execution
|
||||
through static initialization. In particular, these plugins may construct
|
||||
static instances of RegisterPrimOp to add new primops or constants to the
|
||||
expression language, RegisterStoreImplementation to add new store
|
||||
implementations, RegisterCommand to add new subcommands to the `nix`
|
||||
command, and RegisterSetting to add new nix config settings. See the
|
||||
constructors for those types for more details.
|
||||
|
||||
Warning! These APIs are inherently unstable and may change from
|
||||
release to release.
|
||||
|
||||
Since these files are loaded into the same address space as Nix
|
||||
itself, they must be DSOs compatible with the instance of Nix
|
||||
running at the time (i.e. compiled against the same headers, not
|
||||
linked to any incompatible libraries). They should not be linked to
|
||||
any Nix libs directly, as those will be available already at load
|
||||
time.
|
||||
|
||||
If an entry in the list is a directory, all files in the directory
|
||||
are loaded as plugins (non-recursively).
|
||||
)"};
|
||||
};
|
||||
|
||||
static PluginSettings pluginSettings;
|
||||
|
||||
static GlobalConfig::Register rPluginSettings(&pluginSettings);
|
||||
|
||||
void initPlugins()
|
||||
{
|
||||
assert(!pluginSettings.pluginFiles.pluginsLoaded);
|
||||
for (const auto & pluginFile : pluginSettings.pluginFiles.get()) {
|
||||
std::vector<std::filesystem::path> pluginFiles;
|
||||
try {
|
||||
auto ents = std::filesystem::directory_iterator{pluginFile};
|
||||
for (const auto & ent : ents) {
|
||||
checkInterrupt();
|
||||
pluginFiles.emplace_back(ent.path());
|
||||
}
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
if (e.code() != std::errc::not_a_directory)
|
||||
throw;
|
||||
pluginFiles.emplace_back(pluginFile);
|
||||
}
|
||||
for (const auto & file : pluginFiles) {
|
||||
checkInterrupt();
|
||||
/* handle is purposefully leaked as there may be state in the
|
||||
DSO needed by the action of the plugin. */
|
||||
#ifndef _WIN32 // TODO implement via DLL loading on Windows
|
||||
void * handle = dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!handle)
|
||||
throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
|
||||
|
||||
/* Older plugins use a statically initialized object to run their code.
|
||||
Newer plugins can also export nix_plugin_entry() */
|
||||
void (*nix_plugin_entry)() = (void (*)()) dlsym(handle, "nix_plugin_entry");
|
||||
if (nix_plugin_entry)
|
||||
nix_plugin_entry();
|
||||
#else
|
||||
throw Error("could not dynamically open plugin file '%s'", file);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Since plugins can add settings, try to re-apply previously
|
||||
unknown settings. */
|
||||
globalConfig.reapplyUnknownSettings();
|
||||
globalConfig.warnUnknownSettings();
|
||||
|
||||
/* Tell the user if they try to set plugin-files after we've already loaded */
|
||||
pluginSettings.pluginFiles.pluginsLoaded = true;
|
||||
}
|
||||
|
||||
}
|
12
src/libmain/plugin.hh
Normal file
12
src/libmain/plugin.hh
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* This should be called after settings are initialized, but before
|
||||
* anything else
|
||||
*/
|
||||
void initPlugins();
|
||||
|
||||
}
|
|
@ -29,16 +29,6 @@ nix_err nix_libstore_init_no_load_config(nix_c_context * context)
|
|||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err nix_init_plugins(nix_c_context * context)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
nix::initPlugins();
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
Store * nix_store_open(nix_c_context * context, const char * uri, const char *** params)
|
||||
{
|
||||
if (context)
|
||||
|
|
|
@ -42,17 +42,6 @@ nix_err nix_libstore_init(nix_c_context * context);
|
|||
*/
|
||||
nix_err nix_libstore_init_no_load_config(nix_c_context * context);
|
||||
|
||||
/**
|
||||
* @brief Loads the plugins specified in Nix's plugin-files setting.
|
||||
*
|
||||
* Call this once, after calling your desired init functions and setting
|
||||
* relevant settings.
|
||||
*
|
||||
* @param[out] context Optional, stores error information
|
||||
* @return NIX_OK if the initialization was successful, an error code otherwise.
|
||||
*/
|
||||
nix_err nix_init_plugins(nix_c_context * context);
|
||||
|
||||
/**
|
||||
* @brief Open a nix store.
|
||||
*
|
||||
|
|
|
@ -246,8 +246,7 @@ struct ClientSettings
|
|||
// the daemon, as that could cause some pretty weird stuff
|
||||
if (parseFeatures(tokenizeString<StringSet>(value)) != experimentalFeatureSettings.experimentalFeatures.get())
|
||||
debug("Ignoring the client-specified experimental features");
|
||||
} else if (name == settings.pluginFiles.name) {
|
||||
if (tokenizeString<Paths>(value) != settings.pluginFiles.get())
|
||||
} else if (name == "plugin-files") {
|
||||
warn("Ignoring the client-specified plugin-files.\n"
|
||||
"The client specifying plugins to the daemon never made sense, and was removed in Nix >=2.14.");
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <dlfcn.h>
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
|
@ -335,60 +334,6 @@ unsigned int MaxBuildJobsSetting::parse(const std::string & str) const
|
|||
}
|
||||
|
||||
|
||||
Paths PluginFilesSetting::parse(const std::string & str) const
|
||||
{
|
||||
if (pluginsLoaded)
|
||||
throw UsageError("plugin-files set after plugins were loaded, you may need to move the flag before the subcommand");
|
||||
return BaseSetting<Paths>::parse(str);
|
||||
}
|
||||
|
||||
|
||||
void initPlugins()
|
||||
{
|
||||
assert(!settings.pluginFiles.pluginsLoaded);
|
||||
for (const auto & pluginFile : settings.pluginFiles.get()) {
|
||||
std::vector<std::filesystem::path> pluginFiles;
|
||||
try {
|
||||
auto ents = std::filesystem::directory_iterator{pluginFile};
|
||||
for (const auto & ent : ents) {
|
||||
checkInterrupt();
|
||||
pluginFiles.emplace_back(ent.path());
|
||||
}
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
if (e.code() != std::errc::not_a_directory)
|
||||
throw;
|
||||
pluginFiles.emplace_back(pluginFile);
|
||||
}
|
||||
for (const auto & file : pluginFiles) {
|
||||
checkInterrupt();
|
||||
/* handle is purposefully leaked as there may be state in the
|
||||
DSO needed by the action of the plugin. */
|
||||
#ifndef _WIN32 // TODO implement via DLL loading on Windows
|
||||
void *handle =
|
||||
dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!handle)
|
||||
throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
|
||||
|
||||
/* Older plugins use a statically initialized object to run their code.
|
||||
Newer plugins can also export nix_plugin_entry() */
|
||||
void (*nix_plugin_entry)() = (void (*)())dlsym(handle, "nix_plugin_entry");
|
||||
if (nix_plugin_entry)
|
||||
nix_plugin_entry();
|
||||
#else
|
||||
throw Error("could not dynamically open plugin file '%s'", file);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Since plugins can add settings, try to re-apply previously
|
||||
unknown settings. */
|
||||
globalConfig.reapplyUnknownSettings();
|
||||
globalConfig.warnUnknownSettings();
|
||||
|
||||
/* Tell the user if they try to set plugin-files after we've already loaded */
|
||||
settings.pluginFiles.pluginsLoaded = true;
|
||||
}
|
||||
|
||||
static void preloadNSS()
|
||||
{
|
||||
/* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of
|
||||
|
|
|
@ -31,23 +31,6 @@ struct MaxBuildJobsSetting : public BaseSetting<unsigned int>
|
|||
unsigned int parse(const std::string & str) const override;
|
||||
};
|
||||
|
||||
struct PluginFilesSetting : public BaseSetting<Paths>
|
||||
{
|
||||
bool pluginsLoaded = false;
|
||||
|
||||
PluginFilesSetting(Config * options,
|
||||
const Paths & def,
|
||||
const std::string & name,
|
||||
const std::string & description,
|
||||
const std::set<std::string> & aliases = {})
|
||||
: BaseSetting<Paths>(def, true, name, description, aliases)
|
||||
{
|
||||
options->addSetting(this);
|
||||
}
|
||||
|
||||
Paths parse(const std::string & str) const override;
|
||||
};
|
||||
|
||||
const uint32_t maxIdsPerBuild =
|
||||
#if __linux__
|
||||
1 << 16
|
||||
|
@ -1158,33 +1141,6 @@ public:
|
|||
Setting<uint64_t> minFreeCheckInterval{this, 5, "min-free-check-interval",
|
||||
"Number of seconds between checking free disk space."};
|
||||
|
||||
PluginFilesSetting pluginFiles{
|
||||
this, {}, "plugin-files",
|
||||
R"(
|
||||
A list of plugin files to be loaded by Nix. Each of these files will
|
||||
be dlopened by Nix. If they contain the symbol `nix_plugin_entry()`,
|
||||
this symbol will be called. Alternatively, they can affect execution
|
||||
through static initialization. In particular, these plugins may construct
|
||||
static instances of RegisterPrimOp to add new primops or constants to the
|
||||
expression language, RegisterStoreImplementation to add new store
|
||||
implementations, RegisterCommand to add new subcommands to the `nix`
|
||||
command, and RegisterSetting to add new nix config settings. See the
|
||||
constructors for those types for more details.
|
||||
|
||||
Warning! These APIs are inherently unstable and may change from
|
||||
release to release.
|
||||
|
||||
Since these files are loaded into the same address space as Nix
|
||||
itself, they must be DSOs compatible with the instance of Nix
|
||||
running at the time (i.e. compiled against the same headers, not
|
||||
linked to any incompatible libraries). They should not be linked to
|
||||
any Nix libs directly, as those will be available already at load
|
||||
time.
|
||||
|
||||
If an entry in the list is a directory, all files in the directory
|
||||
are loaded as plugins (non-recursively).
|
||||
)"};
|
||||
|
||||
Setting<size_t> narBufferSize{this, 32 * 1024 * 1024, "nar-buffer-size",
|
||||
"Maximum size of NARs before spilling them to disk."};
|
||||
|
||||
|
@ -1278,12 +1234,6 @@ public:
|
|||
// FIXME: don't use a global variable.
|
||||
extern Settings settings;
|
||||
|
||||
/**
|
||||
* This should be called after settings are initialized, but before
|
||||
* anything else
|
||||
*/
|
||||
void initPlugins();
|
||||
|
||||
/**
|
||||
* Load the configuration (from `nix.conf`, `NIX_CONFIG`, etc.) into the
|
||||
* given configuration object.
|
||||
|
|
|
@ -128,7 +128,7 @@ void RemoteStore::setOptions(Connection & conn)
|
|||
overrides.erase(settings.useSubstitutes.name);
|
||||
overrides.erase(loggerSettings.showTrace.name);
|
||||
overrides.erase(experimentalFeatureSettings.experimentalFeatures.name);
|
||||
overrides.erase(settings.pluginFiles.name);
|
||||
overrides.erase("plugin-files");
|
||||
conn.to << overrides.size();
|
||||
for (auto & i : overrides)
|
||||
conn.to << i.first << i.second.value;
|
||||
|
|
Loading…
Reference in a new issue