Добавьте файлы проекта.
This commit is contained in:
75
Updater/Core/SafeFileInstaller.cs
Normal file
75
Updater/Core/SafeFileInstaller.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
namespace Updater.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Безопасный установщик: создает резервную копию замененных файлов, выполняет атомарную замену,
|
||||
/// и откатываемся в случае неудачи.
|
||||
/// </summary>
|
||||
public sealed class SafeFileInstaller : IInstaller
|
||||
{
|
||||
private readonly ILogger _log;
|
||||
public SafeFileInstaller(ILogger log) => _log = log;
|
||||
|
||||
public void Install(string sourceDir, string installPath)
|
||||
{
|
||||
var backupDir = Path.Combine(Path.GetTempPath(), $"upd_backup_{Guid.NewGuid():N}");
|
||||
Directory.CreateDirectory(backupDir);
|
||||
var completed = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Копирование файлов с резервной копией целей
|
||||
foreach (var src in Directory.EnumerateFiles(sourceDir, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
var rel = Path.GetRelativePath(sourceDir, src);
|
||||
var dst = Path.Combine(installPath, rel);
|
||||
var dstDir = Path.GetDirectoryName(dst)!;
|
||||
Directory.CreateDirectory(dstDir);
|
||||
|
||||
if (File.Exists(dst))
|
||||
{
|
||||
var bkp = Path.Combine(backupDir, rel);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(bkp)!);
|
||||
File.Copy(dst, bkp, overwrite: true);
|
||||
}
|
||||
|
||||
File.Copy(src, dst, overwrite: true);
|
||||
}
|
||||
|
||||
completed = true;
|
||||
_log.Info("Install completed successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Error($"Install failed: {ex.Message}");
|
||||
_log.Warn("Rolling back...");
|
||||
Rollback(backupDir, installPath);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Очистка резервной копии только в случае успеха
|
||||
if (completed)
|
||||
{
|
||||
TryDeleteDirectory(backupDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void Rollback(string backupDir, string installPath)
|
||||
{
|
||||
if (!Directory.Exists(backupDir)) return;
|
||||
|
||||
foreach (var bkp in Directory.EnumerateFiles(backupDir, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
var rel = Path.GetRelativePath(backupDir, bkp);
|
||||
var dst = Path.Combine(installPath, rel);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(dst)!);
|
||||
File.Copy(bkp, dst, overwrite: true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryDeleteDirectory(string dir)
|
||||
{
|
||||
try { Directory.Delete(dir, true); } catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user