mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Remove B2 provider - the new S3 provider has more features and can be used with B2
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||
<PackageReference Include="System.Security.Cryptography.Algorithms" Version="4.3.1" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
<PackageReference Include="B2Net" Version="0.7.5" />
|
||||
<PackageReference Include="NuGet.Commands" Version="6.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -46,12 +46,10 @@ namespace Squirrel.CommandLine
|
||||
//{ "releasify", "Take an existing nuget package and convert it into a Squirrel release", new ReleasifyOptions(), Releasify },
|
||||
"",
|
||||
"[ Package Deployment / Syncing ]",
|
||||
{ "b2-down", "Download recent releases from BackBlaze B2", new SyncBackblazeOptions(), o => Download(new BackblazeRepository(o)) },
|
||||
{ "b2-up", "Upload releases to BackBlaze B2", new SyncBackblazeOptions(), o => Upload(new BackblazeRepository(o)) },
|
||||
{ "http-down", "Download recent releases from an HTTP source", new SyncHttpOptions(), o => Download(new SimpleWebRepository(o)) },
|
||||
{ "github-down", "Download recent releases from GitHub", new SyncGithubOptions(), o => Download(new GitHubRepository(o)) },
|
||||
{ "s3-down", "Download recent releases from a S3 bucket", new SyncS3Options(), o => Download(new S3Repository(o)) },
|
||||
{ "s3-up", "Upload recent releases to a S3 bucket", new SyncS3Options(), o => Upload(new S3Repository(o)) },
|
||||
{ "s3-down", "Download releases from S3 compatible API", new SyncS3Options(), o => Download(new S3Repository(o)) },
|
||||
{ "s3-up", "Upload releases to S3 compatible API", new SyncS3Options(), o => Upload(new S3Repository(o)) },
|
||||
{ "http-down", "Download releases from an HTTP source", new SyncHttpOptions(), o => Download(new SimpleWebRepository(o)) },
|
||||
{ "github-down", "Download releases from GitHub", new SyncGithubOptions(), o => Download(new GitHubRepository(o)) },
|
||||
//"",
|
||||
//"[ Examples ]",
|
||||
//$" {exeName} pack ",
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using B2Net;
|
||||
using B2Net.Models;
|
||||
|
||||
namespace Squirrel.CommandLine.Sync
|
||||
{
|
||||
internal class BackblazeRepository : IPackageRepository
|
||||
{
|
||||
private B2StorageProvider _b2;
|
||||
private DirectoryInfo releasesDir;
|
||||
public BackblazeRepository(SyncBackblazeOptions options)
|
||||
{
|
||||
_b2 = new B2StorageProvider(options.b2KeyId, options.b2AppKey, options.b2BucketId);
|
||||
releasesDir = new DirectoryInfo(options.releaseDir);
|
||||
}
|
||||
|
||||
public async Task DownloadRecentPackages()
|
||||
{
|
||||
Console.WriteLine("Downloading RELEASES");
|
||||
var releasesBytes = await _b2.DownloadFile("RELEASES");
|
||||
if (releasesBytes == null) {
|
||||
Console.WriteLine("Can't find RELEASES on remote. Nothing to download.");
|
||||
return;
|
||||
}
|
||||
|
||||
File.WriteAllBytes(Path.Combine(releasesDir.FullName, "RELEASES"), releasesBytes);
|
||||
|
||||
var releasesToDownload = ReleaseEntry.ParseReleaseFile(Encoding.UTF8.GetString(releasesBytes))
|
||||
.Where(x => !x.IsDelta)
|
||||
.OrderByDescending(x => x.Version)
|
||||
.Take(1)
|
||||
.Select(x => new {
|
||||
LocalPath = Path.Combine(releasesDir.FullName, x.Filename),
|
||||
Filename = x.Filename,
|
||||
});
|
||||
|
||||
foreach (var releaseToDownload in releasesToDownload) {
|
||||
Console.WriteLine("Downloading " + releaseToDownload.Filename);
|
||||
var bytes = await _b2.DownloadFile(releaseToDownload.Filename);
|
||||
File.WriteAllBytes(releaseToDownload.LocalPath, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UploadMissingPackages()
|
||||
{
|
||||
foreach (var f in releasesDir.GetFiles()) {
|
||||
await _b2.UploadFile(File.ReadAllBytes(f.FullName), f.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private class B2StorageProvider
|
||||
{
|
||||
private readonly B2Client _client;
|
||||
private List<B2File> _metadataCache;
|
||||
|
||||
public B2StorageProvider(string keyId, string appKey, string bucketId)
|
||||
{
|
||||
var options = new B2Options() {
|
||||
KeyId = keyId,
|
||||
ApplicationKey = appKey,
|
||||
BucketId = bucketId,
|
||||
PersistBucket = true
|
||||
};
|
||||
_client = new B2Client(options, authorizeOnInitialize: true);
|
||||
}
|
||||
|
||||
private async Task EnsureMetadata()
|
||||
{
|
||||
if (_metadataCache != null)
|
||||
return;
|
||||
|
||||
Console.WriteLine("Downloading b2 file metadata (only needs to be done once)");
|
||||
|
||||
_metadataCache = new List<B2File>();
|
||||
B2FileList list = null;
|
||||
do {
|
||||
if (list == null)
|
||||
list = await _client.Files.GetList();
|
||||
else
|
||||
list = await _client.Files.GetList(startFileName: list.NextFileName, maxFileCount: 100);
|
||||
|
||||
_metadataCache.AddRange(list.Files);
|
||||
}
|
||||
while (!String.IsNullOrEmpty(list.NextFileName));
|
||||
}
|
||||
|
||||
public async Task<byte[]> DownloadFile(string fileName)
|
||||
{
|
||||
Console.WriteLine("Downloading b2 file: " + fileName);
|
||||
await EnsureMetadata();
|
||||
fileName = fileName.Replace('\\', '/').TrimEnd('/');
|
||||
|
||||
var search = _metadataCache.FirstOrDefault(f => f.FileName.Equals(fileName, StringComparison.OrdinalIgnoreCase));
|
||||
if (search == null) return null;
|
||||
|
||||
var dl = await _client.Files.DownloadById(search.FileId);
|
||||
return dl?.FileData;
|
||||
}
|
||||
|
||||
public async Task UploadFile(byte[] bytes, string fileName)
|
||||
{
|
||||
Console.WriteLine("Uploading b2 file: " + fileName);
|
||||
await EnsureMetadata();
|
||||
fileName = fileName.Replace('\\', '/').TrimEnd('/');
|
||||
var sha1 = GetSHA1Checksum(bytes);
|
||||
|
||||
// if there is an identical file in the remote
|
||||
var nameMatch = _metadataCache.FirstOrDefault(f => f.FileName.Equals(fileName, StringComparison.OrdinalIgnoreCase));
|
||||
if (nameMatch != null && nameMatch.ContentSHA1.Equals(sha1, StringComparison.OrdinalIgnoreCase)) {
|
||||
Console.WriteLine($" File already exists in remote and sha1 hash matches (skipping)");
|
||||
return;
|
||||
}
|
||||
|
||||
// if a file has the same contents, but a different name, we can do a server-copy
|
||||
B2File uploaded;
|
||||
var sha1Match = _metadataCache.FirstOrDefault(f => f.ContentSHA1.Equals(sha1, StringComparison.OrdinalIgnoreCase));
|
||||
if (sha1Match != null) {
|
||||
Console.WriteLine($" File with different name but matching SHA1 found (copying server-side)");
|
||||
uploaded = await _client.Files.Copy(sha1Match.FileId, fileName);
|
||||
} else {
|
||||
// upload file, retry 3 times
|
||||
// also, if the file already exists, we need to delete the old version afterwards
|
||||
int retry = 3;
|
||||
while (true) {
|
||||
try {
|
||||
uploaded = await _client.Files.Upload(bytes, fileName);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
Console.WriteLine($" File upload failed ({e.Message}). Will try {retry} more times.");
|
||||
await Task.Delay(100);
|
||||
if (--retry < 0) throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we uploaded a file, and _also_ there was a name match, we should delete the old file as the contents were wrong
|
||||
if (nameMatch != null) {
|
||||
Console.WriteLine($" Existing file was updated, old version is being deleted");
|
||||
await _client.Files.Delete(nameMatch.FileId, nameMatch.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetSHA1Checksum(byte[] bytes)
|
||||
{
|
||||
var sha = System.Security.Cryptography.SHA1.Create();
|
||||
byte[] checksum = sha.ComputeHash(bytes);
|
||||
return BitConverter.ToString(checksum).Replace("-", String.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,27 +14,6 @@ namespace Squirrel.CommandLine
|
||||
}
|
||||
}
|
||||
|
||||
internal class SyncBackblazeOptions : BaseOptions
|
||||
{
|
||||
public string b2KeyId { get; private set; }
|
||||
public string b2AppKey { get; private set; }
|
||||
public string b2BucketId { get; private set; }
|
||||
|
||||
public SyncBackblazeOptions()
|
||||
{
|
||||
Add("b2BucketId=", v => b2BucketId = v);
|
||||
Add("b2keyid=", v => b2KeyId = v);
|
||||
Add("b2key=", v => b2AppKey = v);
|
||||
}
|
||||
|
||||
public override void Validate()
|
||||
{
|
||||
IsRequired(nameof(b2KeyId), nameof(b2AppKey), nameof(b2BucketId));
|
||||
Log.Warn("Provider 'b2' is being deprecated and will no longer be updated.");
|
||||
Log.Warn("The replacement is using the 's3' provider with BackBlaze B2 using the '--endpoint' option.");
|
||||
}
|
||||
}
|
||||
|
||||
internal class SyncS3Options : BaseOptions
|
||||
{
|
||||
public string keyId { get; private set; }
|
||||
|
||||
Reference in New Issue
Block a user