From b8210e094b6cb61ed17dd5dcd1b5986525433df2 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Thu, 12 May 2022 16:49:49 +0200 Subject: [PATCH] Add zip backup options to mods. --- Penumbra/Mods/Editor/ModBackup.cs | 94 +++++++++++++++++++++++ Penumbra/UI/ConfigWindow.ModPanel.Edit.cs | 36 ++++++++- 2 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 Penumbra/Mods/Editor/ModBackup.cs diff --git a/Penumbra/Mods/Editor/ModBackup.cs b/Penumbra/Mods/Editor/ModBackup.cs new file mode 100644 index 00000000..acc9e8af --- /dev/null +++ b/Penumbra/Mods/Editor/ModBackup.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Threading.Tasks; +using Dalamud.Logging; + +namespace Penumbra.Mods; + +// Utility to create and apply a zipped backup of a mod. +public class ModBackup +{ + public static bool CreatingBackup { get; private set; } + + private readonly Mod _mod; + public readonly string Name; + public readonly bool Exists; + + public ModBackup( Mod mod ) + { + _mod = mod; + Name = mod.ModPath + ".zip"; + Exists = File.Exists( Name ); + } + + // Create a backup zip without blocking the main thread. + public async void CreateAsync() + { + if( CreatingBackup ) + { + return; + } + + CreatingBackup = true; + await Task.Run( Create ); + CreatingBackup = false; + } + + + // Create a backup. Overwrites pre-existing backups. + private void Create() + { + try + { + Delete(); + ZipFile.CreateFromDirectory( _mod.ModPath.FullName, Name, CompressionLevel.Optimal, false ); + PluginLog.Debug( "Created backup file {backupName} from {modDirectory}.", Name, _mod.ModPath.FullName ); + } + catch( Exception e ) + { + PluginLog.Error( $"Could not backup mod {_mod.Name} to \"{Name}\":\n{e}" ); + } + } + + // Delete a pre-existing backup. + public void Delete() + { + if( !Exists ) + { + return; + } + + try + { + File.Delete( Name ); + PluginLog.Debug( "Deleted backup file {backupName}.", Name ); + } + catch( Exception e ) + { + PluginLog.Error( $"Could not delete file \"{Name}\":\n{e}" ); + } + } + + // Restore a mod from a pre-existing backup. Does not check if the mod contained in the backup is even similar. + // Does an automatic reload after extraction. + public void Restore() + { + try + { + if( Directory.Exists( _mod.ModPath.FullName ) ) + { + Directory.Delete( _mod.ModPath.FullName, true ); + PluginLog.Debug( "Deleted mod folder {modFolder}.", _mod.ModPath.FullName ); + } + + ZipFile.ExtractToDirectory( Name, _mod.ModPath.FullName ); + PluginLog.Debug( "Extracted backup file {backupName} to {modName}.", Name, _mod.ModPath.FullName ); + Penumbra.ModManager.ReloadMod( _mod.Index ); + } + catch( Exception e ) + { + PluginLog.Error( $"Could not restore {_mod.Name} from backup \"{Name}\":\n{e}" ); + } + } +} \ No newline at end of file diff --git a/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs b/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs index 365f3308..d2038205 100644 --- a/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs +++ b/Penumbra/UI/ConfigWindow.ModPanel.Edit.cs @@ -6,7 +6,6 @@ using System.Numerics; using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Logging; -using Dalamud.Memory; using ImGuiNET; using OtterGui; using OtterGui.Raii; @@ -90,11 +89,44 @@ public partial class ConfigWindow Penumbra.ModManager.ReloadMod( _mod.Index ); } - + BackupButtons( buttonSize ); MoveDirectory.Draw( _mod, buttonSize ); + ImGui.Dummy( _window._defaultSpace ); } + private void BackupButtons( Vector2 buttonSize ) + { + var backup = new ModBackup( _mod ); + var tt = ModBackup.CreatingBackup + ? "Already creating a backup." + : backup.Exists + ? $"Overwrite current backup \"{backup.Name}\" with current mod." + : $"Create backup archive of current mod at \"{backup.Name}\"."; + if( ImGuiUtil.DrawDisabledButton( "Create Backup", buttonSize, tt, ModBackup.CreatingBackup ) ) + { + backup.CreateAsync(); + } + + ImGui.SameLine(); + tt = backup.Exists + ? $"Delete existing backup file \"{backup.Name}\"." + : $"Backup file \"{backup.Name}\" does not exist."; + if( ImGuiUtil.DrawDisabledButton( "Delete Backup", buttonSize, tt, !backup.Exists ) ) + { + backup.Delete(); + } + + tt = backup.Exists + ? $"Restore mod from backup file \"{backup.Name}\"." + : $"Backup file \"{backup.Name}\" does not exist."; + ImGui.SameLine(); + if( ImGuiUtil.DrawDisabledButton( "Restore From Backup", buttonSize, tt, !backup.Exists ) ) + { + backup.Restore(); + } + } + // Anything about editing the regular meta information about the mod. private void EditRegularMeta() {