feat: load legacy Cuts and Res runtime assets
This commit is contained in:
@@ -7,8 +7,6 @@ using MMoneyCoderSharp.Data;
|
||||
|
||||
internal static class NxtThemeRestoreDbAudit
|
||||
{
|
||||
private const string OriginalConfigurationPath =
|
||||
@"C:\Users\MD\source\repos\MBN_STOCK_N\MBN_STOCK_N\RES\MmoneyCoder.ini";
|
||||
private const string ActiveRowsQueryName = "AUDIT_ACTIVE_NXT_THEME_ROWS";
|
||||
|
||||
private const string ActiveRowsSql = """
|
||||
@@ -26,9 +24,14 @@ internal static class NxtThemeRestoreDbAudit
|
||||
internal static async Task RunAsync(
|
||||
IDataQueryExecutor executor,
|
||||
MariaDbDatabaseOptions currentOptions,
|
||||
MariaDbEndpointReference referenceOptions,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await RunEndpointAuditAsync(executor, currentOptions, cancellationToken)
|
||||
await RunEndpointAuditAsync(
|
||||
executor,
|
||||
currentOptions,
|
||||
referenceOptions,
|
||||
cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
const int maximumRows = 1_000;
|
||||
@@ -291,13 +294,18 @@ internal static class NxtThemeRestoreDbAudit
|
||||
private static async Task RunEndpointAuditAsync(
|
||||
IDataQueryExecutor executor,
|
||||
MariaDbDatabaseOptions currentOptions,
|
||||
MariaDbEndpointReference referenceOptions,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(executor);
|
||||
ArgumentNullException.ThrowIfNull(currentOptions);
|
||||
ArgumentNullException.ThrowIfNull(referenceOptions);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var original = ReadOriginalEndpoint(OriginalConfigurationPath);
|
||||
var original = NormalizeEndpoint(
|
||||
referenceOptions.Host,
|
||||
referenceOptions.Port,
|
||||
referenceOptions.Database);
|
||||
var current = NormalizeEndpoint(
|
||||
currentOptions.Host,
|
||||
currentOptions.Port,
|
||||
@@ -354,78 +362,6 @@ internal static class NxtThemeRestoreDbAudit
|
||||
$"serverMajorMinor={versionMajorMinor}");
|
||||
}
|
||||
|
||||
private static string ReadOriginalEndpoint(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
"The fixed read-only original MariaDB configuration is unavailable.");
|
||||
}
|
||||
|
||||
var source = new FileInfo(path);
|
||||
if ((source.Attributes & (FileAttributes.Directory | FileAttributes.ReparsePoint)) != 0 ||
|
||||
source.Length is < 1 or > 64 * 1024)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
"The fixed read-only original MariaDB configuration failed its file boundary.");
|
||||
}
|
||||
|
||||
var inMariaSection = false;
|
||||
string? connectionName = null;
|
||||
foreach (var rawLine in File.ReadLines(path))
|
||||
{
|
||||
var line = rawLine.Trim();
|
||||
if (line.StartsWith("[", StringComparison.Ordinal) &&
|
||||
line.EndsWith("]", StringComparison.Ordinal))
|
||||
{
|
||||
inMariaSection = string.Equals(line, "[Maria]", StringComparison.Ordinal);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!inMariaSection || line.Length == 0 ||
|
||||
line.StartsWith("//", StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const string prefix = "ConnectionName=";
|
||||
if (line.StartsWith(prefix, StringComparison.Ordinal))
|
||||
{
|
||||
if (connectionName is not null)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
"The original MariaDB endpoint is ambiguous.");
|
||||
}
|
||||
|
||||
connectionName = line[prefix.Length..];
|
||||
}
|
||||
}
|
||||
|
||||
if (connectionName is null)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
"The original MariaDB endpoint is unavailable.");
|
||||
}
|
||||
|
||||
var slash = connectionName.LastIndexOf('/');
|
||||
var colon = connectionName.LastIndexOf(':', slash - 1);
|
||||
if (slash <= 0 || colon <= 0 || colon >= slash - 1 || slash == connectionName.Length - 1 ||
|
||||
!int.TryParse(
|
||||
connectionName.AsSpan(colon + 1, slash - colon - 1),
|
||||
NumberStyles.None,
|
||||
CultureInfo.InvariantCulture,
|
||||
out var port))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
"The original MariaDB endpoint has an invalid closed shape.");
|
||||
}
|
||||
|
||||
return NormalizeEndpoint(
|
||||
connectionName[..colon],
|
||||
port,
|
||||
connectionName[(slash + 1)..]);
|
||||
}
|
||||
|
||||
private static string NormalizeEndpoint(string? host, int port, string? database)
|
||||
{
|
||||
var normalizedHost = (host ?? string.Empty)
|
||||
@@ -460,3 +396,15 @@ internal static class NxtThemeRestoreDbAudit
|
||||
string.Equals(column.ColumnName, name, StringComparison.Ordinal) &&
|
||||
column.DataType == typeof(string);
|
||||
}
|
||||
|
||||
internal sealed record MariaDbEndpointReference(
|
||||
string? Host,
|
||||
int Port,
|
||||
string? Database)
|
||||
{
|
||||
internal static MariaDbEndpointReference From(MariaDbDatabaseOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
return new MariaDbEndpointReference(options.Host, options.Port, options.Database);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,10 @@ Console.CancelKeyPress += (_, eventArgs) =>
|
||||
cancellation.Cancel();
|
||||
};
|
||||
|
||||
var configurationPath = GetConfigurationPath(args);
|
||||
|
||||
try
|
||||
{
|
||||
var runtime = DatabaseRuntime.CreateDefault(configurationPath);
|
||||
var selection = CreateRuntimeSelection(args);
|
||||
var runtime = selection.Runtime;
|
||||
var statuses = await runtime.HealthService.CheckAllAsync(cancellation.Token);
|
||||
|
||||
foreach (var status in statuses)
|
||||
@@ -59,6 +58,7 @@ try
|
||||
await NxtThemeRestoreDbAudit.RunAsync(
|
||||
runtime.Executor,
|
||||
runtime.Options.MariaDb,
|
||||
selection.ReferenceMariaDb,
|
||||
cancellation.Token);
|
||||
await VerifyLegacyComparisonImportAsync(runtime.Executor, cancellation.Token);
|
||||
|
||||
@@ -131,23 +131,63 @@ static string FormatNullableBoolean(bool? value) => value switch
|
||||
static string FormatProviderErrorCode(int? value) =>
|
||||
value?.ToString(CultureInfo.InvariantCulture) ?? "none";
|
||||
|
||||
static string? GetConfigurationPath(string[] arguments)
|
||||
static DatabaseSmokeRuntimeSelection CreateRuntimeSelection(string[] arguments)
|
||||
{
|
||||
if (arguments.Length == 0)
|
||||
{
|
||||
return null;
|
||||
return CreateJsonRuntimeSelection(configurationPath: null);
|
||||
}
|
||||
|
||||
if (arguments.Length == 2 &&
|
||||
arguments[0].Equals("--config", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return arguments[1];
|
||||
return CreateJsonRuntimeSelection(arguments[1]);
|
||||
}
|
||||
|
||||
if (arguments.Length == 2 &&
|
||||
arguments[0].Equals("--legacy-runtime-root", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var root = Path.GetFullPath(arguments[1]);
|
||||
var iniPath = Path.Combine(root, "Res", "MmoneyCoder.ini");
|
||||
if (!File.Exists(iniPath))
|
||||
{
|
||||
throw new DatabaseConfigurationException(
|
||||
"The legacy runtime root does not contain Res\\MmoneyCoder.ini.");
|
||||
}
|
||||
|
||||
// Keep the selected file's endpoint as the comparison reference before
|
||||
// environment overrides are applied. Credentials never leave the
|
||||
// loader-owned DatabaseOptions instance.
|
||||
var selectedOptions = new LegacyIniDatabaseOptionsLoader(_ => null).Load(iniPath);
|
||||
var runtime = DatabaseRuntime.CreateLegacyExecutableDefault(
|
||||
root,
|
||||
fallbackConfigurationPath: Path.Combine(root, "missing-database.json"),
|
||||
legacyOverridePath: Path.Combine(root, "missing-legacy.ini"));
|
||||
return new DatabaseSmokeRuntimeSelection(
|
||||
runtime,
|
||||
MariaDbEndpointReference.From(selectedOptions.MariaDb));
|
||||
}
|
||||
|
||||
throw new DatabaseConfigurationException(
|
||||
"Usage: MBN_STOCK_WEBVIEW.DbSmoke [--config <path>|--manual-import-audit|--manual-import-fixture]");
|
||||
"Usage: MBN_STOCK_WEBVIEW.DbSmoke [--config <path>|--legacy-runtime-root <bin-debug-path>|--manual-import-audit|--manual-import-fixture]");
|
||||
}
|
||||
|
||||
static DatabaseSmokeRuntimeSelection CreateJsonRuntimeSelection(string? configurationPath)
|
||||
{
|
||||
var configuredOptions = new DatabaseOptionsLoader(_ => null).Load(configurationPath);
|
||||
var runtime = DatabaseRuntime.CreateDefault(configurationPath);
|
||||
var configuredMariaDb = configuredOptions.MariaDb;
|
||||
var reference = HasCompleteEndpointIdentity(configuredMariaDb)
|
||||
? MariaDbEndpointReference.From(configuredMariaDb)
|
||||
: MariaDbEndpointReference.From(runtime.Options.MariaDb);
|
||||
return new DatabaseSmokeRuntimeSelection(runtime, reference);
|
||||
}
|
||||
|
||||
static bool HasCompleteEndpointIdentity(MariaDbDatabaseOptions options) =>
|
||||
!string.IsNullOrWhiteSpace(options.Host) &&
|
||||
options.Port is >= 1 and <= 65_535 &&
|
||||
!string.IsNullOrWhiteSpace(options.Database);
|
||||
|
||||
static async Task VerifyLegacyComparisonImportAsync(
|
||||
IDataQueryExecutor executor,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -711,3 +751,7 @@ static async Task VerifyTradingHaltSelectorAsync(
|
||||
Console.WriteLine(
|
||||
$"TradingHaltSelector: {result.Items.Count.ToString(CultureInfo.InvariantCulture)} rows");
|
||||
}
|
||||
|
||||
internal sealed record DatabaseSmokeRuntimeSelection(
|
||||
DatabaseRuntime Runtime,
|
||||
MariaDbEndpointReference ReferenceMariaDb);
|
||||
|
||||
Reference in New Issue
Block a user