diff --git a/src/Tgstation.Server.Host/Components/ByondExecutableLock.cs b/src/Tgstation.Server.Host/Components/ByondExecutableLock.cs new file mode 100644 index 0000000000..2e89dacb38 --- /dev/null +++ b/src/Tgstation.Server.Host/Components/ByondExecutableLock.cs @@ -0,0 +1,17 @@ +using System; + +namespace Tgstation.Server.Host.Components +{ + sealed class ByondExecutableLock : IByondExecutableLock + { + public Version Version { get; set; } + + public string DreamDaemonPath { get; set; } + + public string DreamMakerPath { get; set; } + + public void Dispose() { } + + public void DoNotDeleteThisSession() { } + } +} diff --git a/src/Tgstation.Server.Host/Components/ByondManager.cs b/src/Tgstation.Server.Host/Components/ByondManager.cs index aff60de879..1c00689b34 100644 --- a/src/Tgstation.Server.Host/Components/ByondManager.cs +++ b/src/Tgstation.Server.Host/Components/ByondManager.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO.Compression; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -13,6 +14,12 @@ namespace Tgstation.Server.Host.Components sealed class ByondManager : IByondManager { const string VersionFileName = "Version.txt"; + const string ActiveVersionFileName = "ActiveVersion.txt"; + + const string BinPath = "byond/bin"; + + /// + public Version ActiveVersion { get; private set; } /// /// The for the @@ -87,27 +94,69 @@ namespace Tgstation.Server.Host.Components } /// - public Task ChangeVersion(Version version, CancellationToken cancellationToken) + public async Task ChangeVersion(Version version, CancellationToken cancellationToken) { - throw new NotImplementedException(); + await InstallVersion(version, cancellationToken).ConfigureAwait(false); + await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false); + ActiveVersion = version; } /// - public Task ClearCache(CancellationToken cancellationToken) + public async Task UseExecutables(Version requiredVersion, CancellationToken cancellationToken) { - throw new NotImplementedException(); + var versionToUse = requiredVersion ?? ActiveVersion; + if (versionToUse == null) + throw new InvalidOperationException("No BYOND versions installed!"); + await InstallVersion(requiredVersion, cancellationToken).ConfigureAwait(false); + + var versionKey = VersionKey(versionToUse); + + return new ByondExecutableLock + { + DreamDaemonPath = ioManager.ResolvePath(ioManager.ConcatPath(versionKey, byondInstaller.DreamDaemonName)), + DreamMakerPath = ioManager.ResolvePath(ioManager.ConcatPath(versionKey, byondInstaller.DreamMakerName)), + Version = versionToUse + }; } /// - public Task GetVersion(CancellationToken cancellationToken) + public async Task StartAsync(CancellationToken cancellationToken) { - throw new NotImplementedException(); + var cacheCleanTask = byondInstaller.CleanCache(cancellationToken); + + var activeVersionBytesTask = ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken); + + var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false); + + async Task ReadVersion(string path) + { + var bytes = await ioManager.ReadAllBytes(ioManager.ConcatPath(path, VersionFileName), cancellationToken).ConfigureAwait(false); + var text = Encoding.UTF8.GetString(bytes); + if (Version.TryParse(text, out var version)) + { + var key = VersionKey(version); + lock (installedVersions) + if (!installedVersions.ContainsKey(key)) + { + installedVersions.Add(key, Task.CompletedTask); + return; + } + } + await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false); + }; + + await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false); + + var activeVersionString = Encoding.UTF8.GetString(await activeVersionBytesTask.ConfigureAwait(false)); + if (Version.TryParse(activeVersionString, out var activeVersion)) + ActiveVersion = activeVersion; + else + await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false); + + await cacheCleanTask.ConfigureAwait(false); } /// - public IByondExecutableLock UseExecutables(Version requiredVersion) - { - throw new NotImplementedException(); - } + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; } } diff --git a/src/Tgstation.Server.Host/Components/IByondInstaller.cs b/src/Tgstation.Server.Host/Components/IByondInstaller.cs index 98a8e4831d..2779e19969 100644 --- a/src/Tgstation.Server.Host/Components/IByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/IByondInstaller.cs @@ -7,10 +7,20 @@ using Stream = System.IO.Stream; namespace Tgstation.Server.Host.Components { /// - /// For downloading and installing BYOND extractions + /// For downloading and installing BYOND extractions for a given system /// interface IByondInstaller { + /// + /// Get the file name of the DreamDaemon executable + /// + string DreamDaemonName { get; } + + /// + /// Get the file name of the DreamMaker executable + /// + string DreamMakerName { get; } + /// /// Download a given BYOND /// @@ -26,5 +36,12 @@ namespace Tgstation.Server.Host.Components /// The for the operation /// Task InstallByond(string path, CancellationToken cancellationToken); + + /// + /// Attempts to cleans the BYOND cache folder for the system + /// + /// The for the operation + /// A representing the running operation + Task CleanCache(CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Tgstation.Server.Host/Components/IByondManager.cs b/src/Tgstation.Server.Host/Components/IByondManager.cs index a0226edd64..c6ac12119e 100644 --- a/src/Tgstation.Server.Host/Components/IByondManager.cs +++ b/src/Tgstation.Server.Host/Components/IByondManager.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Extensions.Hosting; +using System; using System.Threading; using System.Threading.Tasks; @@ -7,8 +8,13 @@ namespace Tgstation.Server.Host.Components /// /// For managing the BYOND installation /// - public interface IByondManager + public interface IByondManager : IHostedService { + /// + /// The currently active BYOND version + /// + Version ActiveVersion { get; } + /// /// Change the active BYOND version /// @@ -16,24 +22,12 @@ namespace Tgstation.Server.Host.Components /// The for the operation Task ChangeVersion(Version version, CancellationToken cancellationToken); - /// - /// Get the currently active BYOND version - /// - /// The for the operation - /// The current BYOND version - Task GetVersion(CancellationToken cancellationToken); - /// /// Lock the current installation's location and return a /// /// The BYOND required - IByondExecutableLock UseExecutables(Version requiredVersion); - - /// - /// Clears the cache folder - /// /// The for the operation - /// A representing the running operation - Task ClearCache(CancellationToken cancellationToken); + /// A resulting in the requested + Task UseExecutables(Version requiredVersion, CancellationToken cancellationToken); } } \ No newline at end of file