From 9a26348d266119044d5bc3879af66570d5db0120 Mon Sep 17 00:00:00 2001 From: Robert Dailey Date: Tue, 12 Sep 2023 09:46:04 -0500 Subject: [PATCH] fix: Properly sync IncludeCustomFormatWhenRenaming --- CHANGELOG.md | 5 ++ .../CustomFormat/CustomFormatLoader.cs | 4 +- src/Recyclarr.TrashLib/Json/BulkJsonLoader.cs | 10 +-- .../Json/GuideJsonLoader.cs | 21 ++++++ .../Json/IBulkJsonLoader.cs | 10 +++ .../Json/JsonAutofacModule.cs | 22 ++++++ .../Json/ServiceJsonLoader.cs | 21 ++++++ .../TrashLibAutofacModule.cs | 5 +- .../Json/BulkJsonLoaderIntegrationTest.cs | 68 +++++++++++++++++++ .../Json/BulkJsonLoaderTest.cs | 37 ---------- 10 files changed, 158 insertions(+), 45 deletions(-) create mode 100644 src/Recyclarr.TrashLib/Json/GuideJsonLoader.cs create mode 100644 src/Recyclarr.TrashLib/Json/IBulkJsonLoader.cs create mode 100644 src/Recyclarr.TrashLib/Json/JsonAutofacModule.cs create mode 100644 src/Recyclarr.TrashLib/Json/ServiceJsonLoader.cs create mode 100644 src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderIntegrationTest.cs delete mode 100644 src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderTest.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 969c3789..f7884767 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- If the guide data for "Include Custom Format when Renaming" is set to "true", it now syncs that + correctly instead of always setting to "false" (#213). + ## [5.4.0] - 2023-09-11 ### Added diff --git a/src/Recyclarr.TrashLib.Guide/CustomFormat/CustomFormatLoader.cs b/src/Recyclarr.TrashLib.Guide/CustomFormat/CustomFormatLoader.cs index 9ac60eef..bc2ec0c7 100644 --- a/src/Recyclarr.TrashLib.Guide/CustomFormat/CustomFormatLoader.cs +++ b/src/Recyclarr.TrashLib.Guide/CustomFormat/CustomFormatLoader.cs @@ -8,10 +8,10 @@ namespace Recyclarr.TrashLib.Guide.CustomFormat; public class CustomFormatLoader : ICustomFormatLoader { - private readonly BulkJsonLoader _loader; + private readonly ServiceJsonLoader _loader; private readonly ICustomFormatCategoryParser _categoryParser; - public CustomFormatLoader(BulkJsonLoader loader, ICustomFormatCategoryParser categoryParser) + public CustomFormatLoader(ServiceJsonLoader loader, ICustomFormatCategoryParser categoryParser) { _loader = loader; _categoryParser = categoryParser; diff --git a/src/Recyclarr.TrashLib/Json/BulkJsonLoader.cs b/src/Recyclarr.TrashLib/Json/BulkJsonLoader.cs index eabba8f2..41530bed 100644 --- a/src/Recyclarr.TrashLib/Json/BulkJsonLoader.cs +++ b/src/Recyclarr.TrashLib/Json/BulkJsonLoader.cs @@ -8,13 +8,15 @@ namespace Recyclarr.TrashLib.Json; public record LoadedJsonObject(IFileInfo File, T Obj); -public class BulkJsonLoader +public class BulkJsonLoader : IBulkJsonLoader { private readonly ILogger _log; + private readonly JsonSerializerSettings _serializerSettings; - public BulkJsonLoader(ILogger log) + public BulkJsonLoader(ILogger log, JsonSerializerSettings serializerSettings) { _log = log; + _serializerSettings = serializerSettings; } public ICollection LoadAllFilesAtPaths( @@ -31,9 +33,9 @@ public class BulkJsonLoader return convertedObservable.ToEnumerable().ToList(); } - private static T ParseJson(string guideData, string fileName) + private T ParseJson(string guideData, string fileName) { - var obj = JsonConvert.DeserializeObject(guideData, GlobalJsonSerializerSettings.Guide); + var obj = JsonConvert.DeserializeObject(guideData, _serializerSettings); if (obj is null) { throw new JsonSerializationException($"Unable to parse JSON at file {fileName}"); diff --git a/src/Recyclarr.TrashLib/Json/GuideJsonLoader.cs b/src/Recyclarr.TrashLib/Json/GuideJsonLoader.cs new file mode 100644 index 00000000..9edb801e --- /dev/null +++ b/src/Recyclarr.TrashLib/Json/GuideJsonLoader.cs @@ -0,0 +1,21 @@ +using System.IO.Abstractions; +using Newtonsoft.Json; + +namespace Recyclarr.TrashLib.Json; + +public class GuideJsonLoader : IBulkJsonLoader +{ + private readonly IBulkJsonLoader _loader; + + public GuideJsonLoader(Func jsonLoaderFactory) + { + _loader = jsonLoaderFactory(GlobalJsonSerializerSettings.Guide); + } + + public ICollection LoadAllFilesAtPaths( + IEnumerable jsonPaths, + Func>, IObservable>? extra = null) + { + return _loader.LoadAllFilesAtPaths(jsonPaths, extra); + } +} diff --git a/src/Recyclarr.TrashLib/Json/IBulkJsonLoader.cs b/src/Recyclarr.TrashLib/Json/IBulkJsonLoader.cs new file mode 100644 index 00000000..c83288d3 --- /dev/null +++ b/src/Recyclarr.TrashLib/Json/IBulkJsonLoader.cs @@ -0,0 +1,10 @@ +using System.IO.Abstractions; + +namespace Recyclarr.TrashLib.Json; + +public interface IBulkJsonLoader +{ + ICollection LoadAllFilesAtPaths( + IEnumerable jsonPaths, + Func>, IObservable>? extra = null); +} diff --git a/src/Recyclarr.TrashLib/Json/JsonAutofacModule.cs b/src/Recyclarr.TrashLib/Json/JsonAutofacModule.cs new file mode 100644 index 00000000..726bcf1d --- /dev/null +++ b/src/Recyclarr.TrashLib/Json/JsonAutofacModule.cs @@ -0,0 +1,22 @@ +using Autofac; +using Newtonsoft.Json; + +namespace Recyclarr.TrashLib.Json; + +public class JsonAutofacModule : Module +{ + protected override void Load(ContainerBuilder builder) + { + base.Load(builder); + builder.Register>(c => + { + return settings => new BulkJsonLoader(c.Resolve(), settings); + }); + + // Decorators for BulkJsonLoader. We do not use RegisterDecorator() here for these reasons: + // - We consume the BulkJsonLoader as a delegate factory, not by instance + // - We do not want all implementations of BulkJsonLoader to be decorated, only a specific implementation. + builder.RegisterType(); + builder.RegisterType(); + } +} diff --git a/src/Recyclarr.TrashLib/Json/ServiceJsonLoader.cs b/src/Recyclarr.TrashLib/Json/ServiceJsonLoader.cs new file mode 100644 index 00000000..95b0484c --- /dev/null +++ b/src/Recyclarr.TrashLib/Json/ServiceJsonLoader.cs @@ -0,0 +1,21 @@ +using System.IO.Abstractions; +using Newtonsoft.Json; + +namespace Recyclarr.TrashLib.Json; + +public class ServiceJsonLoader : IBulkJsonLoader +{ + private readonly IBulkJsonLoader _loader; + + public ServiceJsonLoader(Func jsonLoaderFactory) + { + _loader = jsonLoaderFactory(GlobalJsonSerializerSettings.Services); + } + + public ICollection LoadAllFilesAtPaths( + IEnumerable jsonPaths, + Func>, IObservable>? extra = null) + { + return _loader.LoadAllFilesAtPaths(jsonPaths, extra); + } +} diff --git a/src/Recyclarr.TrashLib/TrashLibAutofacModule.cs b/src/Recyclarr.TrashLib/TrashLibAutofacModule.cs index 3bd4dd05..cda6f9b3 100644 --- a/src/Recyclarr.TrashLib/TrashLibAutofacModule.cs +++ b/src/Recyclarr.TrashLib/TrashLibAutofacModule.cs @@ -25,14 +25,15 @@ public class TrashLibAutofacModule : Module // Needed for Autofac.Extras.Ordering builder.RegisterSource(); - builder.RegisterType().As().SingleInstance(); builder.RegisterModule(); builder.RegisterModule(); builder.RegisterModule(); builder.RegisterModule(); + builder.RegisterModule(); + + builder.RegisterType().As().SingleInstance(); builder.RegisterType().As(); builder.RegisterType().As().SingleInstance(); - builder.RegisterType(); } private static void CommonRegistrations(ContainerBuilder builder) diff --git a/src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderIntegrationTest.cs b/src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderIntegrationTest.cs new file mode 100644 index 00000000..7f27404b --- /dev/null +++ b/src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderIntegrationTest.cs @@ -0,0 +1,68 @@ +using System.Diagnostics.CodeAnalysis; +using System.IO.Abstractions; +using Recyclarr.TrashLib.Json; +using Recyclarr.TrashLib.Models; +using Recyclarr.TrashLib.TestLibrary; + +namespace Recyclarr.TrashLib.Tests.Json; + +[TestFixture] +[Parallelizable(ParallelScope.All)] +public class BulkJsonLoaderIntegrationTest : TrashLibIntegrationFixture +{ + [SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")] + private sealed record TestJsonObject(string TrashId, int TrashScore, string Name); + + [Test] + public void Guide_deserialize_works() + { + var sut = Resolve(); + + const string jsonData = + """ + { + "trash_id": "90cedc1fea7ea5d11298bebd3d1d3223", + "trash_score": "-10000", + "name": "TheName" + } + """; + + Fs.AddFile(Fs.CurrentDirectory().File("file.json"), new MockFileData(jsonData)); + + var result = sut.LoadAllFilesAtPaths(new[] {Fs.CurrentDirectory()}); + + result.Should().BeEquivalentTo(new[] + { + new TestJsonObject("90cedc1fea7ea5d11298bebd3d1d3223", -10000, "TheName") + }); + } + + [Test] + public void Service_deserialize_works() + { + var sut = Resolve(); + + const string jsonData = + """ + { + "id": 22, + "name": "FUNi", + "includeCustomFormatWhenRenaming": true + } + """; + + Fs.AddFile(Fs.CurrentDirectory().File("file.json"), new MockFileData(jsonData)); + + var result = sut.LoadAllFilesAtPaths(new[] {Fs.CurrentDirectory()}); + + result.Should().BeEquivalentTo(new[] + { + new CustomFormatData + { + Id = 22, + Name = "FUNi", + IncludeCustomFormatWhenRenaming = true + } + }); + } +} diff --git a/src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderTest.cs b/src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderTest.cs deleted file mode 100644 index 06d4420d..00000000 --- a/src/tests/Recyclarr.TrashLib.Tests/Json/BulkJsonLoaderTest.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.IO.Abstractions; -using Recyclarr.TrashLib.Json; - -namespace Recyclarr.TrashLib.Tests.Json; - -[TestFixture] -[Parallelizable(ParallelScope.All)] -public class BulkJsonLoaderTest -{ - [SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")] - private sealed record TestJsonObject(string TrashId, int TrashScore, string Name); - - [Test, AutoMockData] - public void Deserialize_works( - [Frozen(Matching.ImplementedInterfaces)] MockFileSystem fs, - BulkJsonLoader sut) - { - var jsonData = - """ - { - "trash_id": "90cedc1fea7ea5d11298bebd3d1d3223", - "trash_score": "-10000", - "name": "TheName" - } - """; - - fs.AddFile(fs.CurrentDirectory().File("file.json"), new MockFileData(jsonData)); - - var result = sut.LoadAllFilesAtPaths(new[] {fs.CurrentDirectory()}); - - result.Should().BeEquivalentTo(new[] - { - new TestJsonObject("90cedc1fea7ea5d11298bebd3d1d3223", -10000, "TheName") - }); - } -}