fix: parse project rosters with legacy-compatible semantics
This commit is contained in:
@@ -17,6 +17,7 @@ public partial class MainWindow : System.Windows.Window
|
||||
private LauncherProduct? selected;
|
||||
private string? projectPath;
|
||||
private string? manualRosterPath;
|
||||
private string? selectedRosterSnapshotPath;
|
||||
private string stage = "ProductSelection";
|
||||
private string code = "PRODUCT_NOT_SELECTED";
|
||||
private string detail = "";
|
||||
@@ -105,10 +106,10 @@ public partial class MainWindow : System.Windows.Window
|
||||
pattern = localProfile is not null && selected.Id == "plant3d" ? localProfile.PatternName : product.Pattern;
|
||||
expectedRoster = manualRosterPath ?? LegacyProductSelections.AutomaticRoster(product, projectPath);
|
||||
Transition("AutomaticRosterPathResolved", "AUTOMATIC_ROSTER_PATH_RESOLVED", "Поиск списка плагинов", expectedRoster);
|
||||
var plan = LegacyProductSelections.ReadRoster(product, projectPath, manualRosterPath, adapter);
|
||||
if (localProfile is not null && selected.Id == "plant3d" && !string.Equals(Path.GetFullPath(plan.RosterPath), Path.GetFullPath(localProfile.DownloadListPath), StringComparison.OrdinalIgnoreCase))
|
||||
throw new InvalidOperationException("LOCAL_PARITY_ROSTER_PROFILE_MISMATCH");
|
||||
var plan = LegacyProductSelections.ReadRoster(product, projectPath, manualRosterPath, adapter, localProfile?.Root);
|
||||
orderedIds = string.Join(", ", plan.OrderedIds);
|
||||
selectedRosterSnapshotPath = plan.SnapshotPath ?? plan.RosterPath;
|
||||
if (plan.SnapshotSha256 is not null) detail = $"Roster snapshot SHA-256: {plan.SnapshotSha256}";
|
||||
Plugins.ItemsSource = plan.OrderedIds;
|
||||
Plugins.IsEnabled = false;
|
||||
PluginStatus.Text = "Источник списка: " + (manualRosterPath is null ? "Автоматически" : "Выбран вручную");
|
||||
@@ -126,7 +127,14 @@ public partial class MainWindow : System.Windows.Window
|
||||
Transition("PackageMappingFailed", "PACKAGE_MAPPING_NOT_FOUND", "Для выбранных плагинов отсутствуют пакеты 2026");
|
||||
return;
|
||||
}
|
||||
ValidateLocalProfileDefinitions(plan);
|
||||
var unmapped = EvaluateLocalProfileDefinitions(plan);
|
||||
if (unmapped.Count > 0)
|
||||
{
|
||||
mappingState = "Known legacy plugin, package 2026 absent: " + string.Join(", ", unmapped);
|
||||
StartButton.IsEnabled = false;
|
||||
Transition("PackageMappingFailed", "PACKAGE_MAPPING_NOT_FOUND", "Для части плагинов проекта пока отсутствуют пакеты версии 2026");
|
||||
return;
|
||||
}
|
||||
mappingState = "Mapped";
|
||||
StartButton.IsEnabled = true;
|
||||
Transition("Ready", "READY", "Готово к запуску");
|
||||
@@ -134,13 +142,22 @@ public partial class MainWindow : System.Windows.Window
|
||||
catch (Exception ex) { ReportFailure(ex, "RosterResolutionFailed"); }
|
||||
}
|
||||
|
||||
private void ValidateLocalProfileDefinitions(LegacyPluginPlan plan)
|
||||
private IReadOnlyList<string> EvaluateLocalProfileDefinitions(LegacyPluginPlan plan)
|
||||
{
|
||||
var settings = adapter.ParseSettings(File.ReadAllText(localProfile!.SettingsPath));
|
||||
var selectedPattern = settings.Patterns.SingleOrDefault(x => string.Equals(x.Name, localProfile.PatternName, StringComparison.Ordinal));
|
||||
if (selectedPattern is null) throw new InvalidOperationException("LOCAL_PARITY_PATTERN_NOT_FOUND");
|
||||
var overlay = LegacyCompatibilityOverlayParser.Parse(File.ReadAllText(localProfile.OverlayPath));
|
||||
adapter.Join(selectedPattern, new LegacyDownloadSelection(plan.OrderedIds), overlay);
|
||||
var missing = new List<string>();
|
||||
foreach (var id in plan.OrderedIds.Distinct(StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
var definitions = selectedPattern.Plugins.Where(x => string.Equals(x.Id, id, StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
if (definitions.Length == 0) throw new InvalidOperationException("LEGACY_PLUGIN_ID_NOT_DEFINED");
|
||||
if (definitions.Length > 1) throw new InvalidOperationException("AMBIGUOUS_LEGACY_PLUGIN_DEFINITION");
|
||||
if (!definitions[0].IsAllowedOn(Environment.MachineName)) { missing.Add(id + " (machine restricted)"); continue; }
|
||||
if (!overlay.Plugins.Any(x => string.Equals(x.LegacyId, id, StringComparison.OrdinalIgnoreCase))) missing.Add(id);
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
|
||||
private async void Start_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
@@ -151,7 +168,7 @@ public partial class MainWindow : System.Windows.Window
|
||||
{
|
||||
preparationState = "InProgress";
|
||||
Transition("PackagePreparation", "PACKAGE_PREPARING", "Подготовка плагинов");
|
||||
var profile = manualRosterPath is null ? localProfile : localProfile with { DownloadListPath = manualRosterPath };
|
||||
var profile = localProfile with { DownloadListPath = selectedRosterSnapshotPath ?? localProfile.DownloadListPath };
|
||||
var prepared = await localService.PrepareAsync(profile, CancellationToken.None);
|
||||
preparationState = "Succeeded";
|
||||
activationState = prepared.Activation.Outcome;
|
||||
@@ -174,6 +191,7 @@ public partial class MainWindow : System.Windows.Window
|
||||
Plugins.IsEnabled = false;
|
||||
StartButton.IsEnabled = false;
|
||||
pattern = expectedRoster = orderedIds = detail = "";
|
||||
selectedRosterSnapshotPath = null;
|
||||
mappingState = preparationState = activationState = bootstrapState = processState = "NotStarted";
|
||||
processId = null;
|
||||
packageLoadMarker = "NotStarted";
|
||||
|
||||
Reference in New Issue
Block a user