diff --git a/Launcher.Next.Autodesk/AutodeskAdapters.cs b/Launcher.Next.Autodesk/AutodeskAdapters.cs index 6a31241..b107f6e 100644 --- a/Launcher.Next.Autodesk/AutodeskAdapters.cs +++ b/Launcher.Next.Autodesk/AutodeskAdapters.cs @@ -25,7 +25,9 @@ public sealed class StartupScriptBuilder : IStartupScriptBuilder var diagnostic = paths.Diagnostic ? "_.CMDECHO\n1\n_.NOMUTT\n0\n_.LOGFILEMODE\n1\n" : string.Empty; - var commands = paths.Diagnostic + var commands = paths.Apply + ? "_.UNDO\nMARK\nPXP-OA\nPXP-OA\n_.UNDO\nBACK\n" + : paths.Diagnostic ? "PHP_REC_AUTOMATION_BEFORE_PXP_1\nPXP-OA\nPHP_REC_AUTOMATION_AFTER_PXP_1\nPHP_REC_AUTOMATION_BEFORE_PXP_2\nPXP-OA\nPHP_REC_AUTOMATION_AFTER_PXP_2\n" : "PXP-OA\nPXP-OA\n"; return dialogFreeOpen + "_.OPEN\n" + quote(fixture) + "\n" + diagnostic + BuildNetloadScript(paths.ValidatedPackageRoot, paths.EntryAssembly) + diff --git a/Launcher.Next.Core/Contracts.cs b/Launcher.Next.Core/Contracts.cs index 606c1cb..7a01fef 100644 --- a/Launcher.Next.Core/Contracts.cs +++ b/Launcher.Next.Core/Contracts.cs @@ -28,7 +28,7 @@ public interface ILocalPackageStore { Task GetCurrentVersionAsync(strin public interface IPackageActivator { Task ActivateAsync(string packageId, string version, CancellationToken cancellationToken); } public interface IRollbackManager { Task RollbackAsync(string packageId, CancellationToken cancellationToken); } public interface IAutodeskProcessLauncher { PreparedLaunch Prepare(LaunchRequest request); } -public sealed record ResolvedAutomationScriptPaths(string ValidatedPackageRoot, string EntryAssembly, string FixtureOrthoDwg, string FixtureModelDwg, string AutomationScriptPath, bool Diagnostic); +public sealed record ResolvedAutomationScriptPaths(string ValidatedPackageRoot, string EntryAssembly, string FixtureOrthoDwg, string FixtureModelDwg, string AutomationScriptPath, bool Diagnostic, bool Apply); public interface IStartupScriptBuilder { string BuildNetloadScript(string validatedPackageRoot, string entryAssembly); string BuildAutomationScript(ResolvedAutomationScriptPaths paths); } public interface ILauncherConfigurationProvider { LauncherMode GetMode(); } public interface ILauncherTelemetry { void Write(string eventType, IReadOnlyDictionary? fields = null); } diff --git a/Launcher.Next.Infrastructure/PilotExecutionService.cs b/Launcher.Next.Infrastructure/PilotExecutionService.cs index 4dcfb1d..6ee7bfe 100644 --- a/Launcher.Next.Infrastructure/PilotExecutionService.cs +++ b/Launcher.Next.Infrastructure/PilotExecutionService.cs @@ -116,7 +116,7 @@ public sealed class PilotExecutionService( scriptPath = paths.Require(LauncherPathVariableNames.AutomationScriptPath); if (!Path.GetFullPath(scriptPath).StartsWith(Path.GetFullPath(paths.Require(LauncherPathVariableNames.LocalSessionRoot)).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException("AUTOMATION_SCRIPT_OUTSIDE_SESSION_ROOT"); Directory.CreateDirectory(Path.GetDirectoryName(scriptPath)!); - var script = scriptBuilder.BuildAutomationScript(new(versionDirectory, request.Preparation.Manifest.EntryAssembly, paths.Require(LauncherPathVariableNames.FixtureOrthoDwg), paths.Require(LauncherPathVariableNames.FixtureModelDwg), scriptPath, request.Preparation.Configuration.AutomationDiagnostic)); + var script = scriptBuilder.BuildAutomationScript(new(versionDirectory, request.Preparation.Manifest.EntryAssembly, paths.Require(LauncherPathVariableNames.FixtureOrthoDwg), paths.Require(LauncherPathVariableNames.FixtureModelDwg), scriptPath, request.Preparation.Configuration.AutomationDiagnostic, request.Preparation.Configuration.LaunchMode == AcadLaunchMode.NextPilotApply)); await File.WriteAllTextAsync(scriptPath, script, cancellationToken); } var arguments = new AcadArgumentBuilder().Build(request.Preparation.Configuration.LaunchMode, automation ? scriptPath : null); diff --git a/tests/Launcher.Next.Tests/PathAndLaunchTests.cs b/tests/Launcher.Next.Tests/PathAndLaunchTests.cs index c83b61c..3d18720 100644 --- a/tests/Launcher.Next.Tests/PathAndLaunchTests.cs +++ b/tests/Launcher.Next.Tests/PathAndLaunchTests.cs @@ -65,7 +65,7 @@ public sealed class PathAndLaunchTests try { var model = Path.Combine(root, "model.dwg"); File.WriteAllText(model, string.Empty); - var paths = new ResolvedAutomationScriptPaths(root, entry, fixture, model, Path.Combine(root, "preview.scr"), false); + var paths = new ResolvedAutomationScriptPaths(root, entry, fixture, model, Path.Combine(root, "preview.scr"), false, false); var first = new StartupScriptBuilder().BuildAutomationScript(paths); var second = new StartupScriptBuilder().BuildAutomationScript(paths); Assert.Equal(first, second); Assert.EndsWith("\n", first); Assert.Equal(2, System.Text.RegularExpressions.Regex.Matches(first, "PXP-OA").Count); Assert.True(first.IndexOf("_.FILEDIA\n0", StringComparison.Ordinal) < first.IndexOf("_.OPEN", StringComparison.Ordinal)); @@ -78,7 +78,13 @@ public sealed class PathAndLaunchTests [Fact] public void DiagnosticScript_BracketsBothPxpOaCommands() { var root = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); Directory.CreateDirectory(root); var entry = "P.dll"; var fixture = Path.Combine(root, "fixture.dwg"); var model = Path.Combine(root, "model.dwg"); File.WriteAllText(Path.Combine(root, entry), ""); File.WriteAllText(fixture, ""); File.WriteAllText(model, ""); - try { var script = new StartupScriptBuilder().BuildAutomationScript(new(root, entry, fixture, model, Path.Combine(root, "diagnostic.scr"), true)); Assert.Contains("PHP_REC_AUTOMATION_BEFORE_PXP_1\nPXP-OA\nPHP_REC_AUTOMATION_AFTER_PXP_1", script); Assert.Contains("PHP_REC_AUTOMATION_BEFORE_PXP_2\nPXP-OA\nPHP_REC_AUTOMATION_AFTER_PXP_2", script); } + try { var script = new StartupScriptBuilder().BuildAutomationScript(new(root, entry, fixture, model, Path.Combine(root, "diagnostic.scr"), true, false)); Assert.Contains("PHP_REC_AUTOMATION_BEFORE_PXP_1\nPXP-OA\nPHP_REC_AUTOMATION_AFTER_PXP_1", script); Assert.Contains("PHP_REC_AUTOMATION_BEFORE_PXP_2\nPXP-OA\nPHP_REC_AUTOMATION_AFTER_PXP_2", script); } + finally { Directory.Delete(root, true); } + } + [Fact] public void ApplyScript_MarksCreatesDeduplicatesAndUndoes() + { + var root = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); Directory.CreateDirectory(root); var entry = "P.dll"; var fixture = Path.Combine(root, "fixture.dwg"); var model = Path.Combine(root, "model.dwg"); File.WriteAllText(Path.Combine(root, entry), ""); File.WriteAllText(fixture, ""); File.WriteAllText(model, ""); + try { var script = new StartupScriptBuilder().BuildAutomationScript(new(root, entry, fixture, model, Path.Combine(root, "apply.scr"), false, true)); Assert.Contains("_.UNDO\nMARK\nPXP-OA\nPXP-OA\n_.UNDO\nBACK", script); } finally { Directory.Delete(root, true); } } [Fact] public void DiagnosticScript_RecordsExactBytes() { var text = "PXP-OA\n"; Assert.Equal(Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(text))), Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(text)))); }