diff --git a/CHANGELOG.md b/CHANGELOG.md index d9f21880..cdfcc6b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ changes you may need to make. lessens the need to redact information in the console. - **BREAKING**: `replace_existing_custom_formats` now defaults to `true`. - **BREAKING**: Restructured repository settings. +- Configuration templates repository moved to `recyclarr/config-templates` on GitHub. Corresponding + settings for this repo as well (see the Settings YAML Reference on the wiki for more details). ### Removed diff --git a/src/Recyclarr.Cli.Tests/BaseCommandSetupIntegrationTest.cs b/src/Recyclarr.Cli.Tests/BaseCommandSetupIntegrationTest.cs index e66e145c..13bcca13 100644 --- a/src/Recyclarr.Cli.Tests/BaseCommandSetupIntegrationTest.cs +++ b/src/Recyclarr.Cli.Tests/BaseCommandSetupIntegrationTest.cs @@ -1,6 +1,7 @@ using System.IO.Abstractions; using Recyclarr.Cli.Console.Setup; using Recyclarr.Cli.TestLibrary; +using Recyclarr.Common.TestLibrary; using Recyclarr.TrashLib.Settings; namespace Recyclarr.Cli.Tests; @@ -74,11 +75,11 @@ log_janitor: var expectedDirs = new[] { + Paths.CacheDirectory.FullName, Paths.LogDirectory.FullName, - Paths.RepoDirectory.FullName, - Paths.CacheDirectory.FullName + Paths.ConfigsDirectory.FullName }; - expectedDirs.Should().IntersectWith(Fs.AllDirectories); + Fs.LeafDirectories().Should().BeEquivalentTo(expectedDirs); } } diff --git a/src/Recyclarr.Cli.Tests/CompositionRootTest.cs b/src/Recyclarr.Cli.Tests/CompositionRootTest.cs index 19244559..1848e5a6 100644 --- a/src/Recyclarr.Cli.Tests/CompositionRootTest.cs +++ b/src/Recyclarr.Cli.Tests/CompositionRootTest.cs @@ -3,7 +3,10 @@ using System.Diagnostics.CodeAnalysis; using Autofac; using Autofac.Core; using NUnit.Framework.Internal; -using Recyclarr.Cli.TestLibrary; +using Recyclarr.TestLibrary.Autofac; +using Recyclarr.TrashLib.Startup; +using Serilog.Core; +using Spectre.Console; namespace Recyclarr.Cli.Tests; @@ -14,17 +17,26 @@ public class CompositionRootTest // Warning CA1812 : CompositionRootTest.ConcreteTypeEnumerator is an internal class that is apparently never // instantiated. [SuppressMessage("Performance", "CA1812", Justification = "Created via reflection by TestCaseSource attribute")] - private sealed class ConcreteTypeEnumerator : CliIntegrationFixture, IEnumerable + private sealed class ConcreteTypeEnumerator : IEnumerable { public IEnumerator GetEnumerator() { - return Container.ComponentRegistry.Registrations + var builder = new ContainerBuilder(); + CompositionRoot.Setup(builder); + CompositionRoot.RegisterExternal(builder, new LoggingLevelSwitch(), new AppDataPathProvider()); + + // These are things that Spectre.Console normally registers for us, so they won't explicitly be + // in the CompositionRoot. Register mocks/stubs here. + builder.RegisterMockFor(); + + var container = builder.Build(); + return container.ComponentRegistry.Registrations .SelectMany(x => x.Services) .OfType() .Select(x => x.ServiceType) .Distinct() .Where(x => x.FullName == null || !x.FullName.StartsWith("Autofac.")) - .Select(x => new TestCaseParameters(new object[] {Container, x}) {TestName = x.FullName}) + .Select(x => new TestCaseParameters(new object[] {container, x}) {TestName = x.FullName}) .GetEnumerator(); } } diff --git a/src/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Guide/CustomFormatCategoryParserTest.cs b/src/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Guide/CustomFormatCategoryParserTest.cs index cd369a4e..736873e7 100644 --- a/src/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Guide/CustomFormatCategoryParserTest.cs +++ b/src/Recyclarr.Cli.Tests/Pipelines/CustomFormat/Guide/CustomFormatCategoryParserTest.cs @@ -1,4 +1,5 @@ using System.IO.Abstractions; +using System.IO.Abstractions.Extensions; using Recyclarr.Cli.Pipelines.CustomFormat.Guide; using Recyclarr.TestLibrary.AutoFixture; using Recyclarr.TrashLib.Startup; @@ -50,7 +51,7 @@ public class CustomFormatCategoryParserTest ------ "; - var file = paths.RepoDirectory + var file = fs.CurrentDirectory() .SubDirectory("docs") .SubDirectory("Radarr") .File("Radarr-collection-of-custom-formats.md"); diff --git a/src/Recyclarr.Cli.Tests/Pipelines/QualitySize/Guide/QualityGuideServiceTest.cs b/src/Recyclarr.Cli.Tests/Pipelines/QualitySize/Guide/QualityGuideServiceTest.cs index 1eb0147b..5610e52b 100644 --- a/src/Recyclarr.Cli.Tests/Pipelines/QualitySize/Guide/QualityGuideServiceTest.cs +++ b/src/Recyclarr.Cli.Tests/Pipelines/QualitySize/Guide/QualityGuideServiceTest.cs @@ -4,6 +4,7 @@ using Recyclarr.Cli.TestLibrary; using Recyclarr.Common.Extensions; using Recyclarr.Common.TestLibrary; using Recyclarr.TrashLib.Config; +using Recyclarr.TrashLib.Repo; namespace Recyclarr.Cli.Tests.Pipelines.QualitySize.Guide; @@ -15,8 +16,23 @@ public class QualityGuideServiceTest : CliIntegrationFixture [TestCase(SupportedServices.Radarr, "radarr")] public void Get_data_for_service(SupportedServices service, string serviceDir) { + var repo = Resolve(); + const string metadataJson = @" +{ + 'json_paths': { + 'radarr': { + 'qualities': ['docs/json/radarr/quality-size'] + }, + 'sonarr': { + 'qualities': ['docs/json/sonarr/quality-size'] + } + } +}"; + + Fs.AddFile(repo.Path.File("metadata.json"), new MockFileData(metadataJson)); + Fs.AddFileFromEmbeddedResource( - Paths.RepoDirectory.SubDir("docs", "json", serviceDir, "quality-size").File("metadata.json"), + repo.Path.SubDir("docs", "json", serviceDir, "quality-size").File("some-quality-size.json"), GetType(), "Data.quality_size.json"); diff --git a/src/Recyclarr.Cli.Tests/ServiceCompatibilityIntegrationTest.cs b/src/Recyclarr.Cli.Tests/ServiceCompatibilityIntegrationTest.cs index 102bb99c..3159ed19 100644 --- a/src/Recyclarr.Cli.Tests/ServiceCompatibilityIntegrationTest.cs +++ b/src/Recyclarr.Cli.Tests/ServiceCompatibilityIntegrationTest.cs @@ -10,20 +10,20 @@ public class ServiceCompatibilityIntegrationTest : CliIntegrationFixture [Test] public void Load_settings_yml_correctly_when_file_exists() { - var sut = Resolve(); - + var sut = Resolve(); // For this test, it doesn't really matter if the YAML data matches what SettingsValue expects. // This test only ensures that the data deserialized is from the actual correct file. const string yamlData = @" repositories: - trash_guide: + trash_guides: clone_url: http://the_url.com "; - Fs.AddFile(Paths.SettingsPath.FullName, new MockFileData(yamlData)); + Fs.AddFile(Paths.SettingsPath, new MockFileData(yamlData)); + Paths.SettingsPath.Refresh(); var settings = sut.Settings; - settings.Repositories.TrashGuide.CloneUrl.Should().Be("http://the_url.com"); + settings.Repositories.TrashGuides.CloneUrl.Should().Be("http://the_url.com"); } } diff --git a/src/Recyclarr.Cli/CompositionRoot.cs b/src/Recyclarr.Cli/CompositionRoot.cs index e8455bdd..6b3e6027 100644 --- a/src/Recyclarr.Cli/CompositionRoot.cs +++ b/src/Recyclarr.Cli/CompositionRoot.cs @@ -19,6 +19,8 @@ using Recyclarr.Cli.Processors; using Recyclarr.Common; using Recyclarr.TrashLib; using Recyclarr.TrashLib.Interfaces; +using Recyclarr.TrashLib.Startup; +using Serilog.Core; using Spectre.Console.Cli; namespace Recyclarr.Cli; @@ -87,4 +89,13 @@ public static class CompositionRoot builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) .AssignableTo(); } + + public static void RegisterExternal( + ContainerBuilder builder, + LoggingLevelSwitch logLevelSwitch, + AppDataPathProvider appDataPathProvider) + { + builder.RegisterInstance(logLevelSwitch); + builder.RegisterInstance(appDataPathProvider); + } } diff --git a/src/Recyclarr.Cli/Console/Commands/ListCustomFormatsCommand.cs b/src/Recyclarr.Cli/Console/Commands/ListCustomFormatsCommand.cs index 5edf02a6..82ec54f6 100644 --- a/src/Recyclarr.Cli/Console/Commands/ListCustomFormatsCommand.cs +++ b/src/Recyclarr.Cli/Console/Commands/ListCustomFormatsCommand.cs @@ -5,7 +5,6 @@ using Recyclarr.Cli.Console.Helpers; using Recyclarr.Cli.Pipelines.CustomFormat.Guide; using Recyclarr.TrashLib.Config; using Recyclarr.TrashLib.Repo; -using Recyclarr.TrashLib.Settings; using Spectre.Console.Cli; #pragma warning disable CS8765 @@ -17,8 +16,7 @@ namespace Recyclarr.Cli.Console.Commands; internal class ListCustomFormatsCommand : AsyncCommand { private readonly CustomFormatDataLister _lister; - private readonly IRepoUpdater _repoUpdater; - private readonly ISettingsProvider _settings; + private readonly ITrashGuidesRepo _repo; [UsedImplicitly] [SuppressMessage("Design", "CA1034:Nested types should not be visible")] @@ -30,19 +28,15 @@ internal class ListCustomFormatsCommand : AsyncCommand ExecuteAsync(CommandContext context, CliSettings settings) { - await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide); + await _repo.Update(); _lister.ListCustomFormats(settings.Service); return 0; } diff --git a/src/Recyclarr.Cli/Console/Commands/ListQualitiesCommand.cs b/src/Recyclarr.Cli/Console/Commands/ListQualitiesCommand.cs index 0827c4b1..0367a1c5 100644 --- a/src/Recyclarr.Cli/Console/Commands/ListQualitiesCommand.cs +++ b/src/Recyclarr.Cli/Console/Commands/ListQualitiesCommand.cs @@ -5,7 +5,6 @@ using Recyclarr.Cli.Console.Helpers; using Recyclarr.Cli.Pipelines.QualitySize.Guide; using Recyclarr.TrashLib.Config; using Recyclarr.TrashLib.Repo; -using Recyclarr.TrashLib.Settings; using Spectre.Console.Cli; namespace Recyclarr.Cli.Console.Commands; @@ -16,8 +15,7 @@ namespace Recyclarr.Cli.Console.Commands; internal class ListQualitiesCommand : AsyncCommand { private readonly QualitySizeDataLister _lister; - private readonly IRepoUpdater _repoUpdater; - private readonly ISettingsProvider _settings; + private readonly ITrashGuidesRepo _repoUpdater; [UsedImplicitly] [SuppressMessage("Design", "CA1034:Nested types should not be visible")] @@ -29,16 +27,15 @@ internal class ListQualitiesCommand : AsyncCommand ExecuteAsync(CommandContext context, CliSettings settings) { - await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide); + await _repoUpdater.Update(); _lister.ListQualities(settings.Service); return 0; } diff --git a/src/Recyclarr.Cli/Console/Commands/ListReleaseProfilesCommand.cs b/src/Recyclarr.Cli/Console/Commands/ListReleaseProfilesCommand.cs index 00b664d4..5f8a8c20 100644 --- a/src/Recyclarr.Cli/Console/Commands/ListReleaseProfilesCommand.cs +++ b/src/Recyclarr.Cli/Console/Commands/ListReleaseProfilesCommand.cs @@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis; using JetBrains.Annotations; using Recyclarr.Cli.Pipelines.ReleaseProfile.Guide; using Recyclarr.TrashLib.Repo; -using Recyclarr.TrashLib.Settings; using Spectre.Console.Cli; #pragma warning disable CS8765 @@ -16,8 +15,7 @@ internal class ListReleaseProfilesCommand : AsyncCommand ExecuteAsync(CommandContext context, CliSettings settings) { try { - await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide); + await _repoUpdater.Update(); if (settings.ListTerms is not null) { diff --git a/src/Recyclarr.Cli/Console/Commands/SyncCommand.cs b/src/Recyclarr.Cli/Console/Commands/SyncCommand.cs index c1aa6226..14c89ecc 100644 --- a/src/Recyclarr.Cli/Console/Commands/SyncCommand.cs +++ b/src/Recyclarr.Cli/Console/Commands/SyncCommand.cs @@ -8,7 +8,6 @@ using Recyclarr.Cli.Migration; using Recyclarr.Cli.Processors; using Recyclarr.TrashLib.Config; using Recyclarr.TrashLib.Repo; -using Recyclarr.TrashLib.Settings; using Spectre.Console.Cli; namespace Recyclarr.Cli.Console.Commands; @@ -18,9 +17,8 @@ namespace Recyclarr.Cli.Console.Commands; public class SyncCommand : AsyncCommand { private readonly IMigrationExecutor _migration; - private readonly IRepoUpdater _repoUpdater; + private readonly ITrashGuidesRepo _repoUpdater; private readonly ISyncProcessor _syncProcessor; - private readonly ISettingsProvider _settings; [UsedImplicitly] [SuppressMessage("Design", "CA1034:Nested types should not be visible")] @@ -52,16 +50,11 @@ public class SyncCommand : AsyncCommand public IReadOnlyCollection Instances => InstancesOption; } - public SyncCommand( - IMigrationExecutor migration, - IRepoUpdater repoUpdater, - ISyncProcessor syncProcessor, - ISettingsProvider settings) + public SyncCommand(IMigrationExecutor migration, ITrashGuidesRepo repo, ISyncProcessor syncProcessor) { _migration = migration; - _repoUpdater = repoUpdater; + _repoUpdater = repo; _syncProcessor = syncProcessor; - _settings = settings; } [SuppressMessage("Design", "CA1031:Do not catch general exception types")] @@ -69,7 +62,7 @@ public class SyncCommand : AsyncCommand { // Will throw if migration is required, otherwise just a warning is issued. _migration.CheckNeededMigrations(); - await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide); + await _repoUpdater.Update(); return (int) await _syncProcessor.ProcessConfigs(settings); } diff --git a/src/Recyclarr.Cli/Processors/ConfigListProcessor.cs b/src/Recyclarr.Cli/Processors/ConfigListProcessor.cs index 6927e88f..da314985 100644 --- a/src/Recyclarr.Cli/Processors/ConfigListProcessor.cs +++ b/src/Recyclarr.Cli/Processors/ConfigListProcessor.cs @@ -1,5 +1,6 @@ using Autofac.Features.Indexed; using Recyclarr.TrashLib.Config.Listers; +using Recyclarr.TrashLib.Repo; namespace Recyclarr.Cli.Processors; @@ -7,15 +8,25 @@ public class ConfigListProcessor { private readonly ILogger _log; private readonly IIndex _configListers; + private readonly IConfigTemplatesRepo _repo; - public ConfigListProcessor(ILogger log, IIndex configListers) + public ConfigListProcessor( + ILogger log, + IIndex configListers, + IConfigTemplatesRepo repo) { _log = log; _configListers = configListers; + _repo = repo; } public async Task Process(ConfigListCategory listCategory) { + if (listCategory == ConfigListCategory.Templates) + { + await _repo.Update(); + } + _log.Debug("Listing configuration for category {Category}", listCategory); if (!_configListers.TryGetValue(listCategory, out var lister)) { diff --git a/src/Recyclarr.Cli/Program.cs b/src/Recyclarr.Cli/Program.cs index ae2d8947..9a6ac55d 100644 --- a/src/Recyclarr.Cli/Program.cs +++ b/src/Recyclarr.Cli/Program.cs @@ -24,10 +24,8 @@ internal static partial class Program CompositionRoot.Setup(builder); var logLevelSwitch = new LoggingLevelSwitch(); - builder.RegisterInstance(logLevelSwitch); - var appDataPathProvider = new AppDataPathProvider(); - builder.RegisterInstance(appDataPathProvider); + CompositionRoot.RegisterExternal(builder, logLevelSwitch, appDataPathProvider); var app = new CommandApp(new AutofacTypeRegistrar(builder, s => _scope = s)); app.Configure(config => diff --git a/src/Recyclarr.Common/Extensions/AutofacExtensions.cs b/src/Recyclarr.Common/Extensions/AutofacExtensions.cs index 90880e98..fa2515d1 100644 --- a/src/Recyclarr.Common/Extensions/AutofacExtensions.cs +++ b/src/Recyclarr.Common/Extensions/AutofacExtensions.cs @@ -1,4 +1,5 @@ using Autofac; +using Autofac.Builder; namespace Recyclarr.Common.Extensions; @@ -9,4 +10,16 @@ public static class AutofacExtensions var type = genericType.MakeGenericType(genericArgs); return scope.Resolve(type); } + + public static IRegistrationBuilder + WithTypeParameter( + this IRegistrationBuilder builder, + Type paramType, + Func resolver) + where TReflectionActivatorData : ReflectionActivatorData + { + return builder.WithParameter( + (info, _) => info.ParameterType == paramType, + (_, context) => resolver(context)); + } } diff --git a/src/Recyclarr.TrashLib.TestLibrary/Data/metadata.json b/src/Recyclarr.TrashLib.TestLibrary/Data/metadata.json deleted file mode 100644 index 7338b37a..00000000 --- a/src/Recyclarr.TrashLib.TestLibrary/Data/metadata.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "json_paths": { - "radarr": { - "custom_formats": ["docs/json/radarr/cf"], - "qualities": ["docs/json/radarr/quality-size"], - "naming": ["docs/json/radarr/naming"] - }, - "sonarr": { - "release_profiles": ["docs/json/sonarr/rp"], - "custom_formats": ["docs/json/sonarr/cf"], - "qualities": ["docs/json/sonarr/quality-size"], - "naming": ["docs/json/sonarr/naming"] - } - }, - "recyclarr": { - "templates": "docs/recyclarr-configs" - } -} diff --git a/src/Recyclarr.TrashLib.TestLibrary/TrashLibIntegrationFixture.cs b/src/Recyclarr.TrashLib.TestLibrary/TrashLibIntegrationFixture.cs index 2feef3e2..31414212 100644 --- a/src/Recyclarr.TrashLib.TestLibrary/TrashLibIntegrationFixture.cs +++ b/src/Recyclarr.TrashLib.TestLibrary/TrashLibIntegrationFixture.cs @@ -5,7 +5,6 @@ using Autofac.Features.ResolveAnything; using AutoMapper.Contrib.Autofac.DependencyInjection; using AutoMapper.EquivalencyExpression; using Recyclarr.Common; -using Recyclarr.Common.TestLibrary; using Recyclarr.TestLibrary.Autofac; using Recyclarr.TrashLib.ApiServices.System; using Recyclarr.TrashLib.Repo.VersionControl; @@ -28,8 +27,6 @@ public abstract class TrashLibIntegrationFixture : IDisposable Paths = new AppPaths(Fs.CurrentDirectory().SubDirectory("test").SubDirectory("recyclarr")); Logger = CreateLogger(); - SetupMetadataJson(); - _container = new Lazy(() => { var builder = new ContainerBuilder(); @@ -77,12 +74,6 @@ public abstract class TrashLibIntegrationFixture : IDisposable .CreateLogger(); } - private void SetupMetadataJson() - { - var metadataFile = Paths.RepoDirectory.File("metadata.json"); - Fs.AddFileFromEmbeddedResource(metadataFile, typeof(TrashLibIntegrationFixture), "Data.metadata.json"); - } - // ReSharper disable MemberCanBePrivate.Global private readonly Lazy _container; diff --git a/src/Recyclarr.TrashLib.Tests/Config/Listers/ConfigTemplateListerTest.cs b/src/Recyclarr.TrashLib.Tests/Config/Listers/ConfigTemplateListerTest.cs index c2729361..ad7d9f6d 100644 --- a/src/Recyclarr.TrashLib.Tests/Config/Listers/ConfigTemplateListerTest.cs +++ b/src/Recyclarr.TrashLib.Tests/Config/Listers/ConfigTemplateListerTest.cs @@ -18,7 +18,7 @@ public class ConfigTemplateListerTest : TrashLibIntegrationFixture [Frozen] IConfigTemplateGuideService guideService, ConfigTemplateLister sut) { - guideService.TemplateData.Returns(new[] + guideService.LoadTemplateData().Returns(new[] { new TemplatePath(SupportedServices.Radarr, "r1", stubFile, false), new TemplatePath(SupportedServices.Radarr, "r2", stubFile, false), diff --git a/src/Recyclarr.TrashLib.Tests/Config/Services/ConfigTemplateGuideServiceTest.cs b/src/Recyclarr.TrashLib.Tests/Config/Services/ConfigTemplateGuideServiceTest.cs index 58d2a79a..05e979d7 100644 --- a/src/Recyclarr.TrashLib.Tests/Config/Services/ConfigTemplateGuideServiceTest.cs +++ b/src/Recyclarr.TrashLib.Tests/Config/Services/ConfigTemplateGuideServiceTest.cs @@ -1,8 +1,8 @@ using System.IO.Abstractions; -using Recyclarr.Common.Extensions; using Recyclarr.Common.TestLibrary; using Recyclarr.TrashLib.Config; using Recyclarr.TrashLib.Config.Services; +using Recyclarr.TrashLib.Repo; using Recyclarr.TrashLib.TestLibrary; namespace Recyclarr.TrashLib.Tests.Config.Services; @@ -15,15 +15,16 @@ public class ConfigTemplateGuideServiceTest : TrashLibIntegrationFixture public void Throw_when_templates_dir_does_not_exist( ConfigTemplateGuideService sut) { - var act = () => _ = sut.TemplateData; + var act = () => _ = sut.LoadTemplateData(); - act.Should().Throw().WithMessage("Path*templates*"); + act.Should().Throw().WithMessage("Recyclarr*templates*"); } [Test] public void Normal_behavior() { - var templateDir = Paths.RepoDirectory.SubDir("docs/recyclarr-configs"); + var repo = Resolve(); + var templateDir = repo.Path; Fs.AddSameFileFromEmbeddedResource(templateDir.File("templates.json"), typeof(ConfigTemplateGuideServiceTest)); TemplatePath MakeTemplatePath(SupportedServices service, string id, string path) @@ -43,7 +44,7 @@ public class ConfigTemplateGuideServiceTest : TrashLibIntegrationFixture var sut = Resolve(); - var data = sut.TemplateData; + var data = sut.LoadTemplateData(); data.Should().BeEquivalentTo(expectedPaths, o => o.Excluding(x => x.TemplateFile)); data.Select(x => x.TemplateFile.FullName) .Should().BeEquivalentTo(expectedPaths.Select(x => x.TemplateFile.FullName)); diff --git a/src/Recyclarr.TrashLib/AppPaths.cs b/src/Recyclarr.TrashLib/AppPaths.cs index fd28f24d..b96f2d90 100644 --- a/src/Recyclarr.TrashLib/AppPaths.cs +++ b/src/Recyclarr.TrashLib/AppPaths.cs @@ -20,7 +20,7 @@ public class AppPaths : IAppPaths public IFileInfo SettingsPath => AppDataDirectory.File("settings.yml"); public IFileInfo SecretsPath => AppDataDirectory.File("secrets.yml"); public IDirectoryInfo LogDirectory => AppDataDirectory.SubDir("logs", "cli"); - public IDirectoryInfo RepoDirectory => AppDataDirectory.SubDir("repo"); + public IDirectoryInfo ReposDirectory => AppDataDirectory.SubDir("repositories"); public IDirectoryInfo CacheDirectory => AppDataDirectory.SubDir("cache"); public IDirectoryInfo ConfigsDirectory => AppDataDirectory.SubDir("configs"); } diff --git a/src/Recyclarr.TrashLib/Config/Listers/ConfigTemplateLister.cs b/src/Recyclarr.TrashLib/Config/Listers/ConfigTemplateLister.cs index 359cf6c5..1227b416 100644 --- a/src/Recyclarr.TrashLib/Config/Listers/ConfigTemplateLister.cs +++ b/src/Recyclarr.TrashLib/Config/Listers/ConfigTemplateLister.cs @@ -1,6 +1,4 @@ using Recyclarr.TrashLib.Config.Services; -using Recyclarr.TrashLib.Repo; -using Recyclarr.TrashLib.Settings; using Spectre.Console; namespace Recyclarr.TrashLib.Config.Listers; @@ -9,26 +7,18 @@ public class ConfigTemplateLister : IConfigLister { private readonly IAnsiConsole _console; private readonly IConfigTemplateGuideService _guideService; - private readonly IRepoUpdater _repoUpdater; - private readonly ISettingsProvider _settings; public ConfigTemplateLister( IAnsiConsole console, - IConfigTemplateGuideService guideService, - IRepoUpdater repoUpdater, - ISettingsProvider settings) + IConfigTemplateGuideService guideService) { _console = console; _guideService = guideService; - _repoUpdater = repoUpdater; - _settings = settings; } - public async Task List() + public Task List() { - await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.ConfigTemplates); - - var data = _guideService.TemplateData; + var data = _guideService.LoadTemplateData(); var table = new Table(); var empty = new Markup(""); @@ -44,6 +34,7 @@ public class ConfigTemplateLister : IConfigLister } _console.Write(table); + return Task.CompletedTask; } private static IEnumerable RenderTemplates( diff --git a/src/Recyclarr.TrashLib/Config/Parsing/ErrorHandling/ContextualMessages.cs b/src/Recyclarr.TrashLib/Config/Parsing/ErrorHandling/ContextualMessages.cs index f7bdcafe..947b500a 100644 --- a/src/Recyclarr.TrashLib/Config/Parsing/ErrorHandling/ContextualMessages.cs +++ b/src/Recyclarr.TrashLib/Config/Parsing/ErrorHandling/ContextualMessages.cs @@ -23,7 +23,7 @@ public static class ContextualMessages { return "Usage of 'repository' setting is no " + - "longer supported. Use 'trash_guide' under 'repositories' instead." + + "longer supported. Use 'trash_guides' under 'repositories' instead." + "See: https://recyclarr.dev/wiki/upgrade-guide/v5.0/#settings-repository-changes"; } diff --git a/src/Recyclarr.TrashLib/Config/Services/ConfigTemplateGuideService.cs b/src/Recyclarr.TrashLib/Config/Services/ConfigTemplateGuideService.cs index 3a3e7d4a..2be1d5ee 100644 --- a/src/Recyclarr.TrashLib/Config/Services/ConfigTemplateGuideService.cs +++ b/src/Recyclarr.TrashLib/Config/Services/ConfigTemplateGuideService.cs @@ -1,9 +1,7 @@ using System.Collections.ObjectModel; using System.IO.Abstractions; using JetBrains.Annotations; -using Recyclarr.Common.Extensions; using Recyclarr.TrashLib.Repo; -using Recyclarr.TrashLib.Startup; namespace Recyclarr.TrashLib.Config.Services; @@ -20,35 +18,27 @@ public record TemplatePath(SupportedServices Service, string Id, IFileInfo Templ public class ConfigTemplateGuideService : IConfigTemplateGuideService { - private readonly IRepoMetadataBuilder _metadataBuilder; - private readonly IAppPaths _paths; - private readonly Lazy> _templateData; + private readonly IConfigTemplatesRepo _repo; - public ConfigTemplateGuideService( - IRepoMetadataBuilder metadataBuilder, - IAppPaths paths) + public ConfigTemplateGuideService(IConfigTemplatesRepo repo) { - _metadataBuilder = metadataBuilder; - _paths = paths; - _templateData = new Lazy>(LoadTemplateData); + _repo = repo; } - private IReadOnlyCollection LoadTemplateData() + public IReadOnlyCollection LoadTemplateData() { - var metadata = _metadataBuilder.GetMetadata(); - - var templatesPath = _paths.RepoDirectory.SubDir(metadata.Recyclarr.Templates); + var templatesPath = _repo.Path.File("templates.json"); if (!templatesPath.Exists) { throw new InvalidDataException( - $"Path to recyclarr templates does not exist: {metadata.Recyclarr.Templates}"); + $"Recyclarr templates.json does not exist: {templatesPath}"); } - var templates = TrashRepoJsonParser.Deserialize(templatesPath.File("templates.json")); + var templates = TrashRepoJsonParser.Deserialize(templatesPath); TemplatePath NewTemplatePath(TemplateEntry entry, SupportedServices service) { - return new TemplatePath(service, entry.Id, templatesPath.File(entry.Template), entry.Hidden); + return new TemplatePath(service, entry.Id, _repo.Path.File(entry.Template), entry.Hidden); } return templates.Radarr @@ -56,6 +46,4 @@ public class ConfigTemplateGuideService : IConfigTemplateGuideService .Concat(templates.Sonarr.Select(x => NewTemplatePath(x, SupportedServices.Sonarr))) .ToList(); } - - public IReadOnlyCollection TemplateData => _templateData.Value; } diff --git a/src/Recyclarr.TrashLib/Config/Services/IConfigTemplateGuideService.cs b/src/Recyclarr.TrashLib/Config/Services/IConfigTemplateGuideService.cs index a6e12cd5..3c8d232e 100644 --- a/src/Recyclarr.TrashLib/Config/Services/IConfigTemplateGuideService.cs +++ b/src/Recyclarr.TrashLib/Config/Services/IConfigTemplateGuideService.cs @@ -2,5 +2,5 @@ namespace Recyclarr.TrashLib.Config.Services; public interface IConfigTemplateGuideService { - IReadOnlyCollection TemplateData { get; } + IReadOnlyCollection LoadTemplateData(); } diff --git a/src/Recyclarr.TrashLib/Repo/ConfigTemplatesRepo.cs b/src/Recyclarr.TrashLib/Repo/ConfigTemplatesRepo.cs new file mode 100644 index 00000000..d65dfb3a --- /dev/null +++ b/src/Recyclarr.TrashLib/Repo/ConfigTemplatesRepo.cs @@ -0,0 +1,26 @@ +using System.IO.Abstractions; +using Recyclarr.Common.Extensions; +using Recyclarr.TrashLib.Settings; +using Recyclarr.TrashLib.Startup; + +namespace Recyclarr.TrashLib.Repo; + +public class ConfigTemplatesRepo : IConfigTemplatesRepo +{ + private readonly IRepoUpdater _repoUpdater; + private readonly ISettingsProvider _settings; + + public ConfigTemplatesRepo(IRepoUpdater repoUpdater, IAppPaths paths, ISettingsProvider settings) + { + _repoUpdater = repoUpdater; + _settings = settings; + Path = paths.ReposDirectory.SubDir("config-templates"); + } + + public IDirectoryInfo Path { get; } + + public Task Update() + { + return _repoUpdater.UpdateRepo(Path, _settings.Settings.Repositories.ConfigTemplates); + } +} diff --git a/src/Recyclarr.TrashLib/Repo/IConfigTemplatesRepo.cs b/src/Recyclarr.TrashLib/Repo/IConfigTemplatesRepo.cs new file mode 100644 index 00000000..38ddc784 --- /dev/null +++ b/src/Recyclarr.TrashLib/Repo/IConfigTemplatesRepo.cs @@ -0,0 +1,9 @@ +using System.IO.Abstractions; + +namespace Recyclarr.TrashLib.Repo; + +public interface IConfigTemplatesRepo +{ + IDirectoryInfo Path { get; } + Task Update(); +} diff --git a/src/Recyclarr.TrashLib/Repo/IRepoUpdater.cs b/src/Recyclarr.TrashLib/Repo/IRepoUpdater.cs index 0096bbbf..b95f4c04 100644 --- a/src/Recyclarr.TrashLib/Repo/IRepoUpdater.cs +++ b/src/Recyclarr.TrashLib/Repo/IRepoUpdater.cs @@ -5,6 +5,5 @@ namespace Recyclarr.TrashLib.Repo; public interface IRepoUpdater { - IDirectoryInfo RepoPath { get; } - Task UpdateRepo(IRepositorySettings repoSettings); + Task UpdateRepo(IDirectoryInfo repoPath, IRepositorySettings repoSettings); } diff --git a/src/Recyclarr.TrashLib/Repo/ITrashGuidesRepo.cs b/src/Recyclarr.TrashLib/Repo/ITrashGuidesRepo.cs new file mode 100644 index 00000000..ba2aba38 --- /dev/null +++ b/src/Recyclarr.TrashLib/Repo/ITrashGuidesRepo.cs @@ -0,0 +1,9 @@ +using System.IO.Abstractions; + +namespace Recyclarr.TrashLib.Repo; + +public interface ITrashGuidesRepo +{ + IDirectoryInfo Path { get; } + Task Update(); +} diff --git a/src/Recyclarr.TrashLib/Repo/RepoAutofacModule.cs b/src/Recyclarr.TrashLib/Repo/RepoAutofacModule.cs index 151eb193..26a6146b 100644 --- a/src/Recyclarr.TrashLib/Repo/RepoAutofacModule.cs +++ b/src/Recyclarr.TrashLib/Repo/RepoAutofacModule.cs @@ -7,6 +7,9 @@ public class RepoAutofacModule : Module protected override void Load(ContainerBuilder builder) { base.Load(builder); + + builder.RegisterType().As(); + builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As().InstancePerLifetimeScope(); } diff --git a/src/Recyclarr.TrashLib/Repo/RepoMetadata.cs b/src/Recyclarr.TrashLib/Repo/RepoMetadata.cs index f8ee7e7c..f44e23ac 100644 --- a/src/Recyclarr.TrashLib/Repo/RepoMetadata.cs +++ b/src/Recyclarr.TrashLib/Repo/RepoMetadata.cs @@ -19,13 +19,7 @@ public record JsonPaths public SonarrMetadata Sonarr { get; init; } = new(); } -public record RecyclarrMetadata -{ - public string Templates { get; init; } = ""; -} - public record RepoMetadata { public JsonPaths JsonPaths { get; init; } = new(); - public RecyclarrMetadata Recyclarr { get; init; } = new(); } diff --git a/src/Recyclarr.TrashLib/Repo/RepoMetadataBuilder.cs b/src/Recyclarr.TrashLib/Repo/RepoMetadataBuilder.cs index d7da876e..50763c37 100644 --- a/src/Recyclarr.TrashLib/Repo/RepoMetadataBuilder.cs +++ b/src/Recyclarr.TrashLib/Repo/RepoMetadataBuilder.cs @@ -1,26 +1,25 @@ using System.IO.Abstractions; -using Recyclarr.TrashLib.Startup; namespace Recyclarr.TrashLib.Repo; public class RepoMetadataBuilder : IRepoMetadataBuilder { - private readonly IAppPaths _paths; private readonly Lazy _metadata; + private readonly IDirectoryInfo _repoPath; - public RepoMetadataBuilder(IAppPaths paths) + public RepoMetadataBuilder(ITrashGuidesRepo repo) { - _paths = paths; - _metadata = new Lazy(() - => TrashRepoJsonParser.Deserialize(_paths.RepoDirectory.File("metadata.json"))); + _repoPath = repo.Path; + _metadata = new Lazy( + () => TrashRepoJsonParser.Deserialize(_repoPath.File("metadata.json"))); } public IReadOnlyList ToDirectoryInfoList(IEnumerable listOfDirectories) { - return listOfDirectories.Select(x => _paths.RepoDirectory.SubDirectory(x)).ToList(); + return listOfDirectories.Select(x => _repoPath.SubDirectory(x)).ToList(); } - public IDirectoryInfo DocsDirectory => _paths.RepoDirectory.SubDirectory("docs"); + public IDirectoryInfo DocsDirectory => _repoPath.SubDirectory("docs"); public RepoMetadata GetMetadata() { diff --git a/src/Recyclarr.TrashLib/Repo/RepoUpdater.cs b/src/Recyclarr.TrashLib/Repo/RepoUpdater.cs index 6036548b..54f54402 100644 --- a/src/Recyclarr.TrashLib/Repo/RepoUpdater.cs +++ b/src/Recyclarr.TrashLib/Repo/RepoUpdater.cs @@ -2,49 +2,43 @@ using System.IO.Abstractions; using Recyclarr.Common; using Recyclarr.TrashLib.Repo.VersionControl; using Recyclarr.TrashLib.Settings; -using Recyclarr.TrashLib.Startup; namespace Recyclarr.TrashLib.Repo; public class RepoUpdater : IRepoUpdater { private readonly ILogger _log; - private readonly IAppPaths _paths; private readonly IGitRepositoryFactory _repositoryFactory; private readonly IFileUtilities _fileUtils; public RepoUpdater( ILogger log, - IAppPaths paths, IGitRepositoryFactory repositoryFactory, IFileUtilities fileUtils) { _log = log; - _paths = paths; _repositoryFactory = repositoryFactory; _fileUtils = fileUtils; } - public IDirectoryInfo RepoPath => _paths.RepoDirectory; - - public async Task UpdateRepo(IRepositorySettings repoSettings) + public async Task UpdateRepo(IDirectoryInfo repoPath, IRepositorySettings repoSettings) { // Retry only once if there's a failure. This gives us an opportunity to delete the git repository and start // fresh. try { - await CheckoutAndUpdateRepo(repoSettings); + await CheckoutAndUpdateRepo(repoPath, repoSettings); } catch (GitCmdException e) { _log.Debug(e, "Non-zero exit code {ExitCode} while executing Git command: {Error}", e.ExitCode, e.Error); - _log.Warning("Deleting local git repo and retrying git operation due to error..."); - _fileUtils.DeleteReadOnlyDirectory(RepoPath.FullName); - await CheckoutAndUpdateRepo(repoSettings); + _log.Warning("Deleting local git repo '{Repodir}' and retrying git operation due to error", repoPath.Name); + _fileUtils.DeleteReadOnlyDirectory(repoPath.FullName); + await CheckoutAndUpdateRepo(repoPath, repoSettings); } } - private async Task CheckoutAndUpdateRepo(IRepositorySettings repoSettings) + private async Task CheckoutAndUpdateRepo(IDirectoryInfo repoPath, IRepositorySettings repoSettings) { var cloneUrl = repoSettings.CloneUrl; var branch = repoSettings.Branch; @@ -55,7 +49,7 @@ public class RepoUpdater : IRepoUpdater _log.Warning("Using explicit SHA1 for local repository: {Sha1}", repoSettings.Sha1); } - using var repo = await _repositoryFactory.CreateAndCloneIfNeeded(cloneUrl, RepoPath.FullName, branch); + using var repo = await _repositoryFactory.CreateAndCloneIfNeeded(cloneUrl, repoPath, branch); await repo.ForceCheckout(branch); await repo.Fetch(); await repo.ResetHard(repoSettings.Sha1 ?? $"origin/{branch}"); diff --git a/src/Recyclarr.TrashLib/Repo/TrashGuidesRepo.cs b/src/Recyclarr.TrashLib/Repo/TrashGuidesRepo.cs new file mode 100644 index 00000000..403b99d8 --- /dev/null +++ b/src/Recyclarr.TrashLib/Repo/TrashGuidesRepo.cs @@ -0,0 +1,26 @@ +using System.IO.Abstractions; +using Recyclarr.Common.Extensions; +using Recyclarr.TrashLib.Settings; +using Recyclarr.TrashLib.Startup; + +namespace Recyclarr.TrashLib.Repo; + +public class TrashGuidesRepo : ITrashGuidesRepo +{ + private readonly IRepoUpdater _repoUpdater; + private readonly ISettingsProvider _settings; + + public TrashGuidesRepo(IRepoUpdater repoUpdater, IAppPaths paths, ISettingsProvider settings) + { + _repoUpdater = repoUpdater; + _settings = settings; + Path = paths.ReposDirectory.SubDir("trash-guides"); + } + + public IDirectoryInfo Path { get; } + + public Task Update() + { + return _repoUpdater.UpdateRepo(Path, _settings.Settings.Repositories.TrashGuides); + } +} diff --git a/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepository.cs b/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepository.cs index 05ffca49..4009e577 100644 --- a/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepository.cs +++ b/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepository.cs @@ -1,21 +1,20 @@ using System.IO.Abstractions; using System.Text; using CliWrap; -using Recyclarr.TrashLib.Startup; namespace Recyclarr.TrashLib.Repo.VersionControl; public sealed class GitRepository : IGitRepository { private readonly ILogger _log; - private readonly IAppPaths _paths; private readonly IGitPath _gitPath; + private readonly IDirectoryInfo _workDir; - public GitRepository(ILogger log, IAppPaths paths, IGitPath gitPath) + public GitRepository(ILogger log, IGitPath gitPath, IDirectoryInfo workDir) { _log = log; - _paths = paths; _gitPath = gitPath; + _workDir = workDir; } private Task RunGitCmd(params string[] args) @@ -30,18 +29,15 @@ public sealed class GitRepository : IGitRepository var output = new StringBuilder(); var error = new StringBuilder(); + _log.Debug("Using working directory: {Dir}", _workDir.FullName); + _workDir.Create(); + var cli = Cli.Wrap(_gitPath.Path) .WithArguments(args) .WithValidation(CommandResultValidation.None) .WithStandardOutputPipe(PipeTarget.ToStringBuilder(output)) - .WithStandardErrorPipe(PipeTarget.ToStringBuilder(error)); - - if (_paths.RepoDirectory.Exists) - { - var workDir = _paths.RepoDirectory.FullName; - _log.Debug("Using working directory: {Dir}", workDir); - cli = cli.WithWorkingDirectory(workDir); - } + .WithStandardErrorPipe(PipeTarget.ToStringBuilder(error)) + .WithWorkingDirectory(_workDir.FullName); var result = await cli.ExecuteAsync(); @@ -53,8 +49,6 @@ public sealed class GitRepository : IGitRepository } } - public IDirectoryInfo Path => _paths.RepoDirectory; - public void Dispose() { // Nothing to do here @@ -93,7 +87,7 @@ public sealed class GitRepository : IGitRepository args.AddRange(new[] {"-b", branch}); } - args.AddRange(new[] {cloneUrl.ToString(), _paths.RepoDirectory.FullName}); + args.AddRange(new[] {cloneUrl.ToString(), "."}); await RunGitCmd(args); } } diff --git a/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepositoryFactory.cs b/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepositoryFactory.cs index 13466175..5d065d35 100644 --- a/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepositoryFactory.cs +++ b/src/Recyclarr.TrashLib/Repo/VersionControl/GitRepositoryFactory.cs @@ -1,25 +1,25 @@ +using System.IO.Abstractions; + namespace Recyclarr.TrashLib.Repo.VersionControl; public class GitRepositoryFactory : IGitRepositoryFactory { - private readonly Func _repoFactory; private readonly ILogger _log; + private readonly IGitPath _gitPath; - public GitRepositoryFactory( - Func repoFactory, - ILogger log) + public GitRepositoryFactory(ILogger log, IGitPath gitPath) { - _repoFactory = repoFactory; _log = log; + _gitPath = gitPath; } - public async Task CreateAndCloneIfNeeded(Uri repoUrl, string repoPath, string branch) + public async Task CreateAndCloneIfNeeded(Uri repoUrl, IDirectoryInfo repoPath, string branch) { - var repo = _repoFactory(repoPath); + var repo = new GitRepository(_log, _gitPath, repoPath); - if (!repo.Path.Exists) + if (!repoPath.Exists) { - _log.Information("Cloning trash repository..."); + _log.Information("Cloning '{RepoName}' repository...", repoPath.Name); await repo.Clone(repoUrl, branch); } else diff --git a/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepository.cs b/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepository.cs index 69506bf0..300b9635 100644 --- a/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepository.cs +++ b/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepository.cs @@ -1,5 +1,3 @@ -using System.IO.Abstractions; - namespace Recyclarr.TrashLib.Repo.VersionControl; public interface IGitRepository : IDisposable @@ -8,7 +6,6 @@ public interface IGitRepository : IDisposable Task Fetch(string remote = "origin"); Task ResetHard(string toBranchOrSha1); Task SetRemote(string name, Uri newUrl); - IDirectoryInfo Path { get; } Task Clone(Uri cloneUrl, string? branch = null); Task Status(); } diff --git a/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepositoryFactory.cs b/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepositoryFactory.cs index aa5d2b55..e4836a60 100644 --- a/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepositoryFactory.cs +++ b/src/Recyclarr.TrashLib/Repo/VersionControl/IGitRepositoryFactory.cs @@ -1,6 +1,8 @@ +using System.IO.Abstractions; + namespace Recyclarr.TrashLib.Repo.VersionControl; public interface IGitRepositoryFactory { - Task CreateAndCloneIfNeeded(Uri repoUrl, string repoPath, string branch); + Task CreateAndCloneIfNeeded(Uri repoUrl, IDirectoryInfo repoPath, string branch); } diff --git a/src/Recyclarr.TrashLib/Repo/VersionControl/VersionControlAutofacModule.cs b/src/Recyclarr.TrashLib/Repo/VersionControl/VersionControlAutofacModule.cs index 2f1f1686..364def8c 100644 --- a/src/Recyclarr.TrashLib/Repo/VersionControl/VersionControlAutofacModule.cs +++ b/src/Recyclarr.TrashLib/Repo/VersionControl/VersionControlAutofacModule.cs @@ -6,7 +6,6 @@ public class VersionControlAutofacModule : Module { protected override void Load(ContainerBuilder builder) { - builder.RegisterType().As(); builder.RegisterType().As(); builder.RegisterType().As(); base.Load(builder); diff --git a/src/Recyclarr.TrashLib/Settings/SettingsProvider.cs b/src/Recyclarr.TrashLib/Settings/SettingsProvider.cs index 1863f7f3..3c22263b 100644 --- a/src/Recyclarr.TrashLib/Settings/SettingsProvider.cs +++ b/src/Recyclarr.TrashLib/Settings/SettingsProvider.cs @@ -1,6 +1,8 @@ using Recyclarr.Common.Extensions; +using Recyclarr.TrashLib.Config.Parsing.ErrorHandling; using Recyclarr.TrashLib.Config.Yaml; using Recyclarr.TrashLib.Startup; +using YamlDotNet.Core; namespace Recyclarr.TrashLib.Settings; @@ -8,11 +10,13 @@ public class SettingsProvider : ISettingsProvider { public SettingsValues Settings => _settings.Value; + private readonly ILogger _log; private readonly IAppPaths _paths; private readonly Lazy _settings; - public SettingsProvider(IAppPaths paths, IYamlSerializerFactory serializerFactory) + public SettingsProvider(ILogger log, IAppPaths paths, IYamlSerializerFactory serializerFactory) { + _log = log; _paths = paths; _settings = new Lazy(() => LoadOrCreateSettingsFile(serializerFactory)); } @@ -24,9 +28,22 @@ public class SettingsProvider : ISettingsProvider CreateDefaultSettingsFile(); } - using var stream = _paths.SettingsPath.OpenText(); - var deserializer = serializerFactory.CreateDeserializer(); - return deserializer.Deserialize(stream.ReadToEnd()) ?? new SettingsValues(); + try + { + using var stream = _paths.SettingsPath.OpenText(); + var deserializer = serializerFactory.CreateDeserializer(); + return deserializer.Deserialize(stream.ReadToEnd()) ?? new SettingsValues(); + } + catch (YamlException e) + { + _log.Debug(e, "Exception while parsing settings file"); + + var line = e.Start.Line; + var msg = ContextualMessages.GetContextualErrorFromException(e); + _log.Error("Exception while parsing settings.yml at line {Line}: {Msg}", line, msg); + + throw; + } } private void CreateDefaultSettingsFile() diff --git a/src/Recyclarr.TrashLib/Settings/SettingsValues.cs b/src/Recyclarr.TrashLib/Settings/SettingsValues.cs index 405a8ae8..cf31451f 100644 --- a/src/Recyclarr.TrashLib/Settings/SettingsValues.cs +++ b/src/Recyclarr.TrashLib/Settings/SettingsValues.cs @@ -23,7 +23,7 @@ public record LogJanitorSettings public record Repositories { - public TrashRepository TrashGuide { get; [UsedImplicitly] init; } = new(); + public TrashRepository TrashGuides { get; [UsedImplicitly] init; } = new(); public ConfigTemplateRepository ConfigTemplates { get; [UsedImplicitly] init; } = new(); } diff --git a/src/Recyclarr.TrashLib/Startup/IAppPaths.cs b/src/Recyclarr.TrashLib/Startup/IAppPaths.cs index 12c8c6fd..12d08e3e 100644 --- a/src/Recyclarr.TrashLib/Startup/IAppPaths.cs +++ b/src/Recyclarr.TrashLib/Startup/IAppPaths.cs @@ -9,7 +9,7 @@ public interface IAppPaths IFileInfo SettingsPath { get; } IFileInfo SecretsPath { get; } IDirectoryInfo LogDirectory { get; } - IDirectoryInfo RepoDirectory { get; } + IDirectoryInfo ReposDirectory { get; } IDirectoryInfo CacheDirectory { get; } IDirectoryInfo ConfigsDirectory { get; } }