Fix down/up progress

This commit is contained in:
Caelan Sayler
2024-12-27 10:59:35 +00:00
committed by Caelan
parent 8323ce6a96
commit 0e9757d1b7
2 changed files with 21 additions and 113 deletions

View File

@@ -1,9 +1,4 @@
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Text;
namespace Velopack.Flow;
namespace Velopack.Flow;
public partial class Profile
{
@@ -12,91 +7,3 @@ public partial class Profile
return DisplayName ?? Email ?? "<unknown>";
}
}
public partial class FlowApi
{
public virtual async Task DownloadInstallerLatestToFileAsync(string packageId, string channel, DownloadAssetType? assetType, string localFilePath,
CancellationToken cancellationToken)
{
if (packageId == null)
throw new ArgumentNullException(nameof(packageId));
if (channel == null)
throw new ArgumentNullException(nameof(channel));
var client = _httpClient;
using var request = new HttpRequestMessage();
request.Method = new HttpMethod("GET");
var urlBuilder = new StringBuilder();
if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder.Append(_baseUrl);
// Operation Path: "v1/download/{packageId}/{channel}"
urlBuilder.Append("v1/download/");
urlBuilder.Append(Uri.EscapeDataString(ConvertToString(packageId, CultureInfo.InvariantCulture)));
urlBuilder.Append('/');
urlBuilder.Append(Uri.EscapeDataString(ConvertToString(channel, CultureInfo.InvariantCulture)));
urlBuilder.Append('?');
if (assetType != null) {
urlBuilder.Append(Uri.EscapeDataString("assetType")).Append('=')
.Append(Uri.EscapeDataString(ConvertToString(assetType, CultureInfo.InvariantCulture))).Append('&');
}
urlBuilder.Length--;
PrepareRequest(client, request, urlBuilder);
var url = urlBuilder.ToString();
request.RequestUri = new Uri(url, UriKind.RelativeOrAbsolute);
PrepareRequest(client, request, url);
using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
var headers = new Dictionary<string, IEnumerable<string>>();
foreach (var item in response.Headers)
headers[item.Key] = item.Value;
if (response.Content != null && response.Content.Headers != null) {
foreach (var item in response.Content.Headers)
headers[item.Key] = item.Value;
}
ProcessResponse(client, response);
var status = (int) response.StatusCode;
if (status == (int) HttpStatusCode.NotFound) {
string responseText = (response.Content == null) ? string.Empty :
#if NET6_0_OR_GREATER
await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
#else
await response.Content.ReadAsStringAsync().ConfigureAwait(false);
#endif
throw new ApiException("A server side error occurred.", status, responseText, headers, null);
} else if (status is (int) HttpStatusCode.OK or (int) HttpStatusCode.NoContent) {
using var fs = File.Create(localFilePath);
if (response.Content != null) {
#if NET6_0_OR_GREATER
await response.Content.CopyToAsync(fs, cancellationToken);
#else
await response.Content.CopyToAsync(fs);
#endif
}
return;
} else {
var responseData = response.Content == null ? null :
#if NET6_0_OR_GREATER
await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
#else
await response.Content.ReadAsStringAsync().ConfigureAwait(false);
#endif
throw new ApiException(
"The HTTP status code of the response was not expected (" + status + ").",
status,
responseData,
headers,
null);
}
}
}

View File

@@ -1,4 +1,6 @@
extern alias HttpFormatting;
// ReSharper disable UseAwaitUsing
extern alias HttpFormatting;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Extensions.Msal;
using NuGet.Versioning;
@@ -12,9 +14,7 @@ using Velopack.Packaging;
using Velopack.Util;
using System.Net;
#if NET6_0_OR_GREATER
using System.Net.Http.Json;
#else
#if !NET6_0_OR_GREATER
using System.Net.Http;
#endif
@@ -73,9 +73,8 @@ public class VelopackFlowServiceClient(
{
loginOptions ??= new VelopackFlowLoginOptions();
FlowApi client = GetFlowApi();
var serviceUrl = Options.VelopackBaseUrl ?? client.BaseUrl;
if (!suppressOutput) {
Logger.LogInformation("Preparing to login to Velopack ({serviceUrl})", serviceUrl);
Logger.LogInformation("Preparing to login to Velopack ({serviceUrl})", client.BaseUrl);
}
var authConfiguration = await GetAuthConfigurationAsync(client, cancellationToken);
@@ -210,7 +209,6 @@ public class VelopackFlowServiceClient(
$"Uploading {Path.GetFileName(filePath)}",
async (report) => {
await UploadReleaseAssetAsync(
client,
filePath,
releaseGroup.Id,
fileType,
@@ -227,15 +225,10 @@ public class VelopackFlowServiceClient(
ZipPackage? prevZip = await progress.RunTask(
$"Downloading delta base for {version}",
async (report) => {
await DownloadLatestRelease(client, packageId, channel, prevVersion, report, cancellationToken);
if (File.Exists(prevVersion)) {
return new ZipPackage(prevVersion);
}
return null;
return await DownloadLatestRelease(packageId, channel, prevVersion, report, cancellationToken);
});
if (prevZip is not null) {
if (prevZip.Version! >= version) {
throw new InvalidOperationException(
$"Latest version in channel {channel} is greater than or equal to local (remote={prevZip.Version}, local={version})");
@@ -260,7 +253,6 @@ public class VelopackFlowServiceClient(
$"Uploading {Path.GetFileName(deltaPath)}",
async (report) => {
await UploadReleaseAssetAsync(
client,
deltaPath,
releaseGroup.Id,
FileType.Release,
@@ -302,11 +294,18 @@ public class VelopackFlowServiceClient(
}
private static async Task DownloadLatestRelease(FlowApi client, string packageId, string channel, string localPath, Action<int> progress, CancellationToken cancellationToken)
private async Task<ZipPackage?> DownloadLatestRelease(string packageId, string channel, string localPath, Action<int> progress,
CancellationToken cancellationToken)
{
try {
await client.DownloadInstallerLatestToFileAsync(packageId, channel, DownloadAssetType.Full, localPath, cancellationToken);
} catch (ApiException e) when (e.StatusCode == (int) HttpStatusCode.NotFound) { }
var client = GetFlowApi(progress);
using var localFile = File.Create(localPath);
using var file = await client.DownloadInstallerLatestAsync(packageId, channel, DownloadAssetType.Full, cancellationToken);
await file.Stream.CopyToAsync(localFile, 81920, cancellationToken).ConfigureAwait(false);
return new ZipPackage(localPath);
} catch (ApiException e) when (e.StatusCode == (int) HttpStatusCode.NotFound) {
return null;
}
}
private async Task WaitUntilReleaseGroupLive(FlowApi client, Guid releaseGroupId, CancellationToken cancellationToken)
@@ -338,7 +337,8 @@ public class VelopackFlowServiceClient(
await client.CreateChannelAsync(request, cancellationToken);
}
private static async Task<ReleaseGroup> CreateReleaseGroupAsync(FlowApi client, string packageId, SemanticVersion version, string channel, CancellationToken cancellationToken)
private static async Task<ReleaseGroup> CreateReleaseGroupAsync(FlowApi client, string packageId, SemanticVersion version, string channel,
CancellationToken cancellationToken)
{
CreateReleaseGroupRequest request = new() {
ChannelIdentifier = channel,
@@ -349,9 +349,10 @@ public class VelopackFlowServiceClient(
return await client.CreateReleaseGroupAsync(request, cancellationToken);
}
private static async Task UploadReleaseAssetAsync(FlowApi client, string filePath, Guid releaseGroupId, FileType fileType, Action<int> progress,
private async Task UploadReleaseAssetAsync(string filePath, Guid releaseGroupId, FileType fileType, Action<int> progress,
CancellationToken cancellationToken)
{
var client = GetFlowApi(progress);
using var stream = File.OpenRead(filePath);
var file = new FileParameter(stream);
await client.UploadReleaseAsync(releaseGroupId, fileType, file, cancellationToken);