diff --git a/src/console/CommandTree/DefaultCommandTree.cs b/src/console/CommandTree/DefaultCommandTree.cs index 0eeeaf5..fd57fdd 100644 --- a/src/console/CommandTree/DefaultCommandTree.cs +++ b/src/console/CommandTree/DefaultCommandTree.cs @@ -26,6 +26,7 @@ namespace Shamir.Console { if (command.Name == args[0]) { + command.Initialize(args[1..]); return command; } } diff --git a/src/console/CommandTree/DefaultHelpTextCommand.cs b/src/console/CommandTree/DefaultHelpTextCommand.cs index bd078fe..fc746d9 100644 --- a/src/console/CommandTree/DefaultHelpTextCommand.cs +++ b/src/console/CommandTree/DefaultHelpTextCommand.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Immutable; using System.Threading.Tasks; @@ -15,7 +16,11 @@ namespace Shamir.Console public IImmutableStack Path { get; } - public ValueTask ExecuteAsync() + public void Initialize(ReadOnlySpan args) + { + } + + public ValueTask ExecuteAsync(IServiceProvider serviceProvider) { System.Console.Error.WriteLine(GetHelpText()); return ValueTask.FromResult(1); // TODO: const diff --git a/src/console/CommandTree/ICommand.cs b/src/console/CommandTree/ICommand.cs index 308b031..e2e1356 100644 --- a/src/console/CommandTree/ICommand.cs +++ b/src/console/CommandTree/ICommand.cs @@ -1,9 +1,11 @@ +using System; using System.Threading.Tasks; namespace Shamir.Console { public interface ICommand : IOperationsNode { - ValueTask ExecuteAsync(); + void Initialize(ReadOnlySpan args); + ValueTask ExecuteAsync(IServiceProvider serviceProvider); } } \ No newline at end of file diff --git a/src/console/Commands/Cdn/StorageLsCommand.cs b/src/console/Commands/Cdn/StorageLsCommand.cs new file mode 100644 index 0000000..2a312cf --- /dev/null +++ b/src/console/Commands/Cdn/StorageLsCommand.cs @@ -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 : ICommand + { + public abstract string Name { get; } + public abstract string Description { get; } + public ImmutableArray Arguments { get; private set; } + + public void Initialize(ReadOnlySpan args) + { + var array = ImmutableArray.CreateBuilder(args.Length); + foreach (var arg in args) + { + array.Add(arg); + } + Arguments = array.MoveToImmutable(); + } + + public async ValueTask ExecuteAsync(IServiceProvider serviceProvider) + { + using var parser = serviceProvider.GetRequiredService(); + var result = parser.ParseArguments(Arguments); + return await result.MapResult( + options => ExecuteAsync(serviceProvider, options), + errors => ValueTask.FromResult(1) + ); + } + + public abstract ValueTask 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 + { + public override string Name => "ls"; + + public override string Description => "List files in an Azure Storage account."; + + public override async ValueTask 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; + } + } +} \ No newline at end of file diff --git a/src/console/Program.cs b/src/console/Program.cs index 30dee75..58028f9 100644 --- a/src/console/Program.cs +++ b/src/console/Program.cs @@ -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 Main(string[] args) { + await using var serviceProvider = new ServiceCollection() + .AddTransient(sp => new Parser(with => with.EnableDashDash = true)) + .BuildServiceProvider(); + var tree = new DefaultCommandTree( "shamir", "command-line multitool", ImmutableArray.Create( - + new DefaultCommandTree( + "cdn", + "Browse and add new data to a CDN backed by Azure Storage", + ImmutableArray.Empty, + ImmutableArray.Create( + new StorageLsCommand() + )) ), - ImmutableArray.Create( - - ) + ImmutableArray.Empty ); var command = tree.FindCommand(args); - return await command.ExecuteAsync(); + + using var scope = serviceProvider.CreateScope(); + return await command.ExecuteAsync(scope.ServiceProvider); } } } diff --git a/src/console/shamir.csproj b/src/console/shamir.csproj index 1d465ec..4a2c32c 100644 --- a/src/console/shamir.csproj +++ b/src/console/shamir.csproj @@ -9,7 +9,9 @@ + + diff --git a/tests/console.tests/CommandTreeTests.cs b/tests/console.tests/CommandTreeTests.cs index aa93565..68db60a 100644 --- a/tests/console.tests/CommandTreeTests.cs +++ b/tests/console.tests/CommandTreeTests.cs @@ -83,7 +83,9 @@ Commands: public string Name { get; } public string Description { get; } - public ValueTask ExecuteAsync() => ValueTask.FromResult(0); + + public void Initialize(ReadOnlySpan args) { } + public ValueTask ExecuteAsync(IServiceProvider serviceProvider) => ValueTask.FromResult(0); } } } \ No newline at end of file