From d6a7917fe1f2d43e60a989d45d0f22ec0b0b3d15 Mon Sep 17 00:00:00 2001 From: Sewer56 Date: Thu, 3 Oct 2024 09:07:46 +0100 Subject: [PATCH 1/3] Improved: Uninstalling now deletes whole standard local application data folder (NexusMods.App), in addition to used directories from config --- src/NexusMods.App/Commandline/CleanupVerbs.cs | 5 +- src/NexusMods.DataModel/DataModelSettings.cs | 50 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/NexusMods.App/Commandline/CleanupVerbs.cs b/src/NexusMods.App/Commandline/CleanupVerbs.cs index 38bdb48cc4..97d306e22d 100644 --- a/src/NexusMods.App/Commandline/CleanupVerbs.cs +++ b/src/NexusMods.App/Commandline/CleanupVerbs.cs @@ -91,11 +91,14 @@ are other than {##}. Resolving these on our end would be hard. // switching backends out. At that point you'd add others here too. JsonStorageBackend.GetConfigsFolderPath(fileSystem), - // The whole base DataModel folder. + // The DataModel folder. DataModelSettings.GetStandardDataModelFolder(fileSystem), // The whole base Download folder. DownloadSettings.GetStandardDownloadsFolder(fileSystem), + + // Local Application Data (where all app files default to). + DataModelSettings.GetLocalApplicationDataDirectory(fileSystem), }.Concat(dataModelSettings.ArchiveLocations.Select(path => path.ToPath(fileSystem))); if (fileSystem.OS.IsUnix()) diff --git a/src/NexusMods.DataModel/DataModelSettings.cs b/src/NexusMods.DataModel/DataModelSettings.cs index c02584095c..b5534f133c 100644 --- a/src/NexusMods.DataModel/DataModelSettings.cs +++ b/src/NexusMods.DataModel/DataModelSettings.cs @@ -11,6 +11,8 @@ namespace NexusMods.DataModel; [PublicAPI] public record DataModelSettings : ISettings { + private const string DataModelFolderName = "DataModel"; + /// /// If true, data model will be stored in memory only and the paths will be ignored. /// @@ -40,30 +42,27 @@ public static ISettingsBuilder Configure(ISettingsBuilder settingsBuilder) public static DataModelSettings CreateDefault(IServiceProvider serviceProvider) { var os = serviceProvider.GetRequiredService().OS; - var baseKnownPath = GetStandardDataModelPaths(os, out var baseDirectoryName); + var baseKnownPath = GetLocalApplicationDataDirectory(os, out var baseDirectoryName); return new DataModelSettings { - MnemonicDBPath = new ConfigurablePath(baseKnownPath, $"{baseDirectoryName}/MnemonicDB.rocksdb"), + MnemonicDBPath = new ConfigurablePath(baseKnownPath, $"{baseDirectoryName}/{DataModelFolderName}/MnemonicDB.rocksdb"), ArchiveLocations = [ - new ConfigurablePath(baseKnownPath, $"{baseDirectoryName}/Archives"), + new ConfigurablePath(baseKnownPath, $"{baseDirectoryName}/{DataModelFolderName}/Archives"), ], }; } - private static KnownPath GetStandardDataModelPaths(IOSInformation os, out string baseDirectoryName) + /// + /// Retrieves the base directory where the App stores its local application data. + /// + /// The absolute path to the local application data directory. + public static AbsolutePath GetLocalApplicationDataDirectory(IFileSystem fs) { - var baseKnownPath = os.MatchPlatform( - onWindows: () => KnownPath.LocalApplicationDataDirectory, - onLinux: () => KnownPath.XDG_DATA_HOME, - onOSX: () => KnownPath.LocalApplicationDataDirectory - ); - - // NOTE: OSX ".App" is apparently special, using _ instead of . to prevent weirdness - baseDirectoryName = os.IsOSX ? "NexusMods_App/DataModel" : "NexusMods.App/DataModel"; - return baseKnownPath; + var basePath = GetLocalApplicationDataDirectory(fs.OS, out var relativePath); + return fs.GetKnownPath(basePath).Combine(relativePath); } - + /// /// Retrieves the default DataModel folder. /// This folder is reserved for the App and should not store user info. @@ -71,7 +70,26 @@ private static KnownPath GetStandardDataModelPaths(IOSInformation os, out string public static AbsolutePath GetStandardDataModelFolder(IFileSystem fs) { var os = fs.OS; - var baseKnownPath = GetStandardDataModelPaths(os, out var baseDirectoryName); - return fs.GetKnownPath(baseKnownPath).Combine(baseDirectoryName); + var baseKnownPath = GetLocalApplicationDataDirectory(os, out var baseDirectoryName); + return fs.GetKnownPath(baseKnownPath).Combine(baseDirectoryName).Combine(DataModelFolderName); + } + + /// + /// Retrieves the base directory where the App stores its local application data. + /// + /// OS Information. + /// Relative path to the returned . + /// + private static KnownPath GetLocalApplicationDataDirectory(IOSInformation os, out string baseDirectoryName) + { + var baseKnownPath = os.MatchPlatform( + onWindows: () => KnownPath.LocalApplicationDataDirectory, + onLinux: () => KnownPath.XDG_DATA_HOME, + onOSX: () => KnownPath.LocalApplicationDataDirectory + ); + + // NOTE: OSX ".App" is apparently special, using _ instead of . to prevent weirdness + baseDirectoryName = os.IsOSX ? "NexusMods_App" : "NexusMods.App"; + return baseKnownPath; } } From dbc942d0443a649c2c9b3c637d3f37367c43a39c Mon Sep 17 00:00:00 2001 From: Sewer56 Date: Thu, 3 Oct 2024 10:00:11 +0100 Subject: [PATCH 2/3] Fixed: Uninstaller now uses single quotes for nested paths. --- src/NexusMods.App/Commandline/CleanupVerbs.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NexusMods.App/Commandline/CleanupVerbs.cs b/src/NexusMods.App/Commandline/CleanupVerbs.cs index 97d306e22d..b8dcc101df 100644 --- a/src/NexusMods.App/Commandline/CleanupVerbs.cs +++ b/src/NexusMods.App/Commandline/CleanupVerbs.cs @@ -138,8 +138,9 @@ private static async Task DeleteRemainingFilesWindows(AbsolutePath[] appFiles, I var scriptPath = Path.Combine(AppContext.BaseDirectory, "uninstall-helper.ps1"); // Execute the PowerShell script + var args = $"-ExecutionPolicy Bypass -Command \"& \'{scriptPath}\' -FilesToDeletePath \'{filesToDeletePath}\' -DirectoriesToDeletePath \'{directoriesToDeletePath}\'\""; await Cli.Wrap("powershell") - .WithArguments($"-ExecutionPolicy Bypass -Command \"& \"{scriptPath}\" -FilesToDeletePath \"{filesToDeletePath}\" -DirectoriesToDeletePath \"{directoriesToDeletePath}\"\"") + .WithArguments(args) .ExecuteAsync(); // Clean up the temporary files From cdf509ec422d2129fcdbc834272d80726a87855a Mon Sep 17 00:00:00 2001 From: Sewer56 Date: Thu, 3 Oct 2024 10:01:08 +0100 Subject: [PATCH 3/3] Removed: Old Hack for Legacy Race Condition --- src/NexusMods.App/Commandline/CleanupVerbs.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/NexusMods.App/Commandline/CleanupVerbs.cs b/src/NexusMods.App/Commandline/CleanupVerbs.cs index b8dcc101df..548b9a0487 100644 --- a/src/NexusMods.App/Commandline/CleanupVerbs.cs +++ b/src/NexusMods.App/Commandline/CleanupVerbs.cs @@ -36,10 +36,6 @@ private static async Task UninstallApp( [Injected] ISettingsManager settingsManager, [Injected] IFileSystem fileSystem) { - // Prevent a race condition where `IRepository` is not fully done initializing. - // https://github.com/Nexus-Mods/NexusMods.App/issues/1396 - Thread.Sleep(1000); - // Step 1: Revert the managed games to their original state var db = conn.Db; var managedInstallations = Loadout.All(db)