Remove B2 provider - the new S3 provider has more features and can be used with B2

This commit is contained in:
Caelan Sayler
2022-05-09 17:09:11 +01:00
parent 032f81be9b
commit a4908f5cd9
4 changed files with 4 additions and 184 deletions

View File

@@ -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>

View File

@@ -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 ",

View File

@@ -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);
}
}
}
}

View File

@@ -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; }