diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index b814da18ff..4101c4ef54 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -30,18 +30,10 @@ ConfigurationManager::ConfigurationManager(bool silent) { setupTokensMapping(); - boost::filesystem::create_directories(mFixedPath.getUserConfigPath()); - boost::filesystem::create_directories(mFixedPath.getUserDataPath()); - + // Initialize with fixed paths, will be overridden in `readConfiguration`. mLogPath = mFixedPath.getUserConfigPath(); - + mUserDataPath = mFixedPath.getUserDataPath(); mScreenshotPath = mFixedPath.getUserDataPath() / "screenshots"; - - // probably not necessary but validate the creation of the screenshots directory and fallback to the original behavior if it fails - boost::system::error_code dirErr; - if (!boost::filesystem::create_directories(mScreenshotPath, dirErr) && !boost::filesystem::is_directory(mScreenshotPath)) { - mScreenshotPath = mFixedPath.getUserDataPath(); - } } ConfigurationManager::~ConfigurationManager() @@ -114,6 +106,30 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m } mLogPath = mActiveConfigPaths.back(); + mUserDataPath = variables["user-data"].as(); + if (mUserDataPath.empty()) + { + if (!quiet) + Log(Debug::Warning) << "Error: `user-data` is not specified"; + mUserDataPath = mFixedPath.getUserDataPath(); + } + processPath(mUserDataPath, true); + mScreenshotPath = mUserDataPath / "screenshots"; + + boost::filesystem::create_directories(getUserConfigPath()); + boost::filesystem::create_directories(mScreenshotPath); + + // probably not necessary but validate the creation of the screenshots directory and fallback to the original behavior if it fails + if (!boost::filesystem::is_directory(mScreenshotPath)) + mScreenshotPath = mUserDataPath; + + if (!quiet) + { + Log(Debug::Info) << "Logs dir: " << getUserConfigPath().string(); + Log(Debug::Info) << "User data dir: " << mUserDataPath.string(); + Log(Debug::Info) << "Screenshots dir: " << mScreenshotPath.string(); + } + mSilent = silent; } @@ -141,8 +157,9 @@ void ConfigurationManager::addExtraConfigDirs(std::stack()->default_value(Files::MaybeQuotedPathContainer(), "config") - ->multitoken()->composing(), "additional config directories"); + ("config", bpo::value()->multitoken()->composing(), "additional config directories") + ("user-data", bpo::value(), + "set user data directory (used for saves, screenshots, etc)"); } boost::program_options::variables_map separateComposingVariables(boost::program_options::variables_map & variables, @@ -230,54 +247,57 @@ void mergeComposingVariables(boost::program_options::variables_map& first, boost boost::program_options::notify(first); } -void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool create) const +void ConfigurationManager::processPath(boost::filesystem::path& path, bool create) const { - std::string path; - for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) - { - path = it->string(); + std::string str = path.string(); + + // Do nothing if the path doesn't start with a token + if (str.empty() || str[0] != '?') + return; - // Check if path contains a token - if (!path.empty() && *path.begin() == '?') + std::string::size_type pos = str.find('?', 1); + if (pos != std::string::npos && pos != 0) + { + auto tokenIt = mTokensMapping.find(str.substr(0, pos + 1)); + if (tokenIt != mTokensMapping.end()) { - std::string::size_type pos = path.find('?', 1); - if (pos != std::string::npos && pos != 0) + boost::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))()); + if (pos < str.length() - 1) { - auto tokenIt = mTokensMapping.find(path.substr(0, pos + 1)); - if (tokenIt != mTokensMapping.end()) - { - boost::filesystem::path tempPath(((mFixedPath).*(tokenIt->second))()); - if (pos < path.length() - 1) - { - // There is something after the token, so we should - // append it to the path - tempPath /= path.substr(pos + 1, path.length() - pos); - } - - *it = tempPath; - } - else - { - // Clean invalid / unknown token, it will be removed outside the loop - (*it).clear(); - } + // There is something after the token, so we should + // append it to the path + tempPath /= str.substr(pos + 1, str.length() - pos); } + + path = tempPath; + } + else + { + if (!mSilent) + Log(Debug::Warning) << "Path starts with unknown token: " << path; + path.clear(); } + } - if (!boost::filesystem::is_directory(*it)) + if (!boost::filesystem::is_directory(path) && create) + { + try { - if (create) - { - try - { - boost::filesystem::create_directories (*it); - } - catch (...) {} - - if (boost::filesystem::is_directory(*it)) - continue; - } + boost::filesystem::create_directories(path); + } + catch (...) {} + } +} +void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool create) const +{ + for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) + { + processPath(*it, create); + if (!boost::filesystem::is_directory(*it)) + { + if (!mSilent) + Log(Debug::Warning) << "No such dir: " << *it; (*it).clear(); } } @@ -322,7 +342,7 @@ const boost::filesystem::path& ConfigurationManager::getUserConfigPath() const const boost::filesystem::path& ConfigurationManager::getUserDataPath() const { - return mFixedPath.getUserDataPath(); + return mUserDataPath; } const boost::filesystem::path& ConfigurationManager::getLocalPath() const diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index fcbb0d5ff5..49844cca41 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -27,6 +27,7 @@ struct ConfigurationManager void readConfiguration(boost::program_options::variables_map& variables, boost::program_options::options_description& description, bool quiet=false); + void processPath(boost::filesystem::path& path, bool create = false) const; void processPaths(Files::PathContainer& dataDirs, bool create = false) const; ///< \param create Try creating the directory, if it does not exist. @@ -70,6 +71,7 @@ struct ConfigurationManager FixedPathType mFixedPath; boost::filesystem::path mLogPath; + boost::filesystem::path mUserDataPath; boost::filesystem::path mScreenshotPath; TokensMappingContainer mTokensMapping; diff --git a/files/openmw.cfg b/files/openmw.cfg index 7bd70c3e5e..d1ecd6f8a3 100644 --- a/files/openmw.cfg +++ b/files/openmw.cfg @@ -4,6 +4,7 @@ content=builtin.omwscripts data-local="?userdata?data" +user-data="?userdata?" config="?userconfig?" resources=${OPENMW_RESOURCE_FILES} script-blacklist=Museum diff --git a/files/openmw.cfg.local b/files/openmw.cfg.local index 79ab9e6156..f928113002 100644 --- a/files/openmw.cfg.local +++ b/files/openmw.cfg.local @@ -4,6 +4,7 @@ content=builtin.omwscripts data-local="?userdata?data" +user-data="?userdata?" config="?userconfig?" resources=./resources script-blacklist=Museum