namespace Updater.Core;
/// Параметры CLI для Updater.exe.
public sealed class Options
{
/// Путь к скачанному архиву (.zip).
public required string ZipPath { get; init; }
/// Целевой каталог установки.
public required string InstallPath { get; init; }
/// Имя исполняемого файла приложения для перезапуска (e.g., MyBot.exe).
public required string AppExe { get; init; }
/// Необязательно: подождите миллисекунды перед перезапуском (льготный период).
public int RestartDelayMs { get; init; } = 500;
public static string Usage =>
"Usage: Updater.exe --zip --installPath --appExe [--restartDelayMs ]";
/// Папрсинг CLI аргументов в Options.
public static Options Parse(string[] args)
{
var dict = new Dictionary(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < args.Length; i++)
{
if (!args[i].StartsWith("--")) continue;
var key = args[i][2..];
var val = (i + 1 < args.Length && !args[i + 1].StartsWith("--")) ? args[i + 1] : "true";
dict[key] = val;
}
var zip = Require(dict, "zip");
var install = Require(dict, "installPath");
var exe = Require(dict, "appExe");
if (!File.Exists(zip)) throw new FileNotFoundException("Zip not found", zip);
Directory.CreateDirectory(install);
return new Options
{
ZipPath = Path.GetFullPath(zip),
InstallPath = Path.GetFullPath(install),
AppExe = exe,
RestartDelayMs = dict.TryGetValue("restartDelayMs", out var d) && int.TryParse(d, out var n) ? n : 500
};
}
private static string Require(IDictionary dict, string key)
=> dict.TryGetValue(key, out var v) && !string.IsNullOrWhiteSpace(v)
? v : throw new ArgumentException($"Missing --{key}");
}
public static class ExitCodes
{
/// Успешное обновление.
public const int Ok = 0;
/// Неверные аргументы командной строки.
public const int InvalidArgs = 2;
/// Ошибка извлечения.
public const int ExtractFailed = 3;
/// Ошибка установки (копировать/заменить).
public const int InstallFailed = 4;
/// Ошибка перезапуска.
public const int RestartFailed = 5;
}