fix(config): Reintroduce multiple inheritance (#2271)
Pre 3.5.0, any key starting with 'inherit' was treated as an inherit directive. This allowed for multiple inheritance even though it was never inteded in that way. 3.5.0 removed that bug/feature by doing a strict check against 'inherit' It seems people were relying on this behavior, so we are adding it back. However multiple inheritance with multiple keys is also deprecated in favor of the `inherit` key now supporting multiple space separated sections. This is because the config doesn't have a key order, but inheritance does depend on the order the different section keys are copied over (if multiple inherited sections define the same key). Fixes #2269
This commit is contained in:
parent
3d6a7ffd4d
commit
b2c515c73c
@ -72,37 +72,61 @@ void config::warn_deprecated(const string& section, const string& key, string re
|
||||
* Look for sections set up to inherit from a base section
|
||||
* and copy the missing parameters
|
||||
*
|
||||
* Multiple sections can be specified, separated by a space.
|
||||
*
|
||||
* [sub/section]
|
||||
* inherit = base/section
|
||||
* inherit = section1 section2
|
||||
*/
|
||||
void config::copy_inherited() {
|
||||
for (auto&& section : m_sections) {
|
||||
std::vector<string> inherit_sections;
|
||||
|
||||
// Collect all sections to be inherited
|
||||
for (auto&& param : section.second) {
|
||||
if (param.first == "inherit") {
|
||||
// Get name of base section
|
||||
string key_name = param.first;
|
||||
if (key_name == "inherit") {
|
||||
auto inherit = param.second;
|
||||
if ((inherit = dereference<string>(section.first, param.first, inherit, inherit)).empty()) {
|
||||
throw value_error("Invalid section \"\" defined for \"" + section.first + ".inherit\"");
|
||||
inherit = dereference<string>(section.first, key_name, inherit, inherit);
|
||||
|
||||
std::vector<string> sections = string_util::split(std::move(inherit), ' ');
|
||||
|
||||
inherit_sections.insert(inherit_sections.end(), sections.begin(), sections.end());
|
||||
|
||||
} else if (key_name.find("inherit") == 0) {
|
||||
// Legacy support for keys that just start with 'inherit'
|
||||
m_log.warn(
|
||||
"\"%s.%s\": Using anything other than 'inherit' for inheriting section keys is deprecated. "
|
||||
"The 'inherit' key supports multiple section names separated by a space.",
|
||||
section.first, key_name);
|
||||
|
||||
auto inherit = param.second;
|
||||
inherit = dereference<string>(section.first, key_name, inherit, inherit);
|
||||
if (inherit.empty() || m_sections.find(inherit) == m_sections.end()) {
|
||||
throw value_error(
|
||||
"Invalid section \"" + inherit + "\" defined for \"" + section.first + "." + key_name + "\"");
|
||||
}
|
||||
|
||||
// Find and validate base section
|
||||
auto base_section = m_sections.find(inherit);
|
||||
inherit_sections.push_back(std::move(inherit));
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& base_name : inherit_sections) {
|
||||
const auto base_section = m_sections.find(base_name);
|
||||
if (base_section == m_sections.end()) {
|
||||
throw value_error("Invalid section \"" + inherit + "\" defined for \"" + section.first + ".inherit\"");
|
||||
throw value_error("Invalid section \"" + base_name + "\" defined for \"" + section.first + ".inherit\"");
|
||||
}
|
||||
|
||||
m_log.trace("config: Copying missing params (sub=\"%s\", base=\"%s\")", section.first, inherit);
|
||||
m_log.trace("config: Inheriting keys from \"%s\" in \"%s\"", base_name, section.first);
|
||||
|
||||
/*
|
||||
* Iterate the base and copy the parameters that haven't been defined
|
||||
* for the sub-section
|
||||
* yet.
|
||||
*/
|
||||
for (auto&& base_param : base_section->second) {
|
||||
section.second.emplace(base_param.first, base_param.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
|
Loading…
Reference in New Issue
Block a user