From 1f2e4494a2f3165489118743afa03ee85abfdc97 Mon Sep 17 00:00:00 2001 From: Jordan Dominion Date: Sat, 14 Oct 2023 22:47:14 -0400 Subject: [PATCH] Fix OD build paths being too long on Windows --- .../Components/Engine/OpenDreamInstaller.cs | 43 +++++++++++++------ .../Engine/WindowsOpenDreamInstaller.cs | 25 ++++++++++- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs b/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs index dc0bb371ec..1aa0bec4ec 100644 --- a/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Engine/OpenDreamInstaller.cs @@ -206,21 +206,25 @@ namespace Tgstation.Server.Host.Components.Engine var dotnetPath = dotnetPaths[selectedPathIndex]; - await using (var buildProcess = ProcessExecutor.LaunchProcess( - dotnetPath, + int? buildExitCode = null; + await HandleExtremelyLongPathOperation( + async shortenedPath => + { + await using var buildProcess = ProcessExecutor.LaunchProcess( + dotnetPath, + shortenedPath, + "build -c Release /p:TgsEngineBuild=true", + null, + true, + true); + buildExitCode = await buildProcess.Lifetime; + Logger.LogDebug("Build output:{newLine}{output}", Environment.NewLine, await buildProcess.GetCombinedOutput(cancellationToken)); + }, sourcePath, - "build -c Release /p:TgsEngineBuild=true", - null, - true, - true)) - { - var buildExitCode = await buildProcess.Lifetime; + cancellationToken); - Logger.LogDebug("Build output:{newLine}{output}", Environment.NewLine, await buildProcess.GetCombinedOutput(cancellationToken)); - - if (buildExitCode != 0) - throw new JobException("OpenDream build failed!"); - } + if (buildExitCode != 0) + throw new JobException("OpenDream build failed!"); await IOManager.MoveDirectory( IOManager.ConcatPath( @@ -250,6 +254,19 @@ namespace Tgstation.Server.Host.Components.Engine return ValueTask.CompletedTask; } + /// + /// Perform an operation on a very long path. + /// + /// A taking a shortened path and resulting in a representing the running operation. + /// The original path to the directory. + /// The for the operation. + /// A representing the running operation. + protected virtual ValueTask HandleExtremelyLongPathOperation( + Func shortenedPathOperation, + string originalPath, + CancellationToken cancellationToken) + => shortenedPathOperation(originalPath); // based god linux has no such weakness + /// /// Gets the paths to the server and client executables. /// diff --git a/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs b/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs index de37cc8b5f..20162e432e 100644 --- a/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Engine/WindowsOpenDreamInstaller.cs @@ -21,6 +21,11 @@ namespace Tgstation.Server.Host.Components.Engine /// sealed class WindowsOpenDreamInstaller : OpenDreamInstaller { + /// + /// The for the . + /// + readonly ISymlinkFactory symlinkFactory; + /// /// Initializes a new instance of the class. /// @@ -30,13 +35,15 @@ namespace Tgstation.Server.Host.Components.Engine /// The for the . /// The for the . /// The of for the . + /// The value of . public WindowsOpenDreamInstaller( IIOManager ioManager, ILogger logger, IPlatformIdentifier platformIdentifier, IProcessExecutor processExecutor, IRepositoryManager repositoryManager, - IOptions generalConfigurationOptions) + IOptions generalConfigurationOptions, + ISymlinkFactory symlinkFactory) : base( ioManager, logger, @@ -45,6 +52,7 @@ namespace Tgstation.Server.Host.Components.Engine repositoryManager, generalConfigurationOptions) { + this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory)); } /// @@ -59,6 +67,21 @@ namespace Tgstation.Server.Host.Components.Engine installPath, cancellationToken)); + /// + protected override async ValueTask HandleExtremelyLongPathOperation(Func shortenedPathOperation, string originalPath, CancellationToken cancellationToken) + { + var shortPath = $"C:/{Guid.NewGuid()}"; + await symlinkFactory.CreateSymbolicLink(originalPath, shortPath, cancellationToken); + try + { + await shortenedPathOperation(shortPath); + } + finally + { + await IOManager.DeleteDirectory(shortPath, CancellationToken.None); // DCT: Should always run. + } + } + /// /// Attempt to add the DreamDaemon executable as an exception to the Windows firewall. ///