From fc161e757c14a0d0b86e69fb5ec631fae8b448de Mon Sep 17 00:00:00 2001 From: Jude Melton-Houghton Date: Thu, 27 Jan 2022 16:24:30 -0500 Subject: [PATCH] Automatically migrate client mod storage (#11960) --- src/client/client.cpp | 28 ++++++++++++++++++++++++++++ src/client/client.h | 3 +++ src/client/game.cpp | 17 ++++++++++++----- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index d4c271bab..935a82653 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientmap.h" #include "clientmedia.h" #include "version.h" +#include "database/database-files.h" #include "database/database-sqlite3.h" #include "serialization.h" #include "guiscalingfilter.h" @@ -140,6 +141,33 @@ Client::Client( m_cache_save_interval = g_settings->getU16("server_map_save_interval"); } +void Client::migrateModStorage() +{ + std::string mod_storage_dir = porting::path_user + DIR_DELIM + "client"; + std::string old_mod_storage = mod_storage_dir + DIR_DELIM + "mod_storage"; + if (fs::IsDir(old_mod_storage)) { + infostream << "Migrating client mod storage to SQLite3 database" << std::endl; + { + ModMetadataDatabaseFiles files_db(mod_storage_dir); + std::vector mod_list; + files_db.listMods(&mod_list); + for (const std::string &modname : mod_list) { + infostream << "Migrating client mod storage for mod " << modname << std::endl; + StringMap meta; + files_db.getModEntries(modname, &meta); + for (const auto &pair : meta) { + m_mod_storage_database->setModEntry(modname, pair.first, pair.second); + } + } + } + if (!fs::Rename(old_mod_storage, old_mod_storage + ".bak")) { + // Execution cannot move forward if the migration does not complete. + throw BaseException("Could not finish migrating client mod storage"); + } + infostream << "Finished migration of client mod storage" << std::endl; + } +} + void Client::loadMods() { // Don't load mods twice. diff --git a/src/client/client.h b/src/client/client.h index 694cd7d1b..84c85471d 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -385,6 +385,9 @@ public: bool registerModStorage(ModMetadata *meta) override; void unregisterModStorage(const std::string &name) override; + // Migrates away old files-based mod storage if necessary + void migrateModStorage(); + // The following set of functions is used by ClientMediaDownloader // Insert a media file appropriately into the appropriate manager bool loadMedia(const std::string &data, const std::string &filename, diff --git a/src/client/game.cpp b/src/client/game.cpp index b6052390b..7478e225f 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1466,11 +1466,18 @@ bool Game::connectToServer(const GameStartData &start_data, return false; } - client = new Client(start_data.name.c_str(), - start_data.password, start_data.address, - *draw_control, texture_src, shader_src, - itemdef_manager, nodedef_manager, sound, eventmgr, - m_rendering_engine, connect_address.isIPv6(), m_game_ui.get()); + try { + client = new Client(start_data.name.c_str(), + start_data.password, start_data.address, + *draw_control, texture_src, shader_src, + itemdef_manager, nodedef_manager, sound, eventmgr, + m_rendering_engine, connect_address.isIPv6(), m_game_ui.get()); + client->migrateModStorage(); + } catch (const BaseException &e) { + *error_message = fmtgettext("Error creating client: %s", e.what()); + errorstream << *error_message << std::endl; + return false; + } client->m_simple_singleplayer_mode = simple_singleplayer_mode;