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 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() public void CleanUnusedLocalData()
{ {
var usedFiles = mods.Select(saveService.FileNames.LocalDataFile).ToHashSet(); if (IsRunning)
foreach (var file in saveService.FileNames.LocalDataFiles.ToList()) return;
{
try
{
if (!file.Exists || usedFiles.Contains(file.FullName))
continue;
file.Delete(); var usedFiles = mods.Select(saveService.FileNames.LocalDataFile).ToHashSet();
Penumbra.Log.Information($"[CleanupService] Deleted unused local data file {file.Name}."); Progress = 0;
} var deleted = 0;
catch (Exception ex) _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() 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 var configFiles = Directory.EnumerateFiles(saveService.FileNames.ConfigDirectory, "*.json.bak", SearchOption.AllDirectories)
{ .ToList();
if (!file.Exists) Progress = 0.1;
continue; if (_cancel.IsCancellationRequested)
return;
file.Delete(); var groupFiles = mods.BasePath.EnumerateFiles("group_*.json.bak", SearchOption.AllDirectories).ToList();
Penumbra.Log.Information($"[CleanupService] Deleted group backup file {file.FullName}."); Progress = 0.5;
} var step = 0.4 / (groupFiles.Count + configFiles.Count);
catch (Exception ex) 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
{ {
try if (!file.Exists)
{ continue;
if (!File.Exists(file))
continue;
File.Delete(file); file.Delete();
Penumbra.Log.Information($"[CleanupService] Deleted config backup file {file}."); ++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() 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); var step = 1.0 / collections.Storage.Count;
if (count > 0) foreach (var collection in collections.Storage)
Penumbra.Log.Information( {
$"[CleanupService] Removed {count} unused settings from collection {collection.Identity.AnonymizedName}."); 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(); ImGui.Separator();
DrawCleanupButtons(); DrawCleanupButtons();
ImGui.NewLine(); ImGui.NewLine();
} }
private void DrawCrashHandler() private void DrawCrashHandler()
@ -991,24 +990,39 @@ public class SettingsTab : ITab, IUiService
private void DrawCleanupButtons() private void DrawCleanupButtons()
{ {
var enabled = _config.DeleteModModifier.IsActive(); 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, 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(); _cleanupService.CleanUnusedLocalData();
if (!enabled) 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, 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, "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(); _cleanupService.CleanBackupFiles();
if (!enabled) 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, 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(); _cleanupService.CleanupAllUnusedSettings();
if (!enabled) 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> /// <summary> Draw a checkbox that toggles the dalamud setting to wait for plugins on open. </summary>