mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 20:24:17 +01:00
140 lines
4.2 KiB
C#
140 lines
4.2 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Penumbra.Mods;
|
|
|
|
/// <summary> Utility to create and apply a zipped backup of a mod. </summary>
|
|
public class ModBackup
|
|
{
|
|
public static bool CreatingBackup { get; private set; }
|
|
|
|
private readonly ModManager _modManager;
|
|
private readonly Mod _mod;
|
|
public readonly string Name;
|
|
public readonly bool Exists;
|
|
|
|
public ModBackup(ModManager modManager, Mod mod)
|
|
{
|
|
_modManager = modManager;
|
|
_mod = mod;
|
|
Name = Path.Combine(_modManager.ExportDirectory.FullName, _mod.ModPath.Name) + ".pmp";
|
|
Exists = File.Exists(Name);
|
|
}
|
|
|
|
/// <summary> Migrate file extensions. </summary>
|
|
public static void MigrateZipToPmp(ModManager modManager)
|
|
{
|
|
foreach (var mod in modManager)
|
|
{
|
|
var pmpName = mod.ModPath + ".pmp";
|
|
var zipName = mod.ModPath + ".zip";
|
|
if (!File.Exists(zipName))
|
|
continue;
|
|
|
|
try
|
|
{
|
|
if (!File.Exists(pmpName))
|
|
File.Move(zipName, pmpName);
|
|
else
|
|
File.Delete(zipName);
|
|
|
|
Penumbra.Log.Information($"Migrated mod export from {zipName} to {pmpName}.");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Penumbra.Log.Warning($"Could not migrate mod export of {mod.ModPath} from .pmp to .zip:\n{e}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Move and/or rename an exported mod.
|
|
/// This object is unusable afterwards.
|
|
/// </summary>
|
|
public void Move(string? newBasePath = null, string? newName = null)
|
|
{
|
|
if (CreatingBackup || !Exists)
|
|
return;
|
|
|
|
try
|
|
{
|
|
newBasePath ??= Path.GetDirectoryName(Name) ?? string.Empty;
|
|
newName = newName == null ? Path.GetFileName(Name) : newName + ".pmp";
|
|
var newPath = Path.Combine(newBasePath, newName);
|
|
File.Move(Name, newPath);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Penumbra.Log.Warning($"Could not move mod export file {Name}:\n{e}");
|
|
}
|
|
}
|
|
|
|
/// <summary> Create a backup zip without blocking the main thread. </summary>
|
|
public async void CreateAsync()
|
|
{
|
|
if (CreatingBackup)
|
|
return;
|
|
|
|
CreatingBackup = true;
|
|
await Task.Run(Create);
|
|
CreatingBackup = false;
|
|
}
|
|
|
|
/// <summary> Create a backup. Overwrites pre-existing backups. </summary>
|
|
private void Create()
|
|
{
|
|
try
|
|
{
|
|
Delete();
|
|
ZipFile.CreateFromDirectory(_mod.ModPath.FullName, Name, CompressionLevel.Optimal, false);
|
|
Penumbra.Log.Debug($"Created export file {Name} from {_mod.ModPath.FullName}.");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Penumbra.Log.Error($"Could not export mod {_mod.Name} to \"{Name}\":\n{e}");
|
|
}
|
|
}
|
|
|
|
/// <summary> Delete a pre-existing backup. </summary>
|
|
public void Delete()
|
|
{
|
|
if (!Exists)
|
|
return;
|
|
|
|
try
|
|
{
|
|
File.Delete(Name);
|
|
Penumbra.Log.Debug($"Deleted export file {Name}.");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Penumbra.Log.Error($"Could not delete file \"{Name}\":\n{e}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public void Restore()
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(_mod.ModPath.FullName))
|
|
{
|
|
Directory.Delete(_mod.ModPath.FullName, true);
|
|
Penumbra.Log.Debug($"Deleted mod folder {_mod.ModPath.FullName}.");
|
|
}
|
|
|
|
ZipFile.ExtractToDirectory(Name, _mod.ModPath.FullName);
|
|
Penumbra.Log.Debug($"Extracted exported file {Name} to {_mod.ModPath.FullName}.");
|
|
_modManager.ReloadMod(_mod.Index);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Penumbra.Log.Error($"Could not restore {_mod.Name} from export \"{Name}\":\n{e}");
|
|
}
|
|
}
|
|
}
|