]> git.lizzy.rs Git - minetest.git/commitdiff
Automatically migrate client mod storage (#11960)
authorJude Melton-Houghton <jwmhjwmh@gmail.com>
Thu, 27 Jan 2022 21:24:30 +0000 (16:24 -0500)
committerGitHub <noreply@github.com>
Thu, 27 Jan 2022 21:24:30 +0000 (22:24 +0100)
src/client/client.cpp
src/client/client.h
src/client/game.cpp

index d4c271baba8f54a1a02b82b349148ac592052629..935a826532f2001f6f1cb1c4b386f231280e3654 100644 (file)
@@ -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<std::string> 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.
index 694cd7d1b05153351d09825384edff5e33821b4a..84c85471daefd87fccabe924d9b27bd2172d3d79 100644 (file)
@@ -385,6 +385,9 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
        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,
index b6052390b40fa7297c9beae7ebe43251261dab74..7478e225fa5acc0d0215040a1aac81273c16122c 100644 (file)
@@ -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;