Browse Source

add unlink check

Signed-off-by: crueter <crueter@eden-emu.dev>
pull/2815/head
crueter 3 months ago
parent
commit
eed68a221e
  1. 2
      src/common/fs/symlink.cpp
  2. 82
      src/qt_common/util/fs.cpp
  3. 10
      src/qt_common/util/fs.h
  4. 21
      src/yuzu/main.cpp
  5. 10
      src/yuzu/ryujinx_dialog.cpp
  6. 5
      src/yuzu/ryujinx_dialog.h

2
src/common/fs/symlink.cpp

@ -36,7 +36,7 @@ bool IsSymlink(const fs::path &path)
#ifdef _WIN32
return fs::status(path).type() == fs::file_type::junction;
#else
return fs::status(path).type() == fs::file_type::symlink;
return fs::is_symlink(path);
#endif
}

82
src/qt_common/util/fs.cpp

@ -1,9 +1,11 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <filesystem>
#include "fs.h"
#include "common/fs/ryujinx_compat.h"
#include "common/fs/symlink.h"
#include "frontend_common/data_manager.h"
#include "qt_common/abstract/frontend.h"
#include "qt_common/qt_string_lookup.h"
@ -11,7 +13,8 @@ namespace fs = std::filesystem;
namespace QtCommon::FS {
void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to) {
void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to)
{
std::error_code ec;
// "ignore" errors--if the dir fails to be deleted, error handling later will handle it
@ -20,11 +23,63 @@ void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to) {
if (Common::FS::CreateSymlink(from, to)) {
QtCommon::Frontend::Information(tr("Linked Save Data"), tr("Save data has been linked."));
} else {
QtCommon::Frontend::Critical(tr("Failed to link save data"),
tr("Could not link directory:\n\t%1\nTo:\n\t%2")
.arg(QString::fromStdString(from.string()),
QString::fromStdString(to.string())));
QtCommon::Frontend::Critical(
tr("Failed to link save data"),
tr("Could not link directory:\n\t%1\nTo:\n\t%2").arg(QString::fromStdString(from.string()), QString::fromStdString(to.string())));
}
}
bool CheckUnlink(const fs::path &eden_dir, const fs::path &ryu_dir)
{
bool eden_link = Common::FS::IsSymlink(eden_dir);
bool ryu_link = Common::FS::IsSymlink(ryu_dir);
if (!(eden_link || ryu_link))
return false;
auto result = QtCommon::Frontend::Warning(
tr("Already Linked"),
tr("This title is already linked to Ryujinx. Would you like to unlink it?"),
QtCommon::Frontend::StandardButton::Yes | QtCommon::Frontend::StandardButton::No);
if (result != QtCommon::Frontend::StandardButton::Yes)
return true;
fs::path linked;
fs::path orig;
if (eden_link) {
linked = eden_dir;
orig = ryu_dir;
} else {
linked = ryu_dir;
orig = eden_dir;
}
// first cleanup the symlink/junction,
try {
fs::remove_all(linked);
} catch (std::exception &e) {
QtCommon::Frontend::Critical(
tr("Failed to unlink old directory"),
tr("OS returned error: %1").arg(QString::fromStdString(e.what())));
return true;
}
// then COPY the other dir
try {
fs::copy(orig, linked, fs::copy_options::recursive);
} catch (std::exception &e) {
QtCommon::Frontend::Critical(
tr("Failed to copy save data"),
tr("OS returned error: %1").arg(QString::fromStdString(e.what())));
}
QtCommon::Frontend::Information(
tr("Unlink Successful"),
tr("Successfully unlinked Ryujinx save data. Save data has been kept intact."));
return true;
}
u64 GetRyujinxSaveID(const u64 &program_id)
@ -53,4 +108,21 @@ u64 GetRyujinxSaveID(const u64 &program_id)
return -1;
}
std::optional<std::pair<fs::path, fs::path> > GetEmuPaths(
const u64 program_id, const u64 save_id, const std::string &user_id)
{
fs::path ryu_dir = Common::FS::GetRyuSavePath(save_id);
if (user_id.empty())
return std::nullopt;
std::string hex_program = fmt::format("{:016X}", program_id);
fs::path eden_dir
= FrontendCommon::DataManager::GetDataDir(FrontendCommon::DataManager::DataDir::Saves,
user_id)
/ hex_program;
return std::make_pair(eden_dir, ryu_dir);
}
} // namespace QtCommon::FS

10
src/qt_common/util/fs.h

@ -3,12 +3,20 @@
#include "common/common_types.h"
#include <filesystem>
#include <optional>
#pragma once
namespace QtCommon::FS {
void LinkRyujinx(std::filesystem::path &from, std::filesystem::path &to);
u64 GetRyujinxSaveID(const u64& program_id);
u64 GetRyujinxSaveID(const u64 &program_id);
/// @brief {eden, ryu}
std::optional<std::pair<std::filesystem::path, std::filesystem::path>> GetEmuPaths(
const u64 program_id, const u64 save_id, const std::string &user_id);
/// returns FALSE if the dirs are NOT linked
bool CheckUnlink(const std::filesystem::path &eden_dir, const std::filesystem::path &ryu_dir);
} // namespace QtCommon::FS

21
src/yuzu/main.cpp

@ -2917,22 +2917,23 @@ std::string GMainWindow::GetProfileID()
void GMainWindow::OnLinkToRyujinx(const u64& program_id)
{
namespace fs = std::filesystem;
u64 save_id = QtCommon::FS::GetRyujinxSaveID(program_id);
if (save_id == (u64) -1)
return;
fs::path ryu_dir = Common::FS::GetRyuSavePath(save_id);
std::string user_id = GetProfileID();
if (user_id.empty())
const std::string user_id = GetProfileID();
auto paths = QtCommon::FS::GetEmuPaths(program_id, save_id, user_id);
if (!paths)
return;
std::string hex_program = fmt::format("{:016X}", program_id);
fs::path eden_dir = FrontendCommon::DataManager::GetDataDir(FrontendCommon::DataManager::DataDir::Saves, user_id)
/ hex_program;
RyujinxDialog dialog(eden_dir, ryu_dir, this);
dialog.exec();
auto eden_dir = paths.value().first;
auto ryu_dir = paths.value().second;
if (!QtCommon::FS::CheckUnlink(eden_dir, ryu_dir)) {
RyujinxDialog dialog(eden_dir, ryu_dir, this);
dialog.exec();
}
}
void GMainWindow::OnMenuLoadFile() {

10
src/yuzu/ryujinx_dialog.cpp

@ -5,7 +5,6 @@
#include "qt_common/util/fs.h"
#include "ui_ryujinx_dialog.h"
#include <filesystem>
#include <fmt/format.h>
namespace fs = std::filesystem;
@ -31,16 +30,11 @@ RyujinxDialog::~RyujinxDialog()
void RyujinxDialog::fromEden()
{
accept();
link(m_eden, m_ryu);
QtCommon::FS::LinkRyujinx(m_eden, m_ryu);
}
void RyujinxDialog::fromRyujinx()
{
accept();
link(m_ryu, m_eden);
}
void RyujinxDialog::link(std::filesystem::path &from, std::filesystem::path &to)
{
QtCommon::FS::LinkRyujinx(from, to);
QtCommon::FS::LinkRyujinx(m_ryu, m_eden);
}

5
src/yuzu/ryujinx_dialog.h

@ -27,11 +27,6 @@ private:
Ui::RyujinxDialog *ui;
std::filesystem::path m_eden;
std::filesystem::path m_ryu;
/// @brief Link two directories
/// @param from The symlink target
/// @param to The symlink name (will be deleted)
void link(std::filesystem::path &from, std::filesystem::path &to);
};
#endif // RYUJINX_DIALOG_H
Loading…
Cancel
Save