macOS: Stop storing user data in Documents for some users; fix symlinks (#6241)
* macOS: Stop storing user data in Documents for some users; fix symlinks * Use SupportedOSPlatform tag, catch exceptions, log warning instead of error * Provide best path hints to user if symlink fixup fails --------- Co-authored-by: jcm <butt@butts.com>
This commit is contained in:
parent
baf94e0e3e
commit
946633276b
3 changed files with 92 additions and 12 deletions
|
@ -2,6 +2,7 @@ using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
|
|
||||||
namespace Ryujinx.Common.Configuration
|
namespace Ryujinx.Common.Configuration
|
||||||
{
|
{
|
||||||
|
@ -95,18 +96,9 @@ namespace Ryujinx.Common.Configuration
|
||||||
|
|
||||||
BaseDirPath = Path.GetFullPath(BaseDirPath); // convert relative paths
|
BaseDirPath = Path.GetFullPath(BaseDirPath); // convert relative paths
|
||||||
|
|
||||||
// NOTE: Moves the Ryujinx folder in `~/.config` to `~/Library/Application Support` if one is found
|
if (IsPathSymlink(BaseDirPath))
|
||||||
// and a Ryujinx folder does not already exist in Application Support.
|
|
||||||
// Also creates a symlink from `~/.config/Ryujinx` to `~/Library/Application Support/Ryujinx` to preserve backwards compatibility.
|
|
||||||
// This should be removed in the future.
|
|
||||||
if (OperatingSystem.IsMacOS() && Mode == LaunchMode.UserProfile)
|
|
||||||
{
|
{
|
||||||
string oldConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir);
|
Logger.Warning?.Print(LogClass.Application, $"Application data directory is a symlink. This may be unintended.");
|
||||||
if (Path.Exists(oldConfigPath) && !IsPathSymlink(oldConfigPath) && !Path.Exists(BaseDirPath))
|
|
||||||
{
|
|
||||||
FileSystemUtils.MoveDirectory(oldConfigPath, BaseDirPath);
|
|
||||||
Directory.CreateSymbolicLink(oldConfigPath, BaseDirPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupBasePaths();
|
SetupBasePaths();
|
||||||
|
@ -245,6 +237,82 @@ namespace Ryujinx.Common.Configuration
|
||||||
return (attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
|
return (attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SupportedOSPlatform("macos")]
|
||||||
|
public static void FixMacOSConfigurationFolders()
|
||||||
|
{
|
||||||
|
string oldConfigPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
|
||||||
|
".config", DefaultBaseDir);
|
||||||
|
if (Path.Exists(oldConfigPath) && !IsPathSymlink(oldConfigPath) && !Path.Exists(BaseDirPath))
|
||||||
|
{
|
||||||
|
FileSystemUtils.MoveDirectory(oldConfigPath, BaseDirPath);
|
||||||
|
Directory.CreateSymbolicLink(oldConfigPath, BaseDirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
string correctApplicationDataDirectoryPath =
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), DefaultBaseDir);
|
||||||
|
if (IsPathSymlink(correctApplicationDataDirectoryPath))
|
||||||
|
{
|
||||||
|
//copy the files somewhere temporarily
|
||||||
|
string tempPath = Path.Combine(Path.GetTempPath(), DefaultBaseDir);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileSystemUtils.CopyDirectory(correctApplicationDataDirectoryPath, tempPath, true);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application,
|
||||||
|
$"Critical error copying Ryujinx application data into the temp folder. {exception}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileSystemInfo resolvedDirectoryInfo =
|
||||||
|
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
|
||||||
|
string resolvedPath = resolvedDirectoryInfo.FullName;
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
|
||||||
|
}
|
||||||
|
catch (Exception symlinkException)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//delete the symlink
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//This will fail if this is an actual directory, so there is no way we can actually delete user data here.
|
||||||
|
File.Delete(correctApplicationDataDirectoryPath);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application,
|
||||||
|
$"Critical error deleting the Ryujinx application data folder symlink at {correctApplicationDataDirectoryPath}. {exception}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileSystemInfo resolvedDirectoryInfo =
|
||||||
|
Directory.ResolveLinkTarget(correctApplicationDataDirectoryPath, true);
|
||||||
|
string resolvedPath = resolvedDirectoryInfo.FullName;
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Please manually move your Ryujinx data from {resolvedPath} to {correctApplicationDataDirectoryPath}, and remove the symlink.");
|
||||||
|
}
|
||||||
|
catch (Exception symlinkException)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Unable to resolve the symlink for Ryujinx application data: {symlinkException}. Follow the symlink at {correctApplicationDataDirectoryPath} and move your data back to the Application Support folder.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//put the files back
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileSystemUtils.CopyDirectory(tempPath, correctApplicationDataDirectoryPath, true);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application,
|
||||||
|
$"Critical error copying Ryujinx application data into the correct location. {exception}. Please manually move your application data from {tempPath} to {correctApplicationDataDirectoryPath}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetModsPath() => CustomModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultModsDir)).FullName;
|
public static string GetModsPath() => CustomModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultModsDir)).FullName;
|
||||||
public static string GetSdModsPath() => CustomSdModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultSdcardDir, "atmosphere")).FullName;
|
public static string GetSdModsPath() => CustomSdModsPath ?? Directory.CreateDirectory(Path.Combine(BaseDirPath, DefaultSdcardDir, "atmosphere")).FullName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace Ryujinx.UI.Common.Configuration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current version of the file format
|
/// The current version of the file format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int CurrentVersion = 48;
|
public const int CurrentVersion = 49;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the configuration file format
|
/// Version of the configuration file format
|
||||||
|
|
|
@ -1430,6 +1430,18 @@ namespace Ryujinx.UI.Common.Configuration
|
||||||
configurationFileUpdated = true;
|
configurationFileUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (configurationFileFormat.Version < 49)
|
||||||
|
{
|
||||||
|
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 49.");
|
||||||
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
AppDataManager.FixMacOSConfigurationFolders();
|
||||||
|
}
|
||||||
|
|
||||||
|
configurationFileUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
||||||
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
||||||
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
||||||
|
|
Reference in a new issue