-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConfigMerging.cs
More file actions
104 lines (88 loc) · 4.02 KB
/
ConfigMerging.cs
File metadata and controls
104 lines (88 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System.Collections.Immutable;
using VsCodeInstallerHelper.ConfigModels;
using VsCodeInstallerHelper.Extensions;
namespace VsCodeInstallerHelper;
internal static class ConfigMerging
{
private static GetSetPair<string?> ExecutingGetSetPair => new(tc => tc.Executing, (tc, v) => tc with{Executing = v});
private static GetSetPair<bool?> CheckFileExistsGetSetPair => new(tc => tc.Configure?.CheckFileExists, (tc, v) =>
{
return tc.Configure switch
{
null => tc with { Configure = new ConfigureConfig(null, v) },
not null => tc with { Configure = tc.Configure with { CheckFileExists = tc.Configure.CheckFileExists.Or(v) } }
};
});
private static GetSetPair<bool?> ResolveFullPathGetSetPair => new(tc => tc.Configure?.CheckFileExists, (tc, v) =>
{
return tc.Configure switch
{
null => tc with { Configure = new ConfigureConfig(v, null) },
not null => tc with { Configure = tc.Configure with { ResolveFullPath = tc.Configure.ResolveFullPath.Or(v) } }
};
});
private static GetSetPair<IReadOnlyList<string>> ExecuteParamsGetSetPair => new GetSetPair<IReadOnlyList<string>>(
tc => tc.ExecuteParams,
(tc, v) =>
{
if (v is null)
return tc;
if (tc.ExecuteParams is null or {Count:0})
return tc with { ExecuteParams = v };
var mergeBuilder = ImmutableArray.CreateBuilder<string>();
mergeBuilder.AddRange(v);
mergeBuilder.AddRange(tc.ExecuteParams);
return tc with { ExecuteParams = mergeBuilder.ToImmutable() };
});
internal static TopConfig? Merge(List<LoadFileConfig> configs)
{
switch (configs.Count)
{
case 0:
Error("No configurations to merge.");
return null;
case 1:
return configs[0];
}
var firstConfig = configs[0];
var mergedConfig = new TopConfig(firstConfig.Configure ?? new ConfigureConfig(null, null), firstConfig.Executing, firstConfig.ExecuteParams);
foreach (var loadFileConfig in configs[1..])
{
mergedConfig = NullMerger(mergedConfig, loadFileConfig, ExecutingGetSetPair);
mergedConfig = NullStructMerger(mergedConfig, loadFileConfig, CheckFileExistsGetSetPair);
mergedConfig = NullStructMerger(mergedConfig, loadFileConfig, ResolveFullPathGetSetPair);
mergedConfig = CollectionMerger<IReadOnlyList<string>, string>(mergedConfig, loadFileConfig, ExecuteParamsGetSetPair);
}
return mergedConfig;
}
private static TopConfig NullMerger<TProp>(TopConfig destConfig, TopConfig sourceConfig, GetSetPair<TProp> getSetPair)
where TProp : class?
{
var destPropValue = getSetPair.Getter(destConfig);
if (destPropValue is not null)
return destConfig;
var sourcePropValue = getSetPair.Getter(sourceConfig);
if (sourcePropValue is null)
return destConfig;
return getSetPair.CreateUpdated(destConfig, sourcePropValue);
}
private static TopConfig NullStructMerger<TProp>(TopConfig destConfig, TopConfig sourceConfig, GetSetPair<TProp?> getSetPair)
where TProp : struct
{
var sourcePropValue = getSetPair.Getter(sourceConfig);
if (sourcePropValue is null)
return destConfig;
return getSetPair.CreateUpdated(destConfig, sourcePropValue);
}
private static TopConfig CollectionMerger<TProp, TValue>(TopConfig destConfig, TopConfig sourceConfig, GetSetPair<TProp> getSetPair)
where TProp : IReadOnlyCollection<TValue>?
{
var sourcePropValue = getSetPair.Getter(sourceConfig);
if (sourcePropValue is null or {Count:0})
return destConfig;
return getSetPair.CreateUpdated(destConfig, sourcePropValue);
}
private sealed record GetSetPair<TProp>(
Func<TopConfig, TProp?> Getter,
Func<TopConfig, TProp?, TopConfig> CreateUpdated);
}