|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
using Recyclarr.Common.Extensions;
|
|
|
|
|
|
|
|
|
|
namespace Recyclarr.TrashLib.Config.Parsing.PostProcessing.ConfigMerging;
|
|
|
|
|
|
|
|
|
@ -24,13 +25,13 @@ public abstract class ServiceConfigMerger<T> where T : ServiceConfigYaml
|
|
|
|
|
{
|
|
|
|
|
return a with
|
|
|
|
|
{
|
|
|
|
|
CustomFormats = Combine(a.CustomFormats, b.CustomFormats, (x, y) => x.Concat(y).ToList()),
|
|
|
|
|
CustomFormats = Combine(a.CustomFormats, b.CustomFormats, MergeCustomFormats),
|
|
|
|
|
QualityProfiles = MergeQualityProfiles(a.QualityProfiles, b.QualityProfiles),
|
|
|
|
|
QualityDefinition = Combine(a.QualityDefinition, b.QualityDefinition,
|
|
|
|
|
(x, y) => x with
|
|
|
|
|
(a1, b1) => a1 with
|
|
|
|
|
{
|
|
|
|
|
Type = y.Type ?? x.Type,
|
|
|
|
|
PreferredRatio = y.PreferredRatio ?? x.PreferredRatio
|
|
|
|
|
Type = b1.Type ?? a1.Type,
|
|
|
|
|
PreferredRatio = b1.PreferredRatio ?? a1.PreferredRatio
|
|
|
|
|
}),
|
|
|
|
|
|
|
|
|
|
DeleteOldCustomFormats =
|
|
|
|
@ -41,6 +42,48 @@ public abstract class ServiceConfigMerger<T> where T : ServiceConfigYaml
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private sealed record FlattenedCfs(string? ProfileName, int? Score, IReadOnlyCollection<string> TrashIds);
|
|
|
|
|
|
|
|
|
|
private static IReadOnlyCollection<CustomFormatConfigYaml> MergeCustomFormats(
|
|
|
|
|
IReadOnlyCollection<CustomFormatConfigYaml> a,
|
|
|
|
|
IReadOnlyCollection<CustomFormatConfigYaml> b)
|
|
|
|
|
{
|
|
|
|
|
var flattenedA = FlattenCfs(a);
|
|
|
|
|
var flattenedB = FlattenCfs(b);
|
|
|
|
|
|
|
|
|
|
return flattenedA
|
|
|
|
|
// This builds a list of TrashIds in side B that are assigned to matching profiles in A
|
|
|
|
|
.Select(x => (A: x, B: flattenedB
|
|
|
|
|
.Where(y => y.ProfileName.EqualsIgnoreCase(x.ProfileName)) // Ignore score
|
|
|
|
|
.SelectMany(y => y.TrashIds)
|
|
|
|
|
.Distinct(StringComparer.InvariantCultureIgnoreCase)
|
|
|
|
|
.ToList()))
|
|
|
|
|
// Add everything on side A that isn't on side B
|
|
|
|
|
.Select(x => new CustomFormatConfigYaml
|
|
|
|
|
{
|
|
|
|
|
TrashIds = x.A.TrashIds
|
|
|
|
|
.Except(x.B, StringComparer.InvariantCultureIgnoreCase)
|
|
|
|
|
.ToList(),
|
|
|
|
|
QualityProfiles = x.A.ProfileName is not null
|
|
|
|
|
? new[] {new QualityScoreConfigYaml {Name = x.A.ProfileName, Score = x.A.Score}}
|
|
|
|
|
: null
|
|
|
|
|
})
|
|
|
|
|
.Concat(b)
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
static List<FlattenedCfs> FlattenCfs(IEnumerable<CustomFormatConfigYaml> cfs)
|
|
|
|
|
{
|
|
|
|
|
return cfs
|
|
|
|
|
.Where(x => x.TrashIds is not null)
|
|
|
|
|
.SelectMany(x => x is {QualityProfiles.Count: > 0}
|
|
|
|
|
? x.QualityProfiles.Select(y => new FlattenedCfs(y.Name, y.Score, x.TrashIds!))
|
|
|
|
|
: new[] {new FlattenedCfs(null, null, x.TrashIds!)})
|
|
|
|
|
.GroupBy(x => (Name: x.ProfileName, x.Score))
|
|
|
|
|
.Select(x => new FlattenedCfs(x.Key.Name, x.Key.Score, x.SelectMany(y => y.TrashIds).ToList()))
|
|
|
|
|
.ToList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static IReadOnlyCollection<QualityProfileConfigYaml>? MergeQualityProfiles(
|
|
|
|
|
IReadOnlyCollection<QualityProfileConfigYaml>? a,
|
|
|
|
|
IReadOnlyCollection<QualityProfileConfigYaml>? b)
|
|
|
|
|