From cf81f1bbb72b511ac785822bc125a9543d457e01 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Fri, 23 Oct 2020 01:41:28 +0100 Subject: [PATCH] Make composing variables compose in the expected order --- apps/openmw/main.cpp | 2 + components/files/configurationmanager.cpp | 63 ++++++++++++++++++++++- components/files/configurationmanager.hpp | 4 ++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 4e18ad95f5..0c46903c91 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -164,7 +164,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat return false; } + bpo::variables_map composingVariables = cfgMgr.separateComposingVariables(variables, desc); cfgMgr.readConfiguration(variables, desc); + cfgMgr.mergeComposingVariables(variables, composingVariables, desc); Version::Version v = Version::getOpenmwVersion(variables["resources"].as().toStdString()); std::cout << v.describe() << std::endl; diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index c74c399224..42639d3e5d 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -2,6 +2,7 @@ #include #include +#include #include /** @@ -58,23 +59,83 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m { bool silent = mSilent; mSilent = quiet; - + // User config has the highest priority. + auto composingVariables = separateComposingVariables(variables, description); + Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the user config"; loadConfig(mFixedPath.getUserConfigPath(), variables, description); + mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); // read either local or global config depending on type of installation + composingVariables = separateComposingVariables(variables, description); + Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the local config"; bool loaded = loadConfig(mFixedPath.getLocalPath(), variables, description); + mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); if (!loaded) { + composingVariables = separateComposingVariables(variables, description); + Log(Debug::Info) << composingVariables.size() << " composing variables were loaded before the global config"; loadConfig(mFixedPath.getGlobalConfigPath(), variables, description); + mergeComposingVariables(variables, composingVariables, description); boost::program_options::notify(variables); } mSilent = silent; } +boost::program_options::variables_map ConfigurationManager::separateComposingVariables(boost::program_options::variables_map & variables, boost::program_options::options_description& description) +{ + boost::program_options::variables_map composingVariables; + for (auto itr = variables.begin(); itr != variables.end();) + { + if (description.find((*itr).first, false).semantic()->is_composing()) + { + composingVariables.emplace(*itr); + itr = variables.erase(itr); + } + else + ++itr; + } + return composingVariables; +} + +void ConfigurationManager::mergeComposingVariables(boost::program_options::variables_map & first, boost::program_options::variables_map & second, boost::program_options::options_description& description) +{ + for (auto& [name, variableValue] : first) + { + if (description.find(name, false).semantic()->is_composing()) + { + if (second[name].defaulted() || second[name].empty()) + continue; + + boost::any& firstValue = variableValue.value(); + const boost::any& secondValue = second[name].value(); + + if (firstValue.type() == typeid(Files::EscapePathContainer)) + { + auto& firstPathContainer = boost::any_cast(firstValue); + const auto& secondPathContainer = boost::any_cast(secondValue); + + firstPathContainer.insert(firstPathContainer.end(), secondPathContainer.begin(), secondPathContainer.end()); + } + else if (firstValue.type() == typeid(Fallback::FallbackMap)) + { + auto& firstMap = boost::any_cast(firstValue); + const auto& secondMap = boost::any_cast(secondValue); + + std::map tempMap(secondMap.mMap); + tempMap.merge(firstMap.mMap); + firstMap.mMap.swap(tempMap); + } + else + Log(Debug::Error) << "Unexpected composing variable type. Curse boost and their blasted arcane templates."; + } + } + +} + void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool create) { std::string path; diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 446abd4dc5..0ec0a1f67d 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -25,6 +25,10 @@ struct ConfigurationManager void readConfiguration(boost::program_options::variables_map& variables, boost::program_options::options_description& description, bool quiet=false); + boost::program_options::variables_map separateComposingVariables(boost::program_options::variables_map& variables, boost::program_options::options_description& description); + + void mergeComposingVariables(boost::program_options::variables_map& first, boost::program_options::variables_map& second, boost::program_options::options_description& description); + void processPaths(Files::PathContainer& dataDirs, bool create = false); ///< \param create Try creating the directory, if it does not exist.