mirror of
https://github.com/Lime3DS/Lime3DS
synced 2024-12-24 08:02:48 -06:00
Implement emulator data migration functionality + prompt
The migration prompt appears when Lime3DS is started while the new user data directory doesn't exist and the old directory *does* exist
This commit is contained in:
parent
d2a5260d62
commit
7731956906
5 changed files with 80 additions and 4 deletions
|
@ -19,17 +19,22 @@
|
|||
#else
|
||||
#ifdef _WIN32
|
||||
#define EMU_DATA_DIR "Lime3DS"
|
||||
#define LEGACY_EMU_DATA_DIR "Citra"
|
||||
#elif defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#if TARGET_OS_IPHONE // TODO: Kill iOS
|
||||
#define APPLE_EMU_DATA_DIR "Documents" DIR_SEP "Lime3DS"
|
||||
#define LEGACY_APPLE_EMU_DATA_DIR "Documents" DIR_SEP "Citra"
|
||||
#else
|
||||
#define APPLE_EMU_DATA_DIR "Library" DIR_SEP "Application Support" DIR_SEP "Lime3DS"
|
||||
#define LEGACY_APPLE_EMU_DATA_DIR "Library" DIR_SEP "Application Support" DIR_SEP "Citra"
|
||||
#endif
|
||||
// For compatibility with XDG paths.
|
||||
#define EMU_DATA_DIR "lime3ds-emu"
|
||||
#define LEGACY_EMU_DATA_DIR "citra-emu"
|
||||
#else
|
||||
#define EMU_DATA_DIR "lime3ds-emu"
|
||||
#define LEGACY_EMU_DATA_DIR "citra-emu"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -771,8 +771,11 @@ void SetUserPath(const std::string& path) {
|
|||
} else {
|
||||
#ifdef _WIN32
|
||||
user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
|
||||
std::string& legacy_user_path = g_paths[UserPath::LegacyUserDir];
|
||||
|
||||
if (!FileUtil::IsDirectory(user_path)) {
|
||||
user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||
legacy_user_path = AppDataRoamingDirectory() + DIR_SEP LEGACY_EMU_DATA_DIR DIR_SEP;
|
||||
} else {
|
||||
LOG_INFO(Common_Filesystem, "Using the local user directory");
|
||||
}
|
||||
|
@ -784,6 +787,7 @@ void SetUserPath(const std::string& path) {
|
|||
g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
|
||||
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
|
||||
#else
|
||||
std::string& legacy_user_path = g_paths[UserPath::LegacyUserDir];
|
||||
auto current_dir = FileUtil::GetCurrentDir();
|
||||
if (current_dir.has_value() &&
|
||||
FileUtil::Exists(current_dir.value() + USERDATA_DIR DIR_SEP)) {
|
||||
|
@ -792,10 +796,16 @@ void SetUserPath(const std::string& path) {
|
|||
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
|
||||
} else {
|
||||
std::string data_dir = GetUserDirectory("XDG_DATA_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||
std::string legacy_data_dir =
|
||||
GetUserDirectory("XDG_DATA_HOME") + DIR_SEP LEGACY_EMU_DATA_DIR DIR_SEP;
|
||||
std::string config_dir =
|
||||
GetUserDirectory("XDG_CONFIG_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||
std::string cache_dir =
|
||||
GetUserDirectory("XDG_CACHE_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||
g_paths.emplace(UserPath::LegacyConfigDir, GetUserDirectory("XDG_CONFIG_HOME") +
|
||||
DIR_SEP LEGACY_EMU_DATA_DIR DIR_SEP);
|
||||
g_paths.emplace(UserPath::LegacyCacheDir, GetUserDirectory("XDG_CACHE_HOME") +
|
||||
DIR_SEP LEGACY_EMU_DATA_DIR DIR_SEP);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// If XDG directories don't already exist from a previous setup, use standard macOS
|
||||
|
@ -803,12 +813,14 @@ void SetUserPath(const std::string& path) {
|
|||
if (!FileUtil::Exists(data_dir) && !FileUtil::Exists(config_dir) &&
|
||||
!FileUtil::Exists(cache_dir)) {
|
||||
data_dir = GetHomeDirectory() + DIR_SEP APPLE_EMU_DATA_DIR DIR_SEP;
|
||||
legacy_data_dir = GetHomeDirectory() + DIR_SEP LEGACY_APPLE_EMU_DATA_DIR DIR_SEP;
|
||||
config_dir = data_dir + CONFIG_DIR DIR_SEP;
|
||||
cache_dir = data_dir + CACHE_DIR DIR_SEP;
|
||||
}
|
||||
#endif
|
||||
|
||||
user_path = data_dir;
|
||||
legacy_user_path = legacy_data_dir;
|
||||
g_paths.emplace(UserPath::ConfigDir, config_dir);
|
||||
g_paths.emplace(UserPath::CacheDir, cache_dir);
|
||||
}
|
||||
|
|
|
@ -32,17 +32,20 @@ enum class UserPath {
|
|||
ConfigDir,
|
||||
DLLDir,
|
||||
DumpDir,
|
||||
IconsDir,
|
||||
LegacyCacheDir, // LegacyCacheDir and LegacyConfigDir are only defined if migrating these
|
||||
LegacyConfigDir, // directories is necessary (aka not a child of LegacyUserDir)
|
||||
LegacyUserDir,
|
||||
LoadDir,
|
||||
LogDir,
|
||||
NANDDir,
|
||||
PlayTimeDir,
|
||||
RootDir,
|
||||
SDMCDir,
|
||||
ShaderDir,
|
||||
StatesDir,
|
||||
SysDataDir,
|
||||
UserDir,
|
||||
IconsDir,
|
||||
PlayTimeDir,
|
||||
};
|
||||
|
||||
// Replaces install-specific paths with standard placeholders, and back again
|
||||
|
|
|
@ -159,12 +159,16 @@ static QString PrettyProductName() {
|
|||
|
||||
GMainWindow::GMainWindow(Core::System& system_)
|
||||
: ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{system.Movie()},
|
||||
config{std::make_unique<Config>()}, emu_thread{nullptr} {
|
||||
emu_thread{nullptr} {
|
||||
Common::Log::Initialize();
|
||||
Common::Log::Start();
|
||||
|
||||
Debugger::ToggleConsole();
|
||||
|
||||
CheckForMigration();
|
||||
|
||||
this->config = std::make_unique<Config>();
|
||||
|
||||
#ifdef __unix__
|
||||
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
|
||||
#endif
|
||||
|
@ -1099,6 +1103,55 @@ void GMainWindow::ShowUpdaterWidgets() {
|
|||
}
|
||||
#endif
|
||||
|
||||
void GMainWindow::CheckForMigration() {
|
||||
namespace fs = std::filesystem;
|
||||
if (fs::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::LegacyUserDir)) &&
|
||||
!fs::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::UserDir))) {
|
||||
if (QMessageBox::information(
|
||||
this, tr("Migration"),
|
||||
tr("Lime3DS has moved to a new data directory.\n\n"
|
||||
"Would you like to migrate your Citra data to this new "
|
||||
"location?\n"
|
||||
"(This may take a while; The old data will not be deleted)"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
|
||||
MigrateUserData();
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Migration"),
|
||||
tr("You can manually re-trigger this prompt by deleting the "
|
||||
"new user data directory:\n"
|
||||
"%1")
|
||||
.arg(QString::fromStdString(
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::UserDir))),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::MigrateUserData() {
|
||||
namespace fs = std::filesystem;
|
||||
const auto copyOptions = fs::copy_options::update_existing | fs::copy_options::recursive;
|
||||
|
||||
fs::copy(FileUtil::GetUserPath(FileUtil::UserPath::LegacyUserDir),
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::UserDir), copyOptions);
|
||||
if (fs::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::LegacyConfigDir))) {
|
||||
fs::copy(FileUtil::GetUserPath(FileUtil::UserPath::LegacyConfigDir),
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir), copyOptions);
|
||||
}
|
||||
if (fs::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::LegacyCacheDir))) {
|
||||
fs::copy(FileUtil::GetUserPath(FileUtil::UserPath::LegacyCacheDir),
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::CacheDir), copyOptions);
|
||||
}
|
||||
|
||||
QMessageBox::information(
|
||||
this, tr("Migration"),
|
||||
tr("Data was migrated successfully. Lime3DS will now start.\n\n"
|
||||
"If you wish to clean up the files which were left in the old data location, you can do "
|
||||
"so by deleting the following directory:\n"
|
||||
"%1")
|
||||
.arg(QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LegacyUserDir))),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
|
||||
#if defined(HAVE_SDL2) && defined(__unix__) && !defined(__APPLE__)
|
||||
static std::optional<QDBusObjectPath> HoldWakeLockLinux(u32 window_id = 0) {
|
||||
if (!QDBusConnection::sessionBus().isConnected()) {
|
||||
|
|
|
@ -171,6 +171,9 @@ private:
|
|||
void CheckForUpdates();
|
||||
#endif
|
||||
|
||||
void CheckForMigration();
|
||||
void MigrateUserData();
|
||||
|
||||
/**
|
||||
* Stores the filename in the recently loaded files list.
|
||||
* The new filename is stored at the beginning of the recently loaded files list.
|
||||
|
|
Loading…
Reference in a new issue