fix: parse project rosters with legacy-compatible semantics
This commit is contained in:
@@ -10,7 +10,11 @@ public sealed record LegacyPluginDefinition(string Id, string Renewal, string Ca
|
||||
}
|
||||
public sealed record LegacyProductPattern(string Name, string Filter, string Roster, IReadOnlyList<LegacyPluginDefinition> Plugins, IReadOnlyList<string>? Attributes = null, IReadOnlyList<string>? Sources = null, string? Target = null, string? Loader = null, string? ObjectPath = null);
|
||||
public sealed record LegacyLauncherSettings(string Help, string CareMarker, IReadOnlyList<LegacyProductPattern> Patterns);
|
||||
public sealed record LegacyDownloadSelection(IReadOnlyList<string> PluginIds);
|
||||
public sealed record LegacyDownloadListEntry(int ElementIndex, string RawId, string NormalizedId, int? FirstOccurrenceIndex, string SourceShape);
|
||||
public sealed record LegacyDownloadSelection(IReadOnlyList<string> PluginIds, IReadOnlyList<LegacyDownloadListEntry>? Entries = null)
|
||||
{
|
||||
public IReadOnlyList<string> EffectivePluginIds => PluginIds.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||
}
|
||||
public sealed record LegacyCompatibilityMapping(string LegacyId, string PackageId, string Version, string Channel);
|
||||
public sealed record LegacyCompatibilityOverlay(string MappingId, string Product, int ProductYear, string Architecture, bool AllowOfflineFallback, IReadOnlyList<LegacyCompatibilityMapping> Plugins);
|
||||
|
||||
@@ -42,18 +46,39 @@ public sealed class LegacyConfigurationAdapter
|
||||
|
||||
public LegacyDownloadSelection ParseDownloadList(string xml)
|
||||
{
|
||||
using var reader = XmlReader.Create(new StringReader(xml), XmlSettings); var root = XDocument.Load(reader).Root;
|
||||
if (root?.Name != "root") throw new InvalidOperationException("LEGACY_DOWNLOAD_LIST_INVALID");
|
||||
var ids = root.Elements("id").Select(x => x.Value.Trim()).ToArray();
|
||||
if (ids.Length == 0 || ids.Any(string.IsNullOrWhiteSpace) || ids.GroupBy(x => x, StringComparer.OrdinalIgnoreCase).Any(x => x.Count() > 1))
|
||||
throw new InvalidOperationException("LEGACY_DOWNLOAD_SELECTION_INVALID");
|
||||
return new(ids);
|
||||
try
|
||||
{
|
||||
using var reader = XmlReader.Create(new StringReader(xml), XmlSettings);
|
||||
var root = XDocument.Load(reader).Root;
|
||||
if (root?.Name != "root") throw new InvalidOperationException("DOWNLOAD_LIST_ROOT_INVALID");
|
||||
// F2_Xml serialized only root/id and removed only exact empty strings. Real project files
|
||||
// also contain source-grouped <area><id> entries; preserve their document order as the
|
||||
// modern plan while retaining raw values and duplicate evidence.
|
||||
var direct = root.Elements("id").Select(x => (Element: x, Shape: "Root"));
|
||||
var grouped = root.Elements("area").SelectMany(area => area.Elements("id").Select(x => (Element: x, Shape: "Area")));
|
||||
var entries = (direct.Any() ? direct : grouped).Select((entry, index) =>
|
||||
{
|
||||
var raw = entry.Element.Value;
|
||||
var normalized = raw; // legacy F2_Xml did not Trim or case-normalize IDs.
|
||||
return new LegacyDownloadListEntry(index, raw, normalized, null, entry.Shape);
|
||||
}).ToArray();
|
||||
var seen = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
var annotated = entries.Select(entry =>
|
||||
{
|
||||
if (entry.RawId == "") return entry;
|
||||
if (seen.TryGetValue(entry.NormalizedId, out var first)) return entry with { FirstOccurrenceIndex = first };
|
||||
seen[entry.NormalizedId] = entry.ElementIndex;
|
||||
return entry;
|
||||
}).ToArray();
|
||||
return new(annotated.Where(x => x.RawId != "").Select(x => x.RawId).ToArray(), annotated);
|
||||
}
|
||||
catch (XmlException) { throw new InvalidOperationException("DOWNLOAD_LIST_XML_MALFORMED"); }
|
||||
}
|
||||
|
||||
public IReadOnlyList<PackageRequirement> Join(LegacyProductPattern pattern, LegacyDownloadSelection selection, LegacyCompatibilityOverlay overlay)
|
||||
{
|
||||
var result = new List<PackageRequirement>();
|
||||
foreach (var id in selection.PluginIds)
|
||||
foreach (var id in selection.EffectivePluginIds)
|
||||
{
|
||||
var definition = pattern.Plugins.Where(x => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (definition.Length == 0) throw new InvalidOperationException("LEGACY_PLUGIN_ID_NOT_DEFINED");
|
||||
|
||||
Reference in New Issue
Block a user