refactor: Reorganize config list command code

This is in preparation for changes to list template includes
json-serializing-nullable-fields-issue
Robert Dailey 9 months ago
parent 802a0466c5
commit 175aa6733b

@ -26,7 +26,12 @@ public static class CliSetup
{
config.SetDescription("Operations for configuration files");
config.AddCommand<ConfigCreateCommand>("create");
config.AddCommand<ConfigListCommand>("list");
config.AddBranch("list", list =>
{
list.SetDescription("List configuration files in various ways");
list.AddCommand<ConfigListLocalCommand>("local");
list.AddCommand<ConfigListTemplatesCommand>("templates");
});
});
cli.AddBranch("delete", delete =>

@ -1,60 +0,0 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Recyclarr.Cli.Console.Helpers;
using Recyclarr.Cli.Processors.Config;
using Recyclarr.TrashLib.Config.Listers;
using Recyclarr.TrashLib.Config.Parsing.ErrorHandling;
using Recyclarr.TrashLib.ExceptionTypes;
using Recyclarr.TrashLib.Repo;
using Spectre.Console.Cli;
namespace Recyclarr.Cli.Console.Commands;
[UsedImplicitly]
[Description("List configuration files in various ways.")]
public class ConfigListCommand : AsyncCommand<ConfigListCommand.CliSettings>
{
private readonly ILogger _log;
private readonly ConfigListProcessor _processor;
private readonly IMultiRepoUpdater _repoUpdater;
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
public class CliSettings : BaseCommandSettings
{
[CommandArgument(0, "[ListCategory]")]
[EnumDescription<ConfigCategory>(
"The type of configuration information to list. If not specified, defaults to 'local'.")]
public ConfigCategory ListCategory { get; [UsedImplicitly] init; } = ConfigCategory.Local;
}
public ConfigListCommand(ILogger log, ConfigListProcessor processor, IMultiRepoUpdater repoUpdater)
{
_log = log;
_processor = processor;
_repoUpdater = repoUpdater;
}
public override async Task<int> ExecuteAsync(CommandContext context, CliSettings settings)
{
try
{
await _repoUpdater.UpdateAllRepositories(settings.CancellationToken);
_processor.Process(settings.ListCategory);
}
catch (FileExistsException e)
{
_log.Error(
"The file {ConfigFile} already exists. Please choose another path or " +
"delete/move the existing file and run this command again", e.AttemptedPath);
return 1;
}
catch (NoConfigurationFilesException)
{
_log.Error("No configuration files found");
}
return 0;
}
}

@ -0,0 +1,46 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Recyclarr.Cli.Processors.Config;
using Recyclarr.TrashLib.Config.Parsing.ErrorHandling;
using Recyclarr.TrashLib.Repo;
using Spectre.Console.Cli;
namespace Recyclarr.Cli.Console.Commands;
[UsedImplicitly]
[Description("List local configuration files.")]
public class ConfigListLocalCommand : AsyncCommand<ConfigListLocalCommand.CliSettings>
{
private readonly ILogger _log;
private readonly ConfigListLocalProcessor _processor;
private readonly IMultiRepoUpdater _repoUpdater;
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
public class CliSettings : BaseCommandSettings
{
}
public ConfigListLocalCommand(ILogger log, ConfigListLocalProcessor processor, IMultiRepoUpdater repoUpdater)
{
_log = log;
_processor = processor;
_repoUpdater = repoUpdater;
}
public override async Task<int> ExecuteAsync(CommandContext context, CliSettings settings)
{
try
{
await _repoUpdater.UpdateAllRepositories(settings.CancellationToken);
_processor.Process();
return 0;
}
catch (NoConfigurationFilesException)
{
_log.Error("No configuration files found");
}
return 1;
}
}

@ -0,0 +1,46 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Recyclarr.Cli.Processors.Config;
using Recyclarr.TrashLib.Config.Parsing.ErrorHandling;
using Recyclarr.TrashLib.Repo;
using Spectre.Console.Cli;
namespace Recyclarr.Cli.Console.Commands;
[UsedImplicitly]
[Description("List local configuration files.")]
public class ConfigListTemplatesCommand : AsyncCommand<ConfigListTemplatesCommand.CliSettings>
{
private readonly ILogger _log;
private readonly ConfigListTemplateProcessor _processor;
private readonly IMultiRepoUpdater _repoUpdater;
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
public class CliSettings : BaseCommandSettings
{
}
public ConfigListTemplatesCommand(ILogger log, ConfigListTemplateProcessor processor, IMultiRepoUpdater repoUpdater)
{
_log = log;
_processor = processor;
_repoUpdater = repoUpdater;
}
public override async Task<int> ExecuteAsync(CommandContext context, CliSettings settings)
{
try
{
await _repoUpdater.UpdateAllRepositories(settings.CancellationToken);
_processor.Process();
return 0;
}
catch (NoConfigurationFilesException)
{
_log.Error("No configuration files found");
}
return 1;
}
}

@ -1,20 +1,21 @@
using System.IO.Abstractions;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Parsing;
using Recyclarr.TrashLib.Config.Services;
using Recyclarr.TrashLib.Startup;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Recyclarr.TrashLib.Config.Listers;
namespace Recyclarr.Cli.Processors.Config;
public class ConfigLocalLister : IConfigLister
public class ConfigListLocalProcessor
{
private readonly IAnsiConsole _console;
private readonly IConfigurationFinder _configFinder;
private readonly IConfigurationLoader _configLoader;
private readonly IAppPaths _paths;
public ConfigLocalLister(
public ConfigListLocalProcessor(
IAnsiConsole console,
IConfigurationFinder configFinder,
IConfigurationLoader configLoader,
@ -26,7 +27,7 @@ public class ConfigLocalLister : IConfigLister
_paths = paths;
}
public void List()
public void Process()
{
var tree = new Tree(_paths.AppDataDirectory.ToString()!);

@ -1,27 +0,0 @@
using Autofac.Features.Indexed;
using Recyclarr.TrashLib.Config.Listers;
namespace Recyclarr.Cli.Processors.Config;
public class ConfigListProcessor
{
private readonly ILogger _log;
private readonly IIndex<ConfigCategory, IConfigLister> _configListers;
public ConfigListProcessor(ILogger log, IIndex<ConfigCategory, IConfigLister> configListers)
{
_log = log;
_configListers = configListers;
}
public void Process(ConfigCategory listCategory)
{
_log.Debug("Listing configuration for category {Category}", listCategory);
if (!_configListers.TryGetValue(listCategory, out var lister))
{
throw new ArgumentOutOfRangeException(nameof(listCategory), listCategory, "Unknown list category");
}
lister.List();
}
}

@ -1,22 +1,26 @@
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Services;
using Spectre.Console;
namespace Recyclarr.TrashLib.Config.Listers;
namespace Recyclarr.Cli.Processors.Config;
public class ConfigTemplateLister : IConfigLister
public class ConfigListTemplateProcessor
{
private readonly IAnsiConsole _console;
private readonly IConfigTemplateGuideService _guideService;
public ConfigTemplateLister(
IAnsiConsole console,
IConfigTemplateGuideService guideService)
public ConfigListTemplateProcessor(IAnsiConsole console, IConfigTemplateGuideService guideService)
{
_console = console;
_guideService = guideService;
}
public void List()
public void Process()
{
ListTemplates();
}
private void ListTemplates()
{
var data = _guideService.LoadTemplateData();

@ -23,7 +23,8 @@ public class ServiceProcessorsAutofacModule : Module
// Configuration
builder.RegisterType<ConfigManipulator>().As<IConfigManipulator>();
builder.RegisterType<ConfigCreationProcessor>().As<IConfigCreationProcessor>();
builder.RegisterType<ConfigListProcessor>();
builder.RegisterType<ConfigListLocalProcessor>();
builder.RegisterType<ConfigListTemplateProcessor>();
// Delete
builder.RegisterType<DeleteCustomFormatsProcessor>().As<IDeleteCustomFormatsProcessor>();

@ -1,6 +1,5 @@
using Autofac;
using FluentValidation;
using Recyclarr.TrashLib.Config.Listers;
using Recyclarr.TrashLib.Config.Parsing;
using Recyclarr.TrashLib.Config.Parsing.PostProcessing;
using Recyclarr.TrashLib.Config.Secrets;
@ -33,10 +32,6 @@ public class ConfigAutofacModule : Module
builder.RegisterType<ConfigParser>();
builder.RegisterType<ConfigSaver>();
// Config Listers
builder.RegisterType<ConfigTemplateLister>().Keyed<IConfigLister>(ConfigCategory.Templates);
builder.RegisterType<ConfigLocalLister>().Keyed<IConfigLister>(ConfigCategory.Local);
// Config Post Processors
builder.RegisterType<ImplicitUrlAndKeyPostProcessor>().As<IConfigPostProcessor>();

@ -1,7 +0,0 @@
namespace Recyclarr.TrashLib.Config.Listers;
public enum ConfigCategory
{
Local,
Templates
}

@ -1,6 +0,0 @@
namespace Recyclarr.TrashLib.Config.Listers;
public interface IConfigLister
{
void List();
}

@ -11,9 +11,9 @@ public class ConfigCommandsIntegrationTest : CliIntegrationFixture
[Test, AutoMockData]
public async Task Repo_update_is_called_on_config_list(
[Frozen] IMultiRepoUpdater updater,
ConfigListCommand sut)
ConfigListLocalCommand sut)
{
await sut.ExecuteAsync(default!, new ConfigListCommand.CliSettings());
await sut.ExecuteAsync(default!, new ConfigListLocalCommand.CliSettings());
await updater.ReceivedWithAnyArgs().UpdateAllRepositories(default);
}

@ -1,25 +0,0 @@
using Recyclarr.Cli.Processors.Config;
using Recyclarr.TestLibrary.Autofac;
using Recyclarr.TrashLib.Config.Listers;
namespace Recyclarr.Cli.Tests.Processors;
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class ConfigListProcessorTest
{
[Test]
[InlineAutoMockData(ConfigCategory.Templates)]
public void List_templates_invokes_correct_lister(
ConfigCategory category,
[Frozen(Matching.ImplementedInterfaces)] StubAutofacIndex<ConfigCategory, IConfigLister> configListers,
IConfigLister lister,
ConfigListProcessor sut)
{
configListers.Add(category, lister);
sut.Process(category);
lister.Received().List();
}
}

@ -1,11 +1,11 @@
using System.IO.Abstractions;
using Recyclarr.Cli.Processors.Config;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Config.Listers;
using Recyclarr.TrashLib.Config.Services;
using Recyclarr.TrashLib.TestLibrary;
using Spectre.Console.Testing;
namespace Recyclarr.TrashLib.Tests.Config.Listers;
namespace Recyclarr.Cli.Tests.Processors;
[TestFixture]
[Parallelizable(ParallelScope.All)]
@ -16,7 +16,7 @@ public class ConfigTemplateListerTest : TrashLibIntegrationFixture
IFileInfo stubFile,
[Frozen(Matching.ImplementedInterfaces)] TestConsole console,
[Frozen] IConfigTemplateGuideService guideService,
ConfigTemplateLister sut)
ConfigListTemplateProcessor sut)
{
guideService.LoadTemplateData().Returns(new[]
{
@ -26,7 +26,7 @@ public class ConfigTemplateListerTest : TrashLibIntegrationFixture
new TemplatePath {Id = "s2", TemplateFile = stubFile, Service = SupportedServices.Sonarr, Hidden = true}
});
sut.List();
sut.Process();
console.Output.Should().NotContain("s2");
}

@ -1,23 +0,0 @@
using Autofac.Features.Indexed;
using Recyclarr.TrashLib.Config.Listers;
using Recyclarr.TrashLib.TestLibrary;
namespace Recyclarr.TrashLib.Tests.Config;
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class ConfigAutofacModuleTest : TrashLibIntegrationFixture
{
private static IEnumerable<ConfigCategory> AllConfigListCategories()
{
return Enum.GetValues<ConfigCategory>();
}
[TestCaseSource(nameof(AllConfigListCategories))]
public void All_list_category_types_registered(ConfigCategory category)
{
var sut = Resolve<IIndex<ConfigCategory, IConfigLister>>();
var result = sut.TryGetValue(category, out _);
result.Should().BeTrue();
}
}
Loading…
Cancel
Save