Improve cleanup.

This commit is contained in:
Ottermandias 2025-02-03 17:43:44 +01:00
parent ec09a7eb0e
commit 4cc5041f0a
2 changed files with 154 additions and 49 deletions

View file

@ -6,69 +6,160 @@ namespace Penumbra.Services;
public class CleanupService(SaveService saveService, ModManager mods, CollectionManager collections) : IService
{
private CancellationTokenSource _cancel = new();
private Task? _task;
public double Progress { get; private set; }
public bool IsRunning
=> _task is { IsCompleted: false };
public void Cancel()
=> _cancel.Cancel();
public void CleanUnusedLocalData()
{
var usedFiles = mods.Select(saveService.FileNames.LocalDataFile).ToHashSet();
foreach (var file in saveService.FileNames.LocalDataFiles.ToList())
{
try
{
if (!file.Exists || usedFiles.Contains(file.FullName))
continue;
if (IsRunning)
return;
file.Delete();
Penumbra.Log.Information($"[CleanupService] Deleted unused local data file {file.Name}.");
}
catch (Exception ex)
var usedFiles = mods.Select(saveService.FileNames.LocalDataFile).ToHashSet();
Progress = 0;
var deleted = 0;
_cancel = new CancellationTokenSource();
_task = Task.Run(() =>
{
var localFiles = saveService.FileNames.LocalDataFiles.ToList();
var step = 0.9 / localFiles.Count;
Progress = 0.1;
foreach (var file in localFiles)
{
Penumbra.Log.Error($"[CleanupService] Failed to delete unused local data file {file.Name}:\n{ex}");
if (_cancel.IsCancellationRequested)
break;
try
{
if (!file.Exists || usedFiles.Contains(file.FullName))
continue;
file.Delete();
Penumbra.Log.Debug($"[CleanupService] Deleted unused local data file {file.Name}.");
++deleted;
}
catch (Exception ex)
{
Penumbra.Log.Error($"[CleanupService] Failed to delete unused local data file {file.Name}:\n{ex}");
}
Progress += step;
}
}
Penumbra.Log.Information($"[CleanupService] Deleted {deleted} unused local data files.");
Progress = 1;
});
}
public void CleanBackupFiles()
{
foreach (var file in mods.BasePath.EnumerateFiles("group_*.json.bak", SearchOption.AllDirectories))
if (IsRunning)
return;
Progress = 0;
var deleted = 0;
_cancel = new CancellationTokenSource();
_task = Task.Run(() =>
{
try
{
if (!file.Exists)
continue;
var configFiles = Directory.EnumerateFiles(saveService.FileNames.ConfigDirectory, "*.json.bak", SearchOption.AllDirectories)
.ToList();
Progress = 0.1;
if (_cancel.IsCancellationRequested)
return;
file.Delete();
Penumbra.Log.Information($"[CleanupService] Deleted group backup file {file.FullName}.");
}
catch (Exception ex)
var groupFiles = mods.BasePath.EnumerateFiles("group_*.json.bak", SearchOption.AllDirectories).ToList();
Progress = 0.5;
var step = 0.4 / (groupFiles.Count + configFiles.Count);
foreach (var file in groupFiles)
{
Penumbra.Log.Error($"[CleanupService] Failed to delete group backup file {file.FullName}:\n{ex}");
}
}
if (_cancel.IsCancellationRequested)
break;
foreach (var file in Directory.EnumerateFiles(saveService.FileNames.ConfigDirectory, "*.json.bak", SearchOption.AllDirectories))
{
try
{
if (!File.Exists(file))
continue;
try
{
if (!file.Exists)
continue;
File.Delete(file);
Penumbra.Log.Information($"[CleanupService] Deleted config backup file {file}.");
file.Delete();
++deleted;
Penumbra.Log.Debug($"[CleanupService] Deleted group backup file {file.FullName}.");
}
catch (Exception ex)
{
Penumbra.Log.Error($"[CleanupService] Failed to delete group backup file {file.FullName}:\n{ex}");
}
Progress += step;
}
catch (Exception ex)
Penumbra.Log.Information($"[CleanupService] Deleted {deleted} group backup files.");
deleted = 0;
foreach (var file in configFiles)
{
Penumbra.Log.Error($"[CleanupService] Failed to delete config backup file {file}:\n{ex}");
if (_cancel.IsCancellationRequested)
break;
try
{
if (!File.Exists(file))
continue;
File.Delete(file);
++deleted;
Penumbra.Log.Debug($"[CleanupService] Deleted config backup file {file}.");
}
catch (Exception ex)
{
Penumbra.Log.Error($"[CleanupService] Failed to delete config backup file {file}:\n{ex}");
}
Progress += step;
}
}
Penumbra.Log.Information($"[CleanupService] Deleted {deleted} config backup files.");
Progress = 1;
});
}
public void CleanupAllUnusedSettings()
{
foreach (var collection in collections.Storage)
if (IsRunning)
return;
Progress = 0;
var totalRemoved = 0;
var diffCollections = 0;
_cancel = new CancellationTokenSource();
_task = Task.Run(() =>
{
var count = collections.Storage.CleanUnavailableSettings(collection);
if (count > 0)
Penumbra.Log.Information(
$"[CleanupService] Removed {count} unused settings from collection {collection.Identity.AnonymizedName}.");
}
var step = 1.0 / collections.Storage.Count;
foreach (var collection in collections.Storage)
{
if (_cancel.IsCancellationRequested)
break;
var count = collections.Storage.CleanUnavailableSettings(collection);
if (count > 0)
{
Penumbra.Log.Debug(
$"[CleanupService] Removed {count} unused settings from collection {collection.Identity.AnonymizedName}.");
totalRemoved += count;
++diffCollections;
}
Progress += step;
}
Penumbra.Log.Information($"[CleanupService] Removed {totalRemoved} unused settings from {diffCollections} separate collections.");
Progress = 1;
});
}
}

View file

@ -797,7 +797,6 @@ public class SettingsTab : ITab, IUiService
ImGui.Separator();
DrawCleanupButtons();
ImGui.NewLine();
}
private void DrawCrashHandler()
@ -991,24 +990,39 @@ public class SettingsTab : ITab, IUiService
private void DrawCleanupButtons()
{
var enabled = _config.DeleteModModifier.IsActive();
if (_cleanupService.Progress is not 0.0 and not 1.0)
{
ImUtf8.ProgressBar((float)_cleanupService.Progress, new Vector2(200 * ImUtf8.GlobalScale, ImGui.GetFrameHeight()),
$"{_cleanupService.Progress * 100}%");
ImGui.SameLine();
if (ImUtf8.Button("Cancel##FileCleanup"u8))
_cleanupService.Cancel();
}
else
{
ImGui.NewLine();
}
if (ImUtf8.ButtonEx("Clear Unused Local Mod Data Files"u8,
"Delete all local mod data files that do not correspond to currently installed mods."u8, default, !enabled))
"Delete all local mod data files that do not correspond to currently installed mods."u8, default,
!enabled || _cleanupService.IsRunning))
_cleanupService.CleanUnusedLocalData();
if (!enabled)
ImUtf8.HoverTooltip($"Hold {_config.DeleteModModifier} while clicking to delete files.");
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking to delete files.");
if (ImUtf8.ButtonEx("Clear Backup Files"u8,
"Delete all backups of .json configuration files in your configuration folder and all backups of mod group files in your mod directory."u8,
default, !enabled))
default, !enabled || _cleanupService.IsRunning))
_cleanupService.CleanBackupFiles();
if (!enabled)
ImUtf8.HoverTooltip($"Hold {_config.DeleteModModifier} while clicking to delete files.");
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking to delete files.");
if (ImUtf8.ButtonEx("Clear All Unused Settings"u8,
"Remove all mod settings in all of your collections that do not correspond to currently installed mods."u8, default, !enabled))
"Remove all mod settings in all of your collections that do not correspond to currently installed mods."u8, default,
!enabled || _cleanupService.IsRunning))
_cleanupService.CleanupAllUnusedSettings();
if (!enabled)
ImUtf8.HoverTooltip($"Hold {_config.DeleteModModifier} while clicking to remove settings.");
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking to remove settings.");
}
/// <summary> Draw a checkbox that toggles the dalamud setting to wait for plugins on open. </summary>