Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1420c2c0eb | ||
|
|
dea6be8094 | ||
|
|
72b0d60f3a | ||
| 9365aa16cd | |||
| 36331e8664 | |||
| d0e57d8d7b | |||
| 16fbddcdc8 | |||
| ec3d8de187 |
@@ -19,20 +19,31 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.x
|
dotnet-version: 8.0.x
|
||||||
|
|
||||||
- name: Restore ReleaseUpdater
|
|
||||||
run: dotnet restore ReleaseUpdater
|
|
||||||
|
|
||||||
- name: Set version from tag
|
- name: Set version from tag
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
TAG="${GITHUB_REF_NAME#v}"
|
TAG="${GITHUB_REF_NAME#v}"
|
||||||
echo "PACKAGE_VERSION=$TAG" >> $GITHUB_OUTPUT
|
echo "PACKAGE_VERSION=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build ReleaseUpdater
|
- name: Replace ProjectReference with PackageReference
|
||||||
run: dotnet build ReleaseUpdater -c Release -p:Version=${{ steps.version.outputs.PACKAGE_VERSION }}
|
run: |
|
||||||
|
sed -i "s#<ProjectReference Include=\"..\/ReleaseUpdater.Common\/ReleaseUpdater.Common.csproj\" />#<PackageReference Include=\"ReleaseUpdater.Common\" Version=\"${{ steps.version.outputs.PACKAGE_VERSION }}\" />#" ReleaseUpdater/ReleaseUpdater.csproj
|
||||||
|
|
||||||
- name: Pack ReleaseUpdater
|
- name: Build and Pack projects
|
||||||
run: dotnet pack ReleaseUpdater -c Release --no-build -p:PackageVersion=${{ steps.version.outputs.PACKAGE_VERSION }} -o ./artifacts
|
run: |
|
||||||
|
mkdir -p artifacts
|
||||||
|
for proj in $PROJECTS; do
|
||||||
|
echo "Restoring $proj..."
|
||||||
|
dotnet restore $proj
|
||||||
|
echo "Building $proj..."
|
||||||
|
dotnet build $proj -c Release -p:Version=${{ steps.version.outputs.PACKAGE_VERSION }}
|
||||||
|
echo "Packing $proj..."
|
||||||
|
dotnet pack $proj -c Release --no-build -p:PackageVersion=${{ steps.version.outputs.PACKAGE_VERSION }} -o ./artifacts
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
PROJECTS: |
|
||||||
|
ReleaseUpdater.Common
|
||||||
|
ReleaseUpdater
|
||||||
|
|
||||||
- name: Upload package artifact
|
- name: Upload package artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
|||||||
@@ -1,10 +1,21 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<Nullable>enable</Nullable>
|
||||||
<Nullable>enable</Nullable>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<PackageId>ReleaseUpdater.Common</PackageId>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Authors>FrigaT</Authors>
|
||||||
|
<Company>FrigaT</Company>
|
||||||
|
<Product>ReleaseUpdater</Product>
|
||||||
|
<Description>Система обновления приложений через github/gitea системы контроля версий.</Description>
|
||||||
|
<Copyright>Copyright © 2025 FrigaT</Copyright>
|
||||||
|
<RepositoryUrl>https://git.frigat.duckdns.org/FrigaT/ReleaseUpdater</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageProjectUrl>https://git.frigat.duckdns.org/FrigaT/ReleaseUpdater</PackageProjectUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public sealed class ReleaseProvider
|
|||||||
/// <param name="token">Токен авторизации (если требуется).</param>
|
/// <param name="token">Токен авторизации (если требуется).</param>
|
||||||
/// <returns>Список релизов.</returns>
|
/// <returns>Список релизов.</returns>
|
||||||
|
|
||||||
public async Task<IReadOnlyList<ReleaseInfo>> GetReleasesAsync(string apiUrl, string? token = null)
|
public async Task<IReadOnlyList<ReleaseInfo>> GetReleasesAsync(Uri apiUrl, string? token = null)
|
||||||
{
|
{
|
||||||
using var client = CreateClient(token);
|
using var client = CreateClient(token);
|
||||||
using var resp = await client.GetAsync(apiUrl);
|
using var resp = await client.GetAsync(apiUrl);
|
||||||
@@ -38,7 +38,7 @@ public sealed class ReleaseProvider
|
|||||||
/// <param name="token">Токен авторизации (если требуется).</param>
|
/// <param name="token">Токен авторизации (если требуется).</param>
|
||||||
/// <returns>Информация о релизе или null.</returns>
|
/// <returns>Информация о релизе или null.</returns>
|
||||||
|
|
||||||
public async Task<ReleaseInfo?> FindReleaseAsync(string apiUrl, string? versionOrLatest, string? token = null)
|
public async Task<ReleaseInfo?> FindReleaseAsync(Uri apiUrl, string? versionOrLatest, string? token = null)
|
||||||
{
|
{
|
||||||
var all = await GetReleasesAsync(apiUrl, token);
|
var all = await GetReleasesAsync(apiUrl, token);
|
||||||
if (string.IsNullOrWhiteSpace(versionOrLatest) || versionOrLatest.Equals("latest", StringComparison.OrdinalIgnoreCase))
|
if (string.IsNullOrWhiteSpace(versionOrLatest) || versionOrLatest.Equals("latest", StringComparison.OrdinalIgnoreCase))
|
||||||
|
|||||||
@@ -1,9 +1,21 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<Nullable>enable</Nullable>
|
||||||
<Nullable>enable</Nullable>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<PackageId>ReleaseUpdater</PackageId>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Authors>FrigaT</Authors>
|
||||||
|
<Company>FrigaT</Company>
|
||||||
|
<Product>ReleaseUpdater</Product>
|
||||||
|
<Description>Система обновления приложений через github/gitea системы контроля версий.</Description>
|
||||||
|
<Copyright>Copyright © 2025 FrigaT</Copyright>
|
||||||
|
<RepositoryUrl>https://git.frigat.duckdns.org/FrigaT/ReleaseUpdater</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageProjectUrl>https://git.frigat.duckdns.org/FrigaT/ReleaseUpdater</PackageProjectUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace ReleaseUpdater;
|
namespace ReleaseUpdater;
|
||||||
|
|
||||||
@@ -14,65 +15,47 @@ public static class ReleaseUpdaterFacade
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static event Action? BeforeInstall;
|
public static event Action? BeforeInstall;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Событие вызывается после успешной установки новой версии.
|
|
||||||
/// </summary>
|
|
||||||
public static event Action? AfterInstall;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Событие вызывается при ошибке обновления.
|
/// Событие вызывается при ошибке обновления.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static event Action<Exception>? UpdateFailed;
|
public static event Action<Exception>? UpdateFailed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Событие вызывается, если текущая версия совпадает с требуемой.
|
||||||
|
/// </summary>
|
||||||
|
public static event Action<string>? AlreadyUp;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Получает список доступных версий из Gitea.
|
/// Получает список доступных версий из Gitea.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task<IReadOnlyList<string>> GetVersionsAsync(string apiUrl, string? token = null)
|
public static async Task<IReadOnlyList<string>> GetVersionsAsync(Uri apiUrl, string? token = null)
|
||||||
{
|
{
|
||||||
var provider = new ReleaseProvider();
|
var provider = new ReleaseProvider();
|
||||||
var releases = await provider.GetReleasesAsync(apiUrl, token);
|
var releases = await provider.GetReleasesAsync(apiUrl, token);
|
||||||
return releases.Select(r => r.TagName).ToList();
|
return releases.Select(r => r.TagName).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Обновление без Updater.exe: скачивание, распаковка и перезапуск прямо из DLL.
|
|
||||||
/// </summary>
|
|
||||||
public static async Task UpdateInlineAsync(
|
|
||||||
string apiUrl, string? token, string installPath, string appExe, string versionOrLatest = "latest")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var provider = new ReleaseProvider();
|
|
||||||
var release = await provider.FindReleaseAsync(apiUrl, versionOrLatest, token)
|
|
||||||
?? throw new Exception("Release not found");
|
|
||||||
|
|
||||||
var asset = release.Assets.FirstOrDefault(a => a.Name.EndsWith(".zip"))
|
|
||||||
?? throw new Exception("No zip asset found");
|
|
||||||
|
|
||||||
var downloader = new HttpAssetDownloader();
|
|
||||||
var zipPath = await downloader.DownloadAssetAsync(asset.DownloadUrl, token);
|
|
||||||
|
|
||||||
BeforeInstall?.Invoke();
|
|
||||||
|
|
||||||
ZipFile.ExtractToDirectory(zipPath, installPath, true);
|
|
||||||
|
|
||||||
AfterInstall?.Invoke();
|
|
||||||
|
|
||||||
Process.Start(Path.Combine(installPath, appExe));
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
UpdateFailed?.Invoke(ex);
|
|
||||||
RestartCurrent(installPath, appExe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обновление через внешний Updater.exe.
|
/// Обновление через внешний Updater.exe.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task UpdateWithExternalAsync(
|
/// <param name="apiUrl">API github/gitea release</param>
|
||||||
string apiUrl, string? token, string installPath, string appExe, string versionOrLatest = "latest", string? updaterExePath = null, bool exitCurrentApp = false)
|
/// <param name="token">Token авторизации</param>
|
||||||
|
/// <param name="installPath">Путь для установки приложения</param>
|
||||||
|
/// <param name="appExeName">Наименование файла приложения</param>
|
||||||
|
/// <param name="tempDirectory">Папка для временного хранилища zip архива</param>
|
||||||
|
/// <param name="updaterExePath">Путь к updater.exe</param>
|
||||||
|
/// <param name="versionOrLatest">Тэг с версией / "latest"</param>
|
||||||
|
/// <param name="assetMask">Маска наименовая ассета обновления. В маске может содержаться {version}</param>
|
||||||
|
public static async Task UpdateAsync(
|
||||||
|
Uri apiUrl,
|
||||||
|
string? token,
|
||||||
|
string installPath,
|
||||||
|
string appExeName,
|
||||||
|
string tempDirectory,
|
||||||
|
string updaterExePath,
|
||||||
|
string versionOrLatest = "latest",
|
||||||
|
string? assetMask = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -80,16 +63,44 @@ public static class ReleaseUpdaterFacade
|
|||||||
var release = await provider.FindReleaseAsync(apiUrl, versionOrLatest, token)
|
var release = await provider.FindReleaseAsync(apiUrl, versionOrLatest, token)
|
||||||
?? throw new Exception("Release not found");
|
?? throw new Exception("Release not found");
|
||||||
|
|
||||||
var asset = release.Assets.FirstOrDefault(a => a.Name.EndsWith(".zip"))
|
|
||||||
?? throw new Exception("No zip asset found");
|
var currentVersion = GetCurrentVersion(); // реализуй сам
|
||||||
|
|
||||||
|
|
||||||
|
if (SemVerService.Compare(release.TagName, currentVersion) == 0)
|
||||||
|
{
|
||||||
|
AlreadyUp?.Invoke(currentVersion);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Маска: myapp-{version}.zip
|
||||||
|
string? mask = assetMask?.Replace("{version}", release.TagName);
|
||||||
|
|
||||||
|
var asset = release.Assets.FirstOrDefault(a =>
|
||||||
|
mask != null
|
||||||
|
? a.Name.Equals(mask, StringComparison.OrdinalIgnoreCase)
|
||||||
|
: a.Name.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)
|
||||||
|
) ?? throw new Exception("No matching asset found");
|
||||||
|
|
||||||
|
string tempNumber = $"{Guid.NewGuid():N}";
|
||||||
|
var tempUpdaterName = $"updater_{tempNumber}.exe";
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(tempDirectory))
|
||||||
|
{
|
||||||
|
tempDirectory = Path.GetTempPath();
|
||||||
|
}
|
||||||
|
else if (!Directory.Exists(tempDirectory))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(tempDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tempUpdaterPath = Path.Combine(tempDirectory, tempUpdaterName);
|
||||||
|
|
||||||
var downloader = new HttpAssetDownloader();
|
var downloader = new HttpAssetDownloader();
|
||||||
var zipPath = await downloader.DownloadAssetAsync(asset.DownloadUrl, token);
|
var zipPath = await downloader.DownloadAssetAsync(asset.DownloadUrl, token, Path.Combine(tempDirectory, $"updater_{tempNumber}.zip"));
|
||||||
|
|
||||||
BeforeInstall?.Invoke();
|
|
||||||
|
|
||||||
|
|
||||||
if (updaterExePath == null) updaterExePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Updater.exe");
|
File.Copy(updaterExePath, tempUpdaterPath);
|
||||||
|
|
||||||
if (installPath.EndsWith("\\"))
|
if (installPath.EndsWith("\\"))
|
||||||
{
|
{
|
||||||
@@ -100,55 +111,42 @@ public static class ReleaseUpdaterFacade
|
|||||||
{
|
{
|
||||||
ZipPath = zipPath,
|
ZipPath = zipPath,
|
||||||
InstallPath = installPath,
|
InstallPath = installPath,
|
||||||
AppExe = appExe,
|
AppExe = appExeName,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (exitCurrentApp)
|
int pid = Process.GetCurrentProcess().Id;
|
||||||
{
|
updaterOptions.WaitProcess = pid;
|
||||||
int pid = Process.GetCurrentProcess().Id;
|
|
||||||
updaterOptions.WaitProcess = pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
var args = ArgumentsToolkit.ArgumentsParser.ToArguments(updaterOptions, true);
|
var args = ArgumentsToolkit.ArgumentsParser.ToArguments(updaterOptions, true);
|
||||||
|
|
||||||
|
BeforeInstall?.Invoke();
|
||||||
|
|
||||||
var process = Process.Start(new ProcessStartInfo
|
var process = Process.Start(new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = updaterExePath,
|
FileName = tempUpdaterPath,
|
||||||
Arguments = args,
|
Arguments = args,
|
||||||
UseShellExecute = true,
|
UseShellExecute = true,
|
||||||
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
|
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory
|
||||||
});
|
});
|
||||||
|
|
||||||
if (exitCurrentApp) { Environment.Exit(0); }
|
|
||||||
|
|
||||||
process?.WaitForExit();
|
|
||||||
|
|
||||||
if (process?.ExitCode == 0)
|
|
||||||
AfterInstall?.Invoke();
|
|
||||||
else
|
|
||||||
throw new Exception($"Updater.exe завершился с кодом {process?.ExitCode}");
|
|
||||||
|
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
UpdateFailed?.Invoke(ex);
|
UpdateFailed?.Invoke(ex);
|
||||||
RestartCurrent(installPath, appExe);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RestartCurrent(string installPath, string appExe)
|
/// <summary>
|
||||||
|
/// Получение текущей версии приложения
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetCurrentVersion()
|
||||||
{
|
{
|
||||||
var currentApp = Path.Combine(installPath, appExe);
|
var entryAssembly = Assembly.GetEntryAssembly();
|
||||||
if (File.Exists(currentApp))
|
var attr = entryAssembly?.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
||||||
{
|
return attr?.InformationalVersion.Split("+")[0]
|
||||||
Process.Start(new ProcessStartInfo
|
?? entryAssembly?.GetName().Version?.ToString()
|
||||||
{
|
?? "unknown";
|
||||||
FileName = currentApp,
|
|
||||||
UseShellExecute = true,
|
|
||||||
WorkingDirectory = installPath
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public sealed class SemVerService
|
|||||||
/// <param name="version">Строка версии (например, "3.5.2").</param>
|
/// <param name="version">Строка версии (например, "3.5.2").</param>
|
||||||
/// <param name="parsed">Результат парсинга.</param>
|
/// <param name="parsed">Результат парсинга.</param>
|
||||||
/// <returns>true, если парсинг успешен.</returns>
|
/// <returns>true, если парсинг успешен.</returns>
|
||||||
public bool TryParse(string version, out Version parsed)
|
public static bool TryParse(string version, out Version parsed)
|
||||||
{
|
{
|
||||||
var v = version.Trim().TrimStart('v');
|
var v = version.Trim().TrimStart('v');
|
||||||
return Version.TryParse(Normalize(v), out parsed);
|
return Version.TryParse(Normalize(v), out parsed);
|
||||||
@@ -34,7 +34,7 @@ public sealed class SemVerService
|
|||||||
/// <param name="v1">Первая версия.</param>
|
/// <param name="v1">Первая версия.</param>
|
||||||
/// <param name="v2">Вторая версия.</param>
|
/// <param name="v2">Вторая версия.</param>
|
||||||
/// <returns>-1 если v1 < v2, 0 если равны, 1 если v1 > v2.</returns>
|
/// <returns>-1 если v1 < v2, 0 если равны, 1 если v1 > v2.</returns>
|
||||||
public int Compare(string v1, string v2)
|
public static int Compare(string v1, string v2)
|
||||||
{
|
{
|
||||||
TryParse(v1, out var a);
|
TryParse(v1, out var a);
|
||||||
TryParse(v2, out var b);
|
TryParse(v2, out var b);
|
||||||
|
|||||||
@@ -14,7 +14,27 @@ internal class Program
|
|||||||
var url = "https://git.frigat.duckdns.org/api/v1/repos/automacon/RetailUpdatesBot/releases";
|
var url = "https://git.frigat.duckdns.org/api/v1/repos/automacon/RetailUpdatesBot/releases";
|
||||||
var APIKey = "0552a77699d7506711946fc71cc6635515726bd1"; //токен
|
var APIKey = "0552a77699d7506711946fc71cc6635515726bd1"; //токен
|
||||||
|
|
||||||
await ReleaseUpdaterFacade.UpdateWithExternalAsync(url, APIKey, installPath, appExe, "latest", updaterPath, true);
|
SemVerService.TryParse("v0.1.2", out var v1);
|
||||||
|
Console.WriteLine($"v0.1.2 - {v1}");
|
||||||
|
SemVerService.TryParse(ReleaseUpdaterFacade.GetCurrentVersion(), out var v2);
|
||||||
|
Console.WriteLine($"{ReleaseUpdaterFacade.GetCurrentVersion()} - {v2}");
|
||||||
|
Console.WriteLine(SemVerService.Compare("v0.1.2", ReleaseUpdaterFacade.GetCurrentVersion()));
|
||||||
|
Console.WriteLine(SemVerService.Compare("v0.1.2", "1.0.0"));
|
||||||
|
Console.WriteLine(SemVerService.Compare("v0.1.2", "0.1.2"));
|
||||||
|
Console.WriteLine(SemVerService.Compare("v0.1.2", "0.1.1"));
|
||||||
|
Console.WriteLine(SemVerService.Compare("v0.1.2", "0.1.3"));
|
||||||
|
Console.WriteLine(SemVerService.Compare("v0.1.2", "0.2.0"));
|
||||||
|
|
||||||
|
await ReleaseUpdaterFacade.UpdateAsync(
|
||||||
|
apiUrl: new Uri(url),
|
||||||
|
token: APIKey,
|
||||||
|
installPath: installPath,
|
||||||
|
appExeName: appExe,
|
||||||
|
tempDirectory: Path.Combine(updaterPath, "Tools", "Temp"),
|
||||||
|
updaterExePath: updaterPath,
|
||||||
|
versionOrLatest: "latest",
|
||||||
|
assetMask: "RetailUpdatesBot-{version}.zip"
|
||||||
|
);
|
||||||
|
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -5,6 +5,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<Version>2.0.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -23,12 +23,13 @@ public sealed class SafeFileInstaller : IInstaller
|
|||||||
var rel = Path.GetRelativePath(sourceDir, src);
|
var rel = Path.GetRelativePath(sourceDir, src);
|
||||||
var dst = Path.Combine(installPath, rel);
|
var dst = Path.Combine(installPath, rel);
|
||||||
var dstDir = Path.GetDirectoryName(dst)!;
|
var dstDir = Path.GetDirectoryName(dst)!;
|
||||||
Directory.CreateDirectory(dstDir);
|
if (!Directory.Exists(dstDir)) Directory.CreateDirectory(dstDir);
|
||||||
|
|
||||||
if (File.Exists(dst))
|
if (File.Exists(dst))
|
||||||
{
|
{
|
||||||
var bkp = Path.Combine(backupDir, rel);
|
var bkp = Path.Combine(backupDir, rel);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(bkp)!);
|
var bkpDir = Path.GetDirectoryName(bkp);
|
||||||
|
if (!Directory.Exists(bkpDir)) Directory.CreateDirectory(bkpDir!);
|
||||||
File.Copy(dst, bkp, overwrite: true);
|
File.Copy(dst, bkp, overwrite: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +64,8 @@ public sealed class SafeFileInstaller : IInstaller
|
|||||||
{
|
{
|
||||||
var rel = Path.GetRelativePath(backupDir, bkp);
|
var rel = Path.GetRelativePath(backupDir, bkp);
|
||||||
var dst = Path.Combine(installPath, rel);
|
var dst = Path.Combine(installPath, rel);
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(dst)!);
|
var dstDir = Path.GetDirectoryName(dst);
|
||||||
|
if (!Directory.Exists(dstDir)) Directory.CreateDirectory(dstDir!);
|
||||||
File.Copy(bkp, dst, overwrite: true);
|
File.Copy(bkp, dst, overwrite: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public sealed class UpdaterApp
|
|||||||
private readonly IInstaller _installer;
|
private readonly IInstaller _installer;
|
||||||
private readonly IProcessManager _proc;
|
private readonly IProcessManager _proc;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
public UpdaterApp(ILogger log, IExtractor extractor, IInstaller installer, IProcessManager proc)
|
public UpdaterApp(ILogger log, IExtractor extractor, IInstaller installer, IProcessManager proc)
|
||||||
{
|
{
|
||||||
_log = log;
|
_log = log;
|
||||||
@@ -34,6 +35,7 @@ public sealed class UpdaterApp
|
|||||||
{
|
{
|
||||||
_log.Error($"Extraction failed: {ex.Message}");
|
_log.Error($"Extraction failed: {ex.Message}");
|
||||||
Cleanup(tempExtractDir);
|
Cleanup(tempExtractDir);
|
||||||
|
_proc.StartApp(opts.InstallPath, opts.AppExe, opts.RestartDelayMs);
|
||||||
return ExitCodes.ExtractFailed;
|
return ExitCodes.ExtractFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ public sealed class UpdaterApp
|
|||||||
{
|
{
|
||||||
_log.Error($"Install failed: {ex.Message}");
|
_log.Error($"Install failed: {ex.Message}");
|
||||||
Cleanup(tempExtractDir);
|
Cleanup(tempExtractDir);
|
||||||
|
_proc.StartApp(opts.InstallPath, opts.AppExe, opts.RestartDelayMs);
|
||||||
return ExitCodes.InstallFailed;
|
return ExitCodes.InstallFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
Updater/Properties/launchSettings.json
Normal file
8
Updater/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Updater": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "-z \"C:\\Job\\Projects\\FrigaT\\ReleaseUpdater\\Updater.Test\\bin\\Debug\\net8.0\\Tools\\tempUpdater\\updater_32f606dc1cda473ab953206927bf047b.zip\" -i \"C:\\Job\\Projects\\FrigaT\\ReleaseUpdater\\Updater.Test\\bin\\Debug\\net8.0\" -a \"RetailUpdatesBot.exe\" -rd \"500\" -ud \"500\" -wp \"31408\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,29 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<Version>2.0.0</Version>
|
||||||
|
<Authors>FrigaT</Authors>
|
||||||
|
<Company>FrigaT</Company>
|
||||||
|
<Product>ReleaseUpdater</Product>
|
||||||
|
<Description>Запускатор обновления</Description>
|
||||||
|
<Copyright>Copyright © 2025 FrigaT</Copyright>
|
||||||
|
<RepositoryUrl>https://git.frigat.duckdns.org/FrigaT/ReleaseUpdater</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageProjectUrl>https://git.frigat.duckdns.org/FrigaT/ReleaseUpdater</PackageProjectUrl>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ArgumentsToolkit" Version="0.0.3" />
|
<PackageReference Include="ArgumentsToolkit" Version="0.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ReleaseUpdater.Common\ReleaseUpdater.Common.csproj" />
|
<ProjectReference Include="..\ReleaseUpdater.Common\ReleaseUpdater.Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user