Skip to content

Commit

Permalink
Merge pull request #2 from Etherna/feature/EGC-5-upload-directory
Browse files Browse the repository at this point in the history
implement upload of directories
  • Loading branch information
tmm360 authored Jul 2, 2024
2 parents 790e8d2 + 0d7a10a commit 6be25c6
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 35 deletions.
3 changes: 3 additions & 0 deletions EthernaGatewayCli.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
.github\workflows\publish-stable.yml = .github\workflows\publish-stable.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{061B4436-4F7D-4A14-8625-AE5930821F3B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -28,5 +30,6 @@ Global
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6DD03B58-3404-41AD-B84D-E43E600C54F3} = {D3B7E18B-46F8-4072-9D14-801FDB15868C}
{F348B863-6892-45AD-AC33-3AD833A14BBB} = {061B4436-4F7D-4A14-8625-AE5930821F3B}
EndGlobalSection
EndGlobal
45 changes: 29 additions & 16 deletions src/EthernaGatewayCli/Commands/Etherna/UploadCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ public UploadCommand(
}

// Properties.
public override string CommandArgsHelpString => "SOURCE_FILE [SOURCE_FILE ...]";
public override string Description => "Upload a file resource to Swarm";
public override string CommandArgsHelpString => "SOURCE [SOURCE ...]";
public override string Description => "Upload files and directories to Swarm";

// Methods.
protected override async Task ExecuteAsync(string[] commandArgs)
Expand All @@ -59,45 +59,58 @@ protected override async Task ExecuteAsync(string[] commandArgs)
// Parse args.
if (commandArgs.Length < 1)
throw new ArgumentException("Upload requires 1 or more arguments");
var filePaths = commandArgs;
var paths = commandArgs;

// Authenticate user.
await authService.SignInAsync();

// Search files and calculate required postage batch depth.
var batchDepth = await gatewayService.CalculatePostageBatchDepthAsync(filePaths);
var batchDepth = await gatewayService.CalculatePostageBatchDepthAsync(paths);

// Identify postage batch to use.
var postageBatchId = await GetUsablePostageBatchIdAsync(batchDepth);

// Upload file.
foreach (var filePath in filePaths)
foreach (var path in paths)
{
IoService.WriteLine($"Uploading {filePath}...");
IoService.WriteLine($"Uploading {path}...");

var uploadSucceeded = false;
SwarmHash hash = default!;
for (int i = 0; i < UploadMaxRetry && !uploadSucceeded; i++)
{
try
{
await using var fileStream = File.OpenRead(filePath);
var mimeType = fileService.GetMimeType(filePath);
if(File.Exists(path)) //is a file
{
await using var fileStream = File.OpenRead(path);
var mimeType = fileService.GetMimeType(path);

hash = await gatewayService.UploadFileAsync(
postageBatchId,
fileStream,
Path.GetFileName(path),
mimeType,
Options.PinResource);
}
else if (Directory.Exists(path)) //is a directory
{
hash = await gatewayService.UploadDirectoryAsync(
postageBatchId,
path,
Options.PinResource);
}
else //invalid path
throw new InvalidOperationException($"Path {path} is not valid");

hash = await gatewayService.UploadFileAsync(
postageBatchId,
fileStream,
Path.GetFileName(filePath),
mimeType,
Options.PinResource);
IoService.WriteLine($"Hash: {hash}");

uploadSucceeded = true;
}
#pragma warning disable CA1031
catch (Exception e)
{
IoService.WriteErrorLine($"Error uploading {filePath}");
IoService.WriteErrorLine($"Error uploading {path}");
IoService.WriteLine(e.ToString());

if (i + 1 < UploadMaxRetry)
Expand All @@ -110,7 +123,7 @@ protected override async Task ExecuteAsync(string[] commandArgs)
}

if (!uploadSucceeded)
IoService.WriteErrorLine($"Can't upload \"{filePath}\" after {UploadMaxRetry} retries");
IoService.WriteErrorLine($"Can't upload \"{path}\" after {UploadMaxRetry} retries");
else if (Options.OfferDownload)
{
#pragma warning disable CA1031
Expand Down
2 changes: 1 addition & 1 deletion src/EthernaGatewayCli/EthernaGatewayCli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="EthernaSdk.Users.Native" Version="0.4.0-alpha.53" />
<PackageReference Include="EthernaSdk.Users.Native" Version="0.4.0-alpha.56" />
<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
53 changes: 36 additions & 17 deletions src/EthernaGatewayCli/Services/GatewayService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,40 @@ public async Task<int> CalculatePostageBatchDepthAsync(byte[] fileData, string f
.RequiredPostageBatchDepth;

[SuppressMessage("Performance", "CA1851:Possible multiple enumerations of \'IEnumerable\' collection")]
public async Task<int> CalculatePostageBatchDepthAsync(IEnumerable<string> filePaths)
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
public async Task<int> CalculatePostageBatchDepthAsync(IEnumerable<string> paths)
{
ArgumentNullException.ThrowIfNull(filePaths, nameof(filePaths));
if (!filePaths.Any())
throw new ArgumentOutOfRangeException(nameof(filePaths), "Empty file paths");
ArgumentNullException.ThrowIfNull(paths, nameof(paths));
if (!paths.Any())
throw new ArgumentOutOfRangeException(nameof(paths), "Empty file paths");

ioService.Write("Calculating required postage batch depth... ");

var buckets = new uint[PostageBuckets.BucketsSize];
var stampIssuer = new PostageStampIssuer(PostageBatch.MaxDepthInstance, buckets);
UploadEvaluationResult lastResult = null!;
foreach (var filePath in filePaths)
foreach (var path in paths)
{
if (!File.Exists(filePath))
throw new InvalidOperationException($"File {filePath} doesn't exist");

await using var fileStream = File.OpenRead(filePath);
var mimeType = fileService.GetMimeType(filePath);
var fileName = Path.GetFileName(filePath);

lastResult = await calculatorService.EvaluateFileUploadAsync(
fileStream,
mimeType,
fileName,
postageStampIssuer: stampIssuer);
if (File.Exists(path)) //is a file
{
await using var fileStream = File.OpenRead(path);
var mimeType = fileService.GetMimeType(path);
var fileName = Path.GetFileName(path);

lastResult = await calculatorService.EvaluateFileUploadAsync(
fileStream,
mimeType,
fileName,
postageStampIssuer: stampIssuer);
}
else if (Directory.Exists(path)) //is a directory
{
lastResult = await calculatorService.EvaluateDirectoryUploadAsync(
path,
postageStampIssuer: stampIssuer);
}
else //invalid path
throw new InvalidOperationException($"Path {path} is not valid");
}

ioService.WriteLine("Done");
Expand Down Expand Up @@ -151,6 +160,16 @@ public Task<SwarmHash> UploadFileAsync(
swarmDeferredUpload: true,
swarmPin: pinResource);

public Task<SwarmHash> UploadDirectoryAsync(
PostageBatchId batchId,
string directoryPath,
bool pinResource) =>
ethernaGatewayClient.UploadDirectoryAsync(
batchId,
directoryPath,
swarmDeferredUpload: true,
swarmPin: pinResource);

// Helpers.
private async Task WaitForBatchUsableAsync(PostageBatchId batchId)
{
Expand Down
15 changes: 14 additions & 1 deletion src/EthernaGatewayCli/Services/IGatewayService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,31 @@ namespace Etherna.GatewayCli.Services
public interface IGatewayService
{
Task<int> CalculatePostageBatchDepthAsync(Stream fileStream, string fileContentType, string fileName);

Task<int> CalculatePostageBatchDepthAsync(byte[] fileData, string fileContentType, string fileName);
Task<int> CalculatePostageBatchDepthAsync(IEnumerable<string> filePaths);

Task<int> CalculatePostageBatchDepthAsync(IEnumerable<string> paths);

Task<PostageBatchId> CreatePostageBatchAsync(BzzBalance amount, int batchDepth, string? label);

Task FundResourceDownloadAsync(SwarmHash hash);

Task FundResourcePinningAsync(SwarmHash hash);

Task<BzzBalance> GetChainPriceAsync();

Task<PostageBatch> GetPostageBatchInfoAsync(PostageBatchId batchId);

Task<SwarmHash> UploadFileAsync(
PostageBatchId batchId,
Stream content,
string? name,
string? contentType,
bool pinResource);

Task<SwarmHash> UploadDirectoryAsync(
PostageBatchId batchId,
string directoryPath,
bool pinResource);
}
}

0 comments on commit 6be25c6

Please sign in to comment.