implement "cdn ls" via CommandLineParser

This commit is contained in:
Yaakov 2021-09-26 00:07:48 +10:00
parent 74c7070e38
commit a4f9f13780
7 changed files with 113 additions and 8 deletions

View file

@ -26,6 +26,7 @@ namespace Shamir.Console
{
if (command.Name == args[0])
{
command.Initialize(args[1..]);
return command;
}
}

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
@ -15,7 +16,11 @@ namespace Shamir.Console
public IImmutableStack<ICommandTree> Path { get; }
public ValueTask<int> ExecuteAsync()
public void Initialize(ReadOnlySpan<string> args)
{
}
public ValueTask<int> ExecuteAsync(IServiceProvider serviceProvider)
{
System.Console.Error.WriteLine(GetHelpText());
return ValueTask.FromResult(1); // TODO: const

View file

@ -1,9 +1,11 @@
using System;
using System.Threading.Tasks;
namespace Shamir.Console
{
public interface ICommand : IOperationsNode
{
ValueTask<int> ExecuteAsync();
void Initialize(ReadOnlySpan<string> args);
ValueTask<int> ExecuteAsync(IServiceProvider serviceProvider);
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Azure.Storage.Blobs;
using CommandLine;
using Microsoft.Extensions.DependencyInjection;
namespace Shamir.Console
{
public abstract class ParsedArgumentsCommand<TOptions> : ICommand
{
public abstract string Name { get; }
public abstract string Description { get; }
public ImmutableArray<string> Arguments { get; private set; }
public void Initialize(ReadOnlySpan<string> args)
{
var array = ImmutableArray.CreateBuilder<string>(args.Length);
foreach (var arg in args)
{
array.Add(arg);
}
Arguments = array.MoveToImmutable();
}
public async ValueTask<int> ExecuteAsync(IServiceProvider serviceProvider)
{
using var parser = serviceProvider.GetRequiredService<Parser>();
var result = parser.ParseArguments<TOptions>(Arguments);
return await result.MapResult(
options => ExecuteAsync(serviceProvider, options),
errors => ValueTask.FromResult(1)
);
}
public abstract ValueTask<int> ExecuteAsync(IServiceProvider serviceProvider, TOptions options);
}
public class StorageLsOptions
{
[Option("connection-string", Required = false)]
public string? ConnectionString { get; set; }
[Value(0)]
public string? ContainerName { get; set; }
}
public sealed class StorageLsCommand : ParsedArgumentsCommand<StorageLsOptions>
{
public override string Name => "ls";
public override string Description => "List files in an Azure Storage account.";
public override async ValueTask<int> ExecuteAsync(IServiceProvider serviceProvider, StorageLsOptions options)
{
var connectionString = options.ConnectionString ?? Environment.GetEnvironmentVariable("AZURE_CONNECTION_STRING");
if (options.ContainerName is null)
{
var client = new BlobServiceClient(connectionString);
await foreach (var container in client.GetBlobContainersAsync())
{
System.Console.WriteLine(container.Name);
}
}
else
{
var client = new BlobContainerClient(connectionString, options.ContainerName);
await foreach (var blob in client.GetBlobsAsync())
{
System.Console.Write(options.ContainerName);
System.Console.Write('/');
System.Console.WriteLine(blob.Name);
}
}
return 0;
}
}
}

View file

@ -1,5 +1,7 @@
using System.Collections.Immutable;
using System.Threading.Tasks;
using CommandLine;
using Microsoft.Extensions.DependencyInjection;
namespace Shamir.Console
{
@ -7,19 +9,29 @@ namespace Shamir.Console
{
public static async Task<int> Main(string[] args)
{
await using var serviceProvider = new ServiceCollection()
.AddTransient<Parser>(sp => new Parser(with => with.EnableDashDash = true))
.BuildServiceProvider();
var tree = new DefaultCommandTree(
"shamir",
"command-line multitool",
ImmutableArray.Create<ICommandTree>(
new DefaultCommandTree(
"cdn",
"Browse and add new data to a CDN backed by Azure Storage",
ImmutableArray<ICommandTree>.Empty,
ImmutableArray.Create<ICommand>(
new StorageLsCommand()
))
),
ImmutableArray.Create<ICommand>(
)
ImmutableArray<ICommand>.Empty
);
var command = tree.FindCommand(args);
return await command.ExecuteAsync();
using var scope = serviceProvider.CreateScope();
return await command.ExecuteAsync(scope.ServiceProvider);
}
}
}

View file

@ -9,7 +9,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.10.0" />
<PackageReference Include="CommandLineParser" Version="2.8.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
</ItemGroup>
</Project>

View file

@ -83,7 +83,9 @@ Commands:
public string Name { get; }
public string Description { get; }
public ValueTask<int> ExecuteAsync() => ValueTask.FromResult(0);
public void Initialize(ReadOnlySpan<string> args) { }
public ValueTask<int> ExecuteAsync(IServiceProvider serviceProvider) => ValueTask.FromResult(0);
}
}
}