diff --git a/src/DMAPI/tgs.dm b/src/DMAPI/tgs.dm
index 6187a67825..6d35cf6593 100644
--- a/src/DMAPI/tgs.dm
+++ b/src/DMAPI/tgs.dm
@@ -1,6 +1,6 @@
// tgstation-server DMAPI
-#define TGS_DMAPI_VERSION "6.5.3"
+#define TGS_DMAPI_VERSION "6.6.0"
// All functions and datums outside this document are subject to change with any version and should not be relied on.
@@ -73,11 +73,11 @@
#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3
/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path.
#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4
-/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND.
+/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND, engine type of the installing BYOND.
#define TGS_EVENT_BYOND_INSTALL_START 5
/// When a BYOND install operation fails. Parameters: Error message
#define TGS_EVENT_BYOND_INSTALL_FAIL 6
-/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND.
+/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND, engine type of the current BYOND, engine type of the new BYOND.
#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7
/// When the compiler starts running. Parameters: Game directory path, origin commit SHA.
#define TGS_EVENT_COMPILE_START 8
@@ -129,6 +129,11 @@
/// DreamDaemon Ultrasafe security level.
#define TGS_SECURITY_ULTRASAFE 2
+/// The Build Your Own Net Dream engine.
+#define TGS_ENGINE_TYPE_BYOND 0
+/// The OpenDream engine.
+#define TGS_ENGINE_TYPE_OPENDREAM 1
+
//REQUIRED HOOKS
/**
diff --git a/src/Tgstation.Server.Api/Models/EngineType.cs b/src/Tgstation.Server.Api/Models/EngineType.cs
new file mode 100644
index 0000000000..67410c1d47
--- /dev/null
+++ b/src/Tgstation.Server.Api/Models/EngineType.cs
@@ -0,0 +1,18 @@
+namespace Tgstation.Server.Api.Models
+{
+ ///
+ /// The type of engine the codebase is using.
+ ///
+ public enum EngineType
+ {
+ ///
+ /// Build your own net dream,
+ ///
+ Byond,
+
+ ///
+ /// The OpenDream BYOND reimplementation.
+ ///
+ OpenDream,
+ }
+}
diff --git a/src/Tgstation.Server.Api/Models/Internal/ByondVersion.cs b/src/Tgstation.Server.Api/Models/Internal/ByondVersion.cs
new file mode 100644
index 0000000000..8526d159b6
--- /dev/null
+++ b/src/Tgstation.Server.Api/Models/Internal/ByondVersion.cs
@@ -0,0 +1,109 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+
+namespace Tgstation.Server.Api.Models.Internal
+{
+ ///
+ /// Information about a Byond installation.
+ ///
+ public class ByondVersion : IEquatable
+ {
+ ///
+ /// The .
+ ///
+ [RequestOptions(FieldPresence.Required)]
+ public EngineType? Engine { get; set; }
+
+ ///
+ /// The of the engine.
+ ///
+ [ResponseOptions]
+ public Version? Version { get; set; }
+
+ ///
+ /// The git committish of the . On response, this will always be a commit SHA.
+ ///
+ [ResponseOptions]
+ [StringLength(Limits.MaximumCommitShaLength)]
+ public string? SourceCommittish { get; set; }
+
+ ///
+ /// Parses a stringified .
+ ///
+ /// The input .
+ /// The output .
+ /// if parsing was successful, otherwise.
+ public static bool TryParse(string input, out ByondVersion? byondVersion)
+ {
+ if (input == null)
+ throw new ArgumentNullException(nameof(input));
+
+ var splits = input.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
+ byondVersion = null;
+
+ if (splits.Length > 2)
+ return false;
+
+ EngineType engine;
+ if (splits.Length > 1)
+ {
+ if (!Enum.TryParse(splits[0], out engine))
+ return false;
+ }
+ else
+ engine = EngineType.Byond;
+
+ if (!Version.TryParse(splits.Last(), out var version))
+ return false;
+
+ byondVersion = new ByondVersion
+ {
+ Engine = engine,
+ Version = version,
+ };
+ return true;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ByondVersion()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to copy.
+ public ByondVersion(ByondVersion other)
+ {
+ if (other == null)
+ throw new ArgumentNullException(nameof(other));
+
+ Version = other.Version;
+ Engine = other.Engine;
+ SourceCommittish = other.SourceCommittish;
+ }
+
+ ///
+ public bool Equals(ByondVersion other)
+ {
+ // https://github.com/dotnet/roslyn-analyzers/issues/2875
+#pragma warning disable CA1062 // Validate arguments of public methods
+ return other!.Version == Version
+ && other.Engine == Engine;
+#pragma warning restore CA1062 // Validate arguments of public methods
+ }
+
+ ///
+ public override bool Equals(object obj)
+ => obj is ByondVersion other && Equals(other);
+
+ ///
+ public override string ToString() => $"{(Engine != EngineType.Byond ? $"{Engine}-" : String.Empty)}{Version}"; // BYOND isn't display for backwards compatibility. SourceCommittish is not included
+
+ ///
+ public override int GetHashCode() => ToString().GetHashCode();
+ }
+}
diff --git a/src/Tgstation.Server.Api/Models/Request/ByondVersionDeleteRequest.cs b/src/Tgstation.Server.Api/Models/Request/ByondVersionDeleteRequest.cs
index aaf8585c9b..ad5eac45cc 100644
--- a/src/Tgstation.Server.Api/Models/Request/ByondVersionDeleteRequest.cs
+++ b/src/Tgstation.Server.Api/Models/Request/ByondVersionDeleteRequest.cs
@@ -1,16 +1,13 @@
using System;
+using Tgstation.Server.Api.Models.Internal;
+
namespace Tgstation.Server.Api.Models.Request
{
///
/// A request to delete a specific .
///
- public class ByondVersionDeleteRequest
+ public class ByondVersionDeleteRequest : ByondVersion
{
- ///
- /// The BYOND version to install.
- ///
- [RequestOptions(FieldPresence.Required)]
- public Version? Version { get; set; }
}
}
diff --git a/src/Tgstation.Server.Api/Models/Request/ByondVersionRequest.cs b/src/Tgstation.Server.Api/Models/Request/ByondVersionRequest.cs
index b86eea074a..a04dfd0d7e 100644
--- a/src/Tgstation.Server.Api/Models/Request/ByondVersionRequest.cs
+++ b/src/Tgstation.Server.Api/Models/Request/ByondVersionRequest.cs
@@ -1,13 +1,22 @@
-namespace Tgstation.Server.Api.Models.Request
+using System;
+
+using Tgstation.Server.Api.Models.Internal;
+
+namespace Tgstation.Server.Api.Models.Request
{
///
- /// A request to install a BYOND .
+ /// A request to install a .
///
- public sealed class ByondVersionRequest : ByondVersionDeleteRequest
+ public sealed class ByondVersionRequest : ByondVersion
{
///
/// If a custom BYOND version is to be uploaded.
///
public bool? UploadCustomZip { get; set; }
+
+ ///
+ /// The remote repository for non- s. By default, this is the original git repository of the target .
+ ///
+ public Uri? SourceRepository { get; set; }
}
}
diff --git a/src/Tgstation.Server.Api/Models/Response/ByondResponse.cs b/src/Tgstation.Server.Api/Models/Response/ByondResponse.cs
index 64b01090d5..92d524728d 100644
--- a/src/Tgstation.Server.Api/Models/Response/ByondResponse.cs
+++ b/src/Tgstation.Server.Api/Models/Response/ByondResponse.cs
@@ -1,16 +1,19 @@
-using System;
+using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Api.Models.Response
{
///
- /// Represents an installed BYOND .
+ /// Represents an installed .
///
- public sealed class ByondResponse
+ public sealed class ByondResponse : ByondVersion
{
///
- /// The installed BYOND . BYOND itself only considers the and numbers. TGS uses the number to represent installed custom versions.
+ /// Initializes a new instance of the class.
///
- [ResponseOptions]
- public Version? Version { get; set; }
+ /// The to copy.
+ public ByondResponse(ByondVersion byondVersion)
+ : base(byondVersion)
+ {
+ }
}
}
diff --git a/src/Tgstation.Server.Api/Models/Response/CompileJobResponse.cs b/src/Tgstation.Server.Api/Models/Response/CompileJobResponse.cs
index 60444d9c3c..a349710f07 100644
--- a/src/Tgstation.Server.Api/Models/Response/CompileJobResponse.cs
+++ b/src/Tgstation.Server.Api/Models/Response/CompileJobResponse.cs
@@ -1,9 +1,11 @@
using System;
+using Tgstation.Server.Api.Models.Internal;
+
namespace Tgstation.Server.Api.Models.Response
{
///
- public sealed class CompileJobResponse : Internal.CompileJob
+ public sealed class CompileJobResponse : CompileJob
{
///
/// The relating to this job.
@@ -16,9 +18,14 @@ namespace Tgstation.Server.Api.Models.Response
public RevisionInformation? RevisionInformation { get; set; }
///
- /// The the was made with.
+ /// The the was made with.
///
- public Version? ByondVersion { get; set; }
+ public ByondVersion? ByondVersion { get; set; }
+
+ ///
+ /// The the was made with.
+ ///
+ public EngineType? Engine { get; set; }
///
/// The origin of the repository the compile job was built from.
diff --git a/src/Tgstation.Server.Api/Rights/ByondRights.cs b/src/Tgstation.Server.Api/Rights/ByondRights.cs
index 288d8ca3b8..6e20a62b3b 100644
--- a/src/Tgstation.Server.Api/Rights/ByondRights.cs
+++ b/src/Tgstation.Server.Api/Rights/ByondRights.cs
@@ -14,33 +14,43 @@ namespace Tgstation.Server.Api.Rights
None = 0,
///
- /// User may view the active installed BYOND version.
+ /// User may view the active installed engine versions.
///
ReadActive = 1 << 0,
///
- /// User may list all installed BYOND versions.
+ /// User may list all installed engine versions.
///
ListInstalled = 1 << 1,
///
- /// User may install official BYOND versions or change the active BYOND version.
+ /// User may install official versions or change the active version.
///
- InstallOfficialOrChangeActiveVersion = 1 << 2,
+ InstallOfficialOrChangeActiveByondVersion = 1 << 2,
///
- /// User may cancel BYOND installation job.
+ /// User may cancel an engine installation job.
///
CancelInstall = 1 << 3,
///
- /// User may upload and activate custom BYOND builds.
+ /// User may upload and activate custom builds.
///
- InstallCustomVersion = 1 << 4,
+ InstallCustomByondVersion = 1 << 4,
///
- /// User may delete non-active BYOND builds.
+ /// User may delete non-active engine builds.
///
DeleteInstall = 1 << 5,
+
+ ///
+ /// User may install official versions or change the active version.
+ ///
+ InstallOfficialOrChangeActiveOpenDreamVersion = 1 << 6,
+
+ ///
+ /// User may activate custom builds via zip upload or custom git committish.
+ ///
+ InstallCustomOpenDreamVersion = 1 << 7,
}
}
diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs b/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs
deleted file mode 100644
index 334b3469ea..0000000000
--- a/src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-using Tgstation.Server.Host.Utils;
-
-namespace Tgstation.Server.Host.Components.Byond
-{
- ///
- sealed class ByondExecutableLock : ReferenceCounter, IByondExecutableLock
- {
- ///
- public Version Version => Instance.Version;
-
- ///
- public string DreamDaemonPath => Instance.DreamDaemonPath;
-
- ///
- public string DreamMakerPath => Instance.DreamMakerPath;
-
- ///
- public bool SupportsCli => Instance.SupportsCli;
-
- ///
- public bool SupportsMapThreads => Instance.SupportsMapThreads;
-
- ///
- public void DoNotDeleteThisSession() => DangerousDropReference();
- }
-}
diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondInstallation.cs b/src/Tgstation.Server.Host/Components/Byond/ByondInstallation.cs
index 8554190d0f..35a7fd614f 100644
--- a/src/Tgstation.Server.Host/Components/Byond/ByondInstallation.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/ByondInstallation.cs
@@ -1,54 +1,148 @@
using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
using System.Threading.Tasks;
+using System.Web;
+
+using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
+using Tgstation.Server.Host.Components.Deployment;
namespace Tgstation.Server.Host.Components.Byond
{
- ///
- sealed class ByondInstallation : IByondInstallation
+ ///
+ /// Implementation of for .
+ ///
+ sealed class ByondInstallation : IEngineInstallation
{
///
- public Version Version { get; }
+ public ByondVersion Version { get; }
///
- public string DreamDaemonPath { get; }
+ public string ServerExePath { get; }
///
- public string DreamMakerPath { get; }
+ public string CompilerExePath { get; }
///
- public bool SupportsCli { get; }
+ public bool PromptsForNetworkAccess { get; }
///
- public bool SupportsMapThreads { get; }
+ public bool HasStandardOutput { get; }
+
+ ///
+ public Task InstallationTask { get; }
///
- /// The that completes when the BYOND version finished installing.
+ /// If map threads are supported by the .
///
- public Task InstallationTask { get; }
+ readonly bool supportsMapThreads;
+
+ ///
+ /// Change a given into the appropriate DreamDaemon command line word.
+ ///
+ /// The level to change.
+ /// A representation of the command line parameter.
+ static string SecurityWord(DreamDaemonSecurity securityLevel)
+ {
+ return securityLevel switch
+ {
+ DreamDaemonSecurity.Safe => "safe",
+ DreamDaemonSecurity.Trusted => "trusted",
+ DreamDaemonSecurity.Ultrasafe => "ultrasafe",
+ _ => throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel)),
+ };
+ }
+
+ ///
+ /// Change a given into the appropriate DreamDaemon command line word.
+ ///
+ /// The level to change.
+ /// A representation of the command line parameter.
+ static string VisibilityWord(DreamDaemonVisibility visibility)
+ {
+ return visibility switch
+ {
+ DreamDaemonVisibility.Public => "public",
+ DreamDaemonVisibility.Private => "private",
+ DreamDaemonVisibility.Invisible => "invisible",
+ _ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon visibility level: {0}", visibility)),
+ };
+ }
///
/// Initializes a new instance of the class.
///
/// The value of .
/// The value of .
- /// The value of .
- /// The value of .
- /// The value of .
- /// The value of .
+ /// The value of .
+ /// The value of .
+ /// If a CLI application is being used.
+ /// The value of .
public ByondInstallation(
Task installationTask,
- Version version,
+ ByondVersion version,
string dreamDaemonPath,
string dreamMakerPath,
bool supportsCli,
bool supportsMapThreads)
{
InstallationTask = installationTask ?? throw new ArgumentNullException(nameof(installationTask));
+ ArgumentNullException.ThrowIfNull(version);
+
+ if (version.Engine.Value != EngineType.Byond)
+ throw new ArgumentException($"Invalid EngineType: {version.Engine.Value}", nameof(version));
+
Version = version ?? throw new ArgumentNullException(nameof(version));
- DreamDaemonPath = dreamDaemonPath ?? throw new ArgumentNullException(nameof(dreamDaemonPath));
- DreamMakerPath = dreamMakerPath ?? throw new ArgumentNullException(nameof(dreamMakerPath));
- SupportsCli = supportsCli;
- SupportsMapThreads = supportsMapThreads;
+ ServerExePath = dreamDaemonPath ?? throw new ArgumentNullException(nameof(dreamDaemonPath));
+ CompilerExePath = dreamMakerPath ?? throw new ArgumentNullException(nameof(dreamMakerPath));
+ HasStandardOutput = supportsCli;
+ PromptsForNetworkAccess = !supportsCli;
+ this.supportsMapThreads = supportsMapThreads;
}
+
+ ///
+ public string FormatServerArguments(
+ IDmbProvider dmbProvider,
+ IReadOnlyDictionary parameters,
+ DreamDaemonLaunchParameters launchParameters,
+ string logFilePath)
+ {
+ ArgumentNullException.ThrowIfNull(dmbProvider);
+ ArgumentNullException.ThrowIfNull(parameters);
+ ArgumentNullException.ThrowIfNull(launchParameters);
+
+ var parametersString = String.Join('&', parameters.Select(kvp => $"{HttpUtility.UrlEncode(kvp.Key)}={HttpUtility.UrlEncode(kvp.Value)}"));
+
+ if (!String.IsNullOrEmpty(launchParameters.AdditionalParameters))
+ parametersString = $"{parametersString}&{launchParameters.AdditionalParameters}";
+
+ var arguments = String.Format(
+ CultureInfo.InvariantCulture,
+ "{0} -port {1} -ports 1-65535 {2}-close -verbose -{3} -{4}{5}{6}{7} -params \"{8}\"",
+ dmbProvider.DmbName,
+ launchParameters.Port.Value,
+ launchParameters.AllowWebClient.Value
+ ? "-webclient "
+ : String.Empty,
+ SecurityWord(launchParameters.SecurityLevel.Value),
+ VisibilityWord(launchParameters.Visibility.Value),
+ logFilePath != null
+ ? $" -logself -log {logFilePath}"
+ : String.Empty, // DD doesn't output anything if -logself is set???
+ launchParameters.StartProfiler.Value
+ ? " -profile"
+ : String.Empty,
+ supportsMapThreads && launchParameters.MapThreads.Value != 0
+ ? $" -map-threads {launchParameters.MapThreads.Value}"
+ : String.Empty,
+ parametersString);
+ return arguments;
+ }
+
+ ///
+ public string FormatCompilerArguments(string dmePath)
+ => $"-clean \"{dmePath ?? throw new ArgumentNullException(nameof(dmePath))}\"";
}
}
diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs
index 2478acdc1f..8260eafffa 100644
--- a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Components.Byond
@@ -24,10 +25,10 @@ namespace Tgstation.Server.Host.Components.Byond
public static Version MapThreadsVersion => new (515, 1609);
///
- public abstract string DreamMakerName { get; }
+ public abstract string CompilerName { get; }
///
- public abstract string PathToUserByondFolder { get; }
+ public abstract string PathToUserFolder { get; }
///
/// Gets the URL formatter string for downloading a byond version of {0:Major} {1:Minor}.
@@ -63,7 +64,7 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public abstract string GetDreamDaemonName(Version version, out bool supportsCli, out bool supportsMapThreads);
+ public abstract string GetDreamDaemonName(ByondVersion version, out bool supportsCli, out bool supportsMapThreads);
///
public async Task CleanCache(CancellationToken cancellationToken)
@@ -73,7 +74,7 @@ namespace Tgstation.Server.Host.Components.Byond
Logger.LogDebug("Cleaning BYOND cache...");
await IOManager.DeleteDirectory(
IOManager.ConcatPath(
- PathToUserByondFolder,
+ PathToUserFolder,
CacheDirectoryName),
cancellationToken);
}
@@ -84,18 +85,18 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public abstract ValueTask InstallByond(Version version, string path, CancellationToken cancellationToken);
+ public abstract ValueTask InstallByond(ByondVersion version, string path, CancellationToken cancellationToken);
///
- public abstract ValueTask UpgradeInstallation(Version version, string path, CancellationToken cancellationToken);
+ public abstract ValueTask UpgradeInstallation(ByondVersion version, string path, CancellationToken cancellationToken);
///
- public async ValueTask DownloadVersion(Version version, CancellationToken cancellationToken)
+ public async ValueTask DownloadVersion(ByondVersion version, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(version);
- Logger.LogTrace("Downloading BYOND version {major}.{minor}...", version.Major, version.Minor);
- var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsUrlTemplate, version.Major, version.Minor);
+ Logger.LogTrace("Downloading BYOND version {major}.{minor}...", version.Version.Major, version.Version.Minor);
+ var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsUrlTemplate, version.Version.Major, version.Version.Minor);
await using var download = fileDownloader.DownloadFile(new Uri(url), null);
await using var buffer = new BufferedFileStreamProvider(
diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs b/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs
index 73fadec987..3c6f06c3ad 100644
--- a/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/ByondManager.cs
@@ -10,6 +10,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Host.Components.Events;
using Tgstation.Server.Host.IO;
@@ -47,10 +48,10 @@ namespace Tgstation.Server.Host.Components.Byond
const string ActiveVersionFileName = "ActiveVersion.txt";
///
- public Version ActiveVersion { get; private set; }
+ public ByondVersion ActiveVersion { get; private set; }
///
- public IReadOnlyList InstalledVersions
+ public IReadOnlyList InstalledVersions
{
get
{
@@ -87,7 +88,7 @@ namespace Tgstation.Server.Host.Components.Byond
///
/// Map of byond s to s that complete when they are installed.
///
- readonly Dictionary> installedVersions;
+ readonly Dictionary> installedVersions;
///
/// The for changing or deleting the active BYOND version.
@@ -103,11 +104,14 @@ namespace Tgstation.Server.Host.Components.Byond
/// Validates a given parameter.
///
/// The to validate.
- static void CheckVersionParameter(Version version)
+ static void CheckVersionParameter(ByondVersion version)
{
ArgumentNullException.ThrowIfNull(version);
- if (version.Build == 0)
+ if (!version.Engine.HasValue)
+ throw new InvalidOperationException("version.Engine cannot be null!");
+
+ if (version.Version.Build == 0)
throw new InvalidOperationException("version.Build cannot be 0!");
}
@@ -125,7 +129,7 @@ namespace Tgstation.Server.Host.Components.Byond
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
- installedVersions = new Dictionary>();
+ installedVersions = new Dictionary>();
changeDeleteSemaphore = new SemaphoreSlim(1);
activeVersionChanged = new TaskCompletionSource();
}
@@ -136,7 +140,7 @@ namespace Tgstation.Server.Host.Components.Byond
///
public async ValueTask ChangeVersion(
JobProgressReporter progressReporter,
- Version version,
+ ByondVersion version,
Stream customVersionStream,
bool allowInstallation,
CancellationToken cancellationToken)
@@ -154,7 +158,10 @@ namespace Tgstation.Server.Host.Components.Byond
cancellationToken);
// We reparse the version because it could be changed after a custom install.
- version = installLock.Version;
+ version = new ByondVersion(version)
+ {
+ Version = installLock.Version.Version,
+ };
var stringVersion = version.ToString();
await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(stringVersion), cancellationToken);
@@ -177,7 +184,7 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public async ValueTask UseExecutables(Version requiredVersion, string trustDmbFullPath, CancellationToken cancellationToken)
+ public async ValueTask UseExecutables(ByondVersion requiredVersion, string trustDmbFullPath, CancellationToken cancellationToken)
{
logger.LogTrace(
"Acquiring lock on BYOND version {version}...",
@@ -205,7 +212,7 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public async ValueTask DeleteVersion(JobProgressReporter progressReporter, Version version, CancellationToken cancellationToken)
+ public async ValueTask DeleteVersion(JobProgressReporter progressReporter, ByondVersion version, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(progressReporter);
@@ -213,15 +220,18 @@ namespace Tgstation.Server.Host.Components.Byond
logger.LogTrace("DeleteVersion {version}", version);
- if (version == ActiveVersion)
+ if (version.Equals(ActiveVersion))
throw new JobException(ErrorCode.ByondCannotDeleteActiveVersion);
- ReferenceCountingContainer container;
+ ReferenceCountingContainer container;
lock (installedVersions)
if (!installedVersions.TryGetValue(version, out container))
- return; // already "deleted"
+ {
+ logger.LogTrace("Version {version} already deleted.", version);
+ return;
+ }
- logger.LogInformation("Deleting BYOND version {version}...", version);
+ logger.LogInformation("Deleting version {version}...", version);
progressReporter.StageName = "Waiting for version to not be in use...";
while (true)
{
@@ -238,7 +248,7 @@ namespace Tgstation.Server.Host.Components.Byond
.WaitAsync(cancellationToken);
if (containerTask.IsCompleted)
- logger.LogTrace("All BYOND locks for {version} are gone", version);
+ logger.LogTrace("All locks for version {version} are gone", version);
using (await SemaphoreSlimContext.Lock(changeDeleteSemaphore, cancellationToken))
{
@@ -252,7 +262,7 @@ namespace Tgstation.Server.Host.Components.Byond
proceed = container.OnZeroReferences.IsCompleted;
if (proceed)
if (!installedVersions.TryGetValue(version, out var newerContainer))
- logger.LogWarning("Unable to remove BYOND installation {version} from list! Is there a duplicate job running?", version);
+ logger.LogWarning("Unable to remove engine installation {version} from list! Is there a duplicate job running?", version);
else
{
if (container != newerContainer)
@@ -291,6 +301,13 @@ namespace Tgstation.Server.Host.Components.Byond
}
}
+ ///
+ public async ValueTask EnsureEngineSource(Uri source, EngineType engine, CancellationToken cancellationToken)
+ {
+ await Task.Yield();
+ throw new NotImplementedException();
+ }
+
///
public async Task StartAsync(CancellationToken cancellationToken)
{
@@ -302,7 +319,7 @@ namespace Tgstation.Server.Host.Components.Byond
var activeVersionBytesTask = GetActiveVersion();
- var byondDir = byondInstaller.PathToUserByondFolder;
+ var byondDir = byondInstaller.PathToUserFolder;
if (byondDir != null)
using (await SemaphoreSlimContext.Lock(UserFilesSemaphore, cancellationToken))
{
@@ -328,7 +345,7 @@ namespace Tgstation.Server.Host.Components.Byond
await ioManager.CreateDirectory(DefaultIOManager.CurrentDirectory, cancellationToken);
var directories = await ioManager.GetDirectories(DefaultIOManager.CurrentDirectory, cancellationToken);
- var installedVersionPaths = new Dictionary();
+ var installedVersionPaths = new Dictionary();
async ValueTask ReadVersion(string path)
{
@@ -342,7 +359,7 @@ namespace Tgstation.Server.Host.Components.Byond
var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken);
var text = Encoding.UTF8.GetString(bytes);
- if (!Version.TryParse(text, out var version))
+ if (!ByondVersion.TryParse(text, out var version))
{
logger.LogWarning("Cleaning path with unparsable version file: {versionPath}", ioManager.ResolvePath(path));
await ioManager.DeleteDirectory(path, cancellationToken); // cleanup
@@ -383,10 +400,10 @@ namespace Tgstation.Server.Host.Components.Byond
{
var activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
- Version activeVersion;
+ ByondVersion activeVersion;
bool hasRequestedActiveVersion;
lock (installedVersions)
- hasRequestedActiveVersion = Version.TryParse(activeVersionString, out activeVersion)
+ hasRequestedActiveVersion = ByondVersion.TryParse(activeVersionString, out activeVersion)
&& installedVersions.ContainsKey(activeVersion);
if (hasRequestedActiveVersion)
@@ -403,46 +420,47 @@ namespace Tgstation.Server.Host.Components.Byond
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
///
- /// Ensures a BYOND is installed if it isn't already.
+ /// Ensures a BYOND is installed if it isn't already.
///
/// The optional for the operation.
- /// The BYOND to install.
+ /// The to install.
/// Custom zip file to use. Will cause a number to be added.
/// If this BYOND version is required as part of a locking operation.
- /// If an installation should be performed if the is not installed. If and an installation is required an will be thrown.
+ /// If an installation should be performed if the is not installed. If and an installation is required an will be thrown.
/// The for the operation.
- /// A resulting in the .
- async ValueTask AssertAndLockVersion(
+ /// A resulting in the .
+ async ValueTask AssertAndLockVersion(
JobProgressReporter progressReporter,
- Version version,
+ ByondVersion byondVersion,
Stream customVersionStream,
bool neededForLock,
bool allowInstallation,
CancellationToken cancellationToken)
{
var ourTcs = new TaskCompletionSource();
- ByondInstallation installation;
- ByondExecutableLock installLock;
+ IEngineInstallation installation;
+ EngineExecutableLock installLock;
bool installedOrInstalling;
+ var byondEngine = byondVersion.Engine.Value == EngineType.Byond;
lock (installedVersions)
{
- if (customVersionStream != null)
+ if (customVersionStream != null && byondEngine)
{
var customInstallationNumber = 1;
do
{
- version = new Version(version.Major, version.Minor, customInstallationNumber++);
+ byondVersion.Version = new Version(byondVersion.Version.Major, byondVersion.Version.Minor, customInstallationNumber++);
}
- while (installedVersions.ContainsKey(version));
+ while (installedVersions.ContainsKey(byondVersion));
}
- installedOrInstalling = installedVersions.TryGetValue(version, out var installationContainer);
+ installedOrInstalling = installedVersions.TryGetValue(byondVersion, out var installationContainer);
if (!installedOrInstalling)
{
if (!allowInstallation)
- throw new InvalidOperationException($"BYOND version {version} not installed!");
+ throw new InvalidOperationException($"BYOND version {byondVersion} not installed!");
- installationContainer = AddInstallationContainer(version, ourTcs.Task);
+ installationContainer = AddInstallationContainer(byondVersion, ourTcs.Task);
}
installation = installationContainer.Instance;
@@ -457,7 +475,7 @@ namespace Tgstation.Server.Host.Components.Byond
progressReporter.StageName = "Waiting for existing installation job...";
if (neededForLock && !installation.InstallationTask.IsCompleted)
- logger.LogWarning("The required BYOND version ({version}) is not readily available! We will have to wait for it to install.", version);
+ logger.LogWarning("The required BYOND version ({version}) is not readily available! We will have to wait for it to install.", byondVersion);
await installation.InstallationTask.WaitAsync(cancellationToken);
return installLock;
@@ -467,24 +485,24 @@ namespace Tgstation.Server.Host.Components.Byond
try
{
if (customVersionStream != null)
- logger.LogInformation("Installing custom BYOND version as {version}...", version);
+ logger.LogInformation("Installing custom BYOND version as {version}...", byondVersion);
else if (neededForLock)
{
- if (version.Build > 0)
+ if (byondEngine && byondVersion.Version.Build > 0)
throw new JobException(ErrorCode.ByondNonExistentCustomVersion);
- logger.LogWarning("The required BYOND version ({version}) is not readily available! We will have to install it.", version);
+ logger.LogWarning("The required BYOND version ({version}) is not readily available! We will have to install it.", byondVersion);
}
else
- logger.LogDebug("Requested BYOND version {version} not currently installed. Doing so now...", version);
+ logger.LogDebug("Requested BYOND version {version} not currently installed. Doing so now...", byondVersion);
if (progressReporter != null)
progressReporter.StageName = "Running event";
- var versionString = version.ToString();
+ var versionString = byondVersion.ToString();
await eventConsumer.HandleEvent(EventType.ByondInstallStart, new List { versionString }, false, cancellationToken);
- await InstallVersionFiles(progressReporter, version, customVersionStream, cancellationToken);
+ await InstallVersionFiles(progressReporter, byondVersion, customVersionStream, cancellationToken);
ourTcs.SetResult();
}
@@ -494,7 +512,7 @@ namespace Tgstation.Server.Host.Components.Byond
await eventConsumer.HandleEvent(EventType.ByondInstallFail, new List { ex.Message }, false, cancellationToken);
lock (installedVersions)
- installedVersions.Remove(version);
+ installedVersions.Remove(byondVersion);
ourTcs.SetException(ex);
throw;
@@ -513,11 +531,11 @@ namespace Tgstation.Server.Host.Components.Byond
/// Installs the files for a given BYOND .
///
/// The optional for the operation.
- /// The BYOND being installed with the number set if appropriate.
+ /// The being installed with the number set if appropriate.
/// Custom zip file to use. Will cause a number to be added.
/// The for the operation.
/// A representing the running operation.
- async ValueTask InstallVersionFiles(JobProgressReporter progressReporter, Version version, Stream customVersionStream, CancellationToken cancellationToken)
+ async ValueTask InstallVersionFiles(JobProgressReporter progressReporter, ByondVersion version, Stream customVersionStream, CancellationToken cancellationToken)
{
var installFullPath = ioManager.ResolvePath(version.ToString());
async ValueTask DirectoryCleanup()
@@ -585,32 +603,46 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- /// Create and add a new to .
+ /// Create and add a new to .
///
/// The being added.
/// The representing the installation process.
- /// The new containing the new .
- ReferenceCountingContainer AddInstallationContainer(Version version, Task installationTask)
+ /// The new containing the new .
+ ReferenceCountingContainer AddInstallationContainer(ByondVersion version, Task installationTask)
{
var binPathForVersion = ioManager.ConcatPath(version.ToString(), BinPath);
- var installation = new ByondInstallation(
- installationTask,
- version,
- ioManager.ResolvePath(
- ioManager.ConcatPath(
- binPathForVersion,
- byondInstaller.GetDreamDaemonName(
- version,
- out var supportsCli,
- out var supportsMapThreads))),
- ioManager.ResolvePath(
- ioManager.ConcatPath(
- binPathForVersion,
- byondInstaller.DreamMakerName)),
- supportsCli,
- supportsMapThreads);
+ IEngineInstallation installation;
- var installationContainer = new ReferenceCountingContainer(installation);
+ switch (version.Engine.Value)
+ {
+ case EngineType.Byond:
+ installation = new ByondInstallation(
+ installationTask,
+ version,
+ ioManager.ResolvePath(
+ ioManager.ConcatPath(
+ binPathForVersion,
+ byondInstaller.GetDreamDaemonName(
+ version,
+ out var supportsCli,
+ out var supportsMapThreads))),
+ ioManager.ResolvePath(
+ ioManager.ConcatPath(
+ binPathForVersion,
+ byondInstaller.CompilerName)),
+ supportsCli,
+ supportsMapThreads);
+ break;
+ case EngineType.OpenDream:
+ installation = new OpenDreamInstallation(
+ installationTask,
+ version);
+ break;
+ default:
+ throw new InvalidOperationException($"Invalid EngineType: {version.Engine.Value}");
+ }
+
+ var installationContainer = new ReferenceCountingContainer(installation);
lock (installedVersions)
installedVersions.Add(version, installationContainer);
@@ -626,7 +658,7 @@ namespace Tgstation.Server.Host.Components.Byond
/// A representing the running operation.
async ValueTask TrustDmbPath(string fullDmbPath, CancellationToken cancellationToken)
{
- var byondDir = byondInstaller.PathToUserByondFolder;
+ var byondDir = byondInstaller.PathToUserFolder;
if (String.IsNullOrWhiteSpace(byondDir))
{
logger.LogTrace("No relevant user BYOND directory to install a \"{fileName}\" in", TrustedDmbFileName);
diff --git a/src/Tgstation.Server.Host/Components/Byond/EngineExecutableLock.cs b/src/Tgstation.Server.Host/Components/Byond/EngineExecutableLock.cs
new file mode 100644
index 0000000000..9c3d2ebdfc
--- /dev/null
+++ b/src/Tgstation.Server.Host/Components/Byond/EngineExecutableLock.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+using Tgstation.Server.Api.Models.Internal;
+using Tgstation.Server.Host.Components.Deployment;
+using Tgstation.Server.Host.Utils;
+
+namespace Tgstation.Server.Host.Components.Byond
+{
+ ///
+ sealed class EngineExecutableLock : ReferenceCounter, IEngineExecutableLock
+ {
+ ///
+ public ByondVersion Version => Instance.Version;
+
+ ///
+ public string ServerExePath => Instance.ServerExePath;
+
+ ///
+ public string CompilerExePath => Instance.CompilerExePath;
+
+ ///
+ public bool HasStandardOutput => Instance.HasStandardOutput;
+
+ ///
+ public bool PromptsForNetworkAccess => Instance.PromptsForNetworkAccess;
+
+ ///
+ public Task InstallationTask => Instance.InstallationTask;
+
+ ///
+ public void DoNotDeleteThisSession() => DangerousDropReference();
+
+ ///
+ public string FormatServerArguments(
+ IDmbProvider dmbProvider,
+ IReadOnlyDictionary parameters,
+ DreamDaemonLaunchParameters launchParameters,
+ string logFilePath)
+ => Instance.FormatServerArguments(
+ dmbProvider,
+ parameters,
+ launchParameters,
+ logFilePath);
+
+ ///
+ public string FormatCompilerArguments(string dmePath) => Instance.FormatCompilerArguments(dmePath);
+ }
+}
diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondInstallation.cs b/src/Tgstation.Server.Host/Components/Byond/IByondInstallation.cs
deleted file mode 100644
index 52a4e694b7..0000000000
--- a/src/Tgstation.Server.Host/Components/Byond/IByondInstallation.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-
-namespace Tgstation.Server.Host.Components.Byond
-{
- ///
- /// Represents a BYOND installation.
- ///
- public interface IByondInstallation
- {
- ///
- /// The of the .
- ///
- Version Version { get; }
-
- ///
- /// The full path to the DreamDaemon executable.
- ///
- string DreamDaemonPath { get; }
-
- ///
- /// The full path to the dm/DreamMaker executable.
- ///
- string DreamMakerPath { get; }
-
- ///
- /// If supports being run as a command-line application.
- ///
- bool SupportsCli { get; }
-
- ///
- /// If supports the -map-threads parameter.
- ///
- bool SupportsMapThreads { get; }
- }
-}
diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs
index 9c35337830..b1a89bd48c 100644
--- a/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs
@@ -1,8 +1,9 @@
-using System;
-using System.IO;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using Tgstation.Server.Api.Models.Internal;
+
namespace Tgstation.Server.Host.Components.Byond
{
///
@@ -11,52 +12,52 @@ namespace Tgstation.Server.Host.Components.Byond
interface IByondInstaller
{
///
- /// Get the file name of the DreamMaker executable.
+ /// Get the file name of the compiler executable.
///
- string DreamMakerName { get; }
+ string CompilerName { get; }
///
- /// The path to the BYOND folder for the user.
+ /// The path to the folder for the user's data.
///
- string PathToUserByondFolder { get; }
+ string PathToUserFolder { get; }
///
/// Get the file name of the DreamDaemon executable.
///
- /// The of BYOND to select the executable name for.
+ /// The of BYOND to select the executable name for.
/// Whether or not the returned path supports being run as a command-line application.
/// Whether or not the returned path supports the '-map-threads' parameter.
/// The file name of the DreamDaemon executable.
- string GetDreamDaemonName(Version version, out bool supportsCli, out bool supportsMapThreads);
+ string GetDreamDaemonName(ByondVersion version, out bool supportsCli, out bool supportsMapThreads);
///
/// Download a given BYOND .
///
- /// The of BYOND to download.
+ /// The of BYOND to download.
/// The for the operation.
/// A resulting in a of the zipfile.
- ValueTask DownloadVersion(Version version, CancellationToken cancellationToken);
+ ValueTask DownloadVersion(ByondVersion version, CancellationToken cancellationToken);
///
/// Does actions necessary to get an extracted BYOND installation working.
///
- /// The of BYOND being installed.
+ /// The being installed.
/// The path to the BYOND installation.
/// The for the operation.
/// A representing the running operation.
- ValueTask InstallByond(Version version, string path, CancellationToken cancellationToken);
+ ValueTask InstallByond(ByondVersion version, string path, CancellationToken cancellationToken);
///
/// Does actions necessary to get upgrade a BYOND version installed by a previous version of TGS.
///
- /// The of BYOND being installed.
+ /// The being installed.
/// The path to the BYOND installation.
/// The for the operation.
/// A representing the running operation.
- ValueTask UpgradeInstallation(Version version, string path, CancellationToken cancellationToken);
+ ValueTask UpgradeInstallation(ByondVersion version, string path, CancellationToken cancellationToken);
///
- /// Attempts to cleans the BYOND cache folder for the system.
+ /// Attempts to cleans the engine's cache folder for the system.
///
/// The for the operation.
/// A representing the running operation.
diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondManager.cs b/src/Tgstation.Server.Host/Components/Byond/IByondManager.cs
index 092034b1c0..1da8c041d1 100644
--- a/src/Tgstation.Server.Host/Components/Byond/IByondManager.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/IByondManager.cs
@@ -4,6 +4,8 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Jobs;
namespace Tgstation.Server.Host.Components.Byond
@@ -11,48 +13,62 @@ namespace Tgstation.Server.Host.Components.Byond
///
/// For managing the BYOND installation.
///
- /// When passing in s, ensure they are BYOND format versions unless referring to a custom version. This means should NEVER be 0.
+ /// When passing in s for , ensure they are BYOND format versions unless referring to a custom version. This means should NEVER be 0.
public interface IByondManager : IComponentService, IDisposable
{
///
- /// The currently active BYOND version.
+ /// The currently active .
///
- Version ActiveVersion { get; }
+ ByondVersion ActiveVersion { get; }
///
- /// The installed BYOND versions.
+ /// The installed s.
///
- IReadOnlyList InstalledVersions { get; }
+ IReadOnlyList InstalledVersions { get; }
///
- /// Change the active BYOND version.
+ /// Ensure that the given is registered for the given .
+ ///
+ /// The source of the .
+ /// The .
+ /// The for the operation.
+ /// A representing the running operation.
+ ValueTask EnsureEngineSource(Uri source, EngineType engine, CancellationToken cancellationToken);
+
+ ///
+ /// Change the active .
///
/// The optional for the operation.
- /// The new .
+ /// The new .
/// Optional of a custom BYOND version zip file.
/// If an installation should be performed if the is not installed. If and an installation is required an will be thrown.
/// The for the operation.
/// A representing the running operation.
- ValueTask ChangeVersion(JobProgressReporter progressReporter, Version version, Stream customVersionStream, bool allowInstallation, CancellationToken cancellationToken);
+ ValueTask ChangeVersion(
+ JobProgressReporter progressReporter,
+ ByondVersion version,
+ Stream customVersionStream,
+ bool allowInstallation,
+ CancellationToken cancellationToken);
///
- /// Deletes a given BYOND version from the disk.
+ /// Deletes a given from the disk.
///
/// The for the operation.
- /// The to delete.
+ /// The to delete.
/// The for the operation.
- /// A representing the running operation.
- ValueTask DeleteVersion(JobProgressReporter progressReporter, Version version, CancellationToken cancellationToken);
+ /// A representing the running operation.
+ ValueTask DeleteVersion(JobProgressReporter progressReporter, ByondVersion version, CancellationToken cancellationToken);
///
- /// Lock the current installation's location and return a .
+ /// Lock the current installation's location and return a .
///
- /// The BYOND required.
+ /// The required.
/// The optional full path to .dmb to trust while using the executables.
/// The for the operation.
- /// A resulting in the requested .
- ValueTask UseExecutables(
- Version requiredVersion,
+ /// A resulting in the requested .
+ ValueTask UseExecutables(
+ ByondVersion requiredVersion,
string trustDmbFullPath,
CancellationToken cancellationToken);
}
diff --git a/src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs b/src/Tgstation.Server.Host/Components/Byond/IEngineExecutableLock.cs
similarity index 80%
rename from src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs
rename to src/Tgstation.Server.Host/Components/Byond/IEngineExecutableLock.cs
index a320109dce..ae3ad5d438 100644
--- a/src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/IEngineExecutableLock.cs
@@ -5,7 +5,7 @@ namespace Tgstation.Server.Host.Components.Byond
///
/// Represents usage of the two primary BYOND server executables.
///
- public interface IByondExecutableLock : IByondInstallation, IDisposable
+ public interface IEngineExecutableLock : IEngineInstallation, IDisposable
{
///
/// Call if, during a detach, this version should not be deleted.
diff --git a/src/Tgstation.Server.Host/Components/Byond/IEngineInstallation.cs b/src/Tgstation.Server.Host/Components/Byond/IEngineInstallation.cs
new file mode 100644
index 0000000000..39c29b547a
--- /dev/null
+++ b/src/Tgstation.Server.Host/Components/Byond/IEngineInstallation.cs
@@ -0,0 +1,65 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+using Tgstation.Server.Api.Models.Internal;
+using Tgstation.Server.Host.Components.Deployment;
+
+namespace Tgstation.Server.Host.Components.Byond
+{
+ ///
+ /// Represents a BYOND installation.
+ ///
+ public interface IEngineInstallation
+ {
+ ///
+ /// The of the .
+ ///
+ ByondVersion Version { get; }
+
+ ///
+ /// The full path to the game server executable.
+ ///
+ string ServerExePath { get; }
+
+ ///
+ /// The full path to the dm/DreamMaker executable.
+ ///
+ string CompilerExePath { get; }
+
+ ///
+ /// If supports being run as a command-line application and outputs log information to be captured.
+ ///
+ bool HasStandardOutput { get; }
+
+ ///
+ /// If may create network prompts.
+ ///
+ bool PromptsForNetworkAccess { get; }
+
+ ///
+ /// The that completes when the BYOND version finished installing.
+ ///
+ Task InstallationTask { get; }
+
+ ///
+ /// Return the command line arguments for launching with given .
+ ///
+ /// The .
+ /// The map of parameter s as a . Should NOT include the of .
+ /// The .
+ /// The path to the log file, if any.
+ /// The formatted arguments .
+ string FormatServerArguments(
+ IDmbProvider dmbProvider,
+ IReadOnlyDictionary parameters,
+ DreamDaemonLaunchParameters launchParameters,
+ string logFilePath);
+
+ ///
+ /// Return the command line arguments for compiling a given if compilation is necessary.
+ ///
+ /// The full path to the .dme to compile.
+ /// An arguments if compilation is required, otherwise.
+ string FormatCompilerArguments(string dmePath);
+ }
+}
diff --git a/src/Tgstation.Server.Host/Components/Byond/OpenDreamInstallation.cs b/src/Tgstation.Server.Host/Components/Byond/OpenDreamInstallation.cs
new file mode 100644
index 0000000000..a7df3ddc28
--- /dev/null
+++ b/src/Tgstation.Server.Host/Components/Byond/OpenDreamInstallation.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
+using Tgstation.Server.Host.Components.Deployment;
+
+namespace Tgstation.Server.Host.Components.Byond
+{
+ ///
+ /// Implementation of for .
+ ///
+ sealed class OpenDreamInstallation : IEngineInstallation
+ {
+ ///
+ public ByondVersion Version { get; }
+
+ ///
+ public string ServerExePath { get; }
+
+ ///
+ public string CompilerExePath { get; }
+
+ ///
+ public bool PromptsForNetworkAccess => false;
+
+ ///
+ public bool HasStandardOutput => true;
+
+ ///
+ public Task InstallationTask { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of .
+ /// The value of .
+ public OpenDreamInstallation(
+ Task installationTask,
+ ByondVersion version)
+ {
+ InstallationTask = installationTask ?? throw new ArgumentNullException(nameof(installationTask));
+ ArgumentNullException.ThrowIfNull(version);
+
+ if (version.Engine.Value != EngineType.OpenDream)
+ throw new ArgumentException($"Invalid EngineType: {version.Engine.Value}", nameof(version));
+
+ Version = version ?? throw new ArgumentNullException(nameof(version));
+
+ throw new NotImplementedException();
+ }
+
+ ///
+ public string FormatServerArguments(IDmbProvider dmbProvider, IReadOnlyDictionary parameters, DreamDaemonLaunchParameters launchParameters, string logFilePath)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ public string FormatCompilerArguments(string dmePath)
+ {
+ ArgumentNullException.ThrowIfNull(dmePath);
+ return null;
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs
index 3657e015d4..7fed2498ec 100644
--- a/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Host.IO;
@@ -32,10 +33,10 @@ namespace Tgstation.Server.Host.Components.Byond
const string ShellScriptExtension = ".sh";
///
- public override string DreamMakerName => DreamMakerExecutableName + ShellScriptExtension;
+ public override string CompilerName => DreamMakerExecutableName + ShellScriptExtension;
///
- public override string PathToUserByondFolder { get; }
+ public override string PathToUserFolder { get; }
///
protected override string ByondRevisionsUrlTemplate => "https://www.byond.com/download/build/{0}/{0}.{1}_byond_linux.zip";
@@ -61,7 +62,7 @@ namespace Tgstation.Server.Host.Components.Byond
{
this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
- PathToUserByondFolder = IOManager.ResolvePath(
+ PathToUserFolder = IOManager.ResolvePath(
IOManager.ConcatPath(
Environment.GetFolderPath(
Environment.SpecialFolder.UserProfile),
@@ -69,17 +70,17 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public override string GetDreamDaemonName(Version version, out bool supportsCli, out bool supportsMapThreads)
+ public override string GetDreamDaemonName(ByondVersion version, out bool supportsCli, out bool supportsMapThreads)
{
ArgumentNullException.ThrowIfNull(version);
supportsCli = true;
- supportsMapThreads = version >= MapThreadsVersion;
+ supportsMapThreads = version.Version >= MapThreadsVersion;
return DreamDaemonExecutableName + ShellScriptExtension;
}
///
- public override ValueTask InstallByond(Version version, string path, CancellationToken cancellationToken)
+ public override ValueTask InstallByond(ByondVersion version, string path, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(version);
ArgumentNullException.ThrowIfNull(path);
@@ -105,7 +106,7 @@ namespace Tgstation.Server.Host.Components.Byond
dreamDaemonScript);
var dmTask = WriteAndMakeExecutable(
- IOManager.ConcatPath(basePath, DreamMakerName),
+ IOManager.ConcatPath(basePath, CompilerName),
dreamMakerScript);
var task = ValueTaskExtensions.WhenAll(
@@ -119,7 +120,7 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public override ValueTask UpgradeInstallation(Version version, string path, CancellationToken cancellationToken)
+ public override ValueTask UpgradeInstallation(ByondVersion version, string path, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(version);
ArgumentNullException.ThrowIfNull(path);
diff --git a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
index 8080abc12f..0b177584a4 100644
--- a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.IO;
@@ -53,10 +54,10 @@ namespace Tgstation.Server.Host.Components.Byond
public static Version DDExeVersion => new (515, 1598);
///
- public override string DreamMakerName => "dm.exe";
+ public override string CompilerName => "dm.exe";
///
- public override string PathToUserByondFolder { get; }
+ public override string PathToUserFolder { get; }
///
protected override string ByondRevisionsUrlTemplate => "https://www.byond.com/download/build/{0}/{0}.{1}_byond.zip";
@@ -102,9 +103,9 @@ namespace Tgstation.Server.Host.Components.Byond
var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
if (String.IsNullOrWhiteSpace(documentsDirectory))
- PathToUserByondFolder = null; // happens with the service account
+ PathToUserFolder = null; // happens with the service account
else
- PathToUserByondFolder = IOManager.ResolvePath(IOManager.ConcatPath(documentsDirectory, "BYOND"));
+ PathToUserFolder = IOManager.ResolvePath(IOManager.ConcatPath(documentsDirectory, "BYOND"));
semaphore = new SemaphoreSlim(1);
installedDirectX = false;
@@ -114,17 +115,17 @@ namespace Tgstation.Server.Host.Components.Byond
public void Dispose() => semaphore.Dispose();
///
- public override string GetDreamDaemonName(Version version, out bool supportsCli, out bool supportsMapThreads)
+ public override string GetDreamDaemonName(ByondVersion version, out bool supportsCli, out bool supportsMapThreads)
{
ArgumentNullException.ThrowIfNull(version);
- supportsCli = version >= DDExeVersion;
- supportsMapThreads = version >= MapThreadsVersion;
+ supportsCli = version.Version >= DDExeVersion;
+ supportsMapThreads = version.Version >= MapThreadsVersion;
return supportsCli ? "dd.exe" : "dreamdaemon.exe";
}
///
- public override ValueTask InstallByond(Version version, string path, CancellationToken cancellationToken)
+ public override ValueTask InstallByond(ByondVersion version, string path, CancellationToken cancellationToken)
{
var tasks = new List(3)
{
@@ -139,7 +140,7 @@ namespace Tgstation.Server.Host.Components.Byond
}
///
- public override async ValueTask UpgradeInstallation(Version version, string path, CancellationToken cancellationToken)
+ public override async ValueTask UpgradeInstallation(ByondVersion version, string path, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(version);
ArgumentNullException.ThrowIfNull(path);
@@ -147,7 +148,7 @@ namespace Tgstation.Server.Host.Components.Byond
if (generalConfiguration.SkipAddingByondFirewallException)
return;
- if (version < DDExeVersion)
+ if (version.Version < DDExeVersion)
return;
if (await IOManager.FileExists(IOManager.ConcatPath(path, TgsFirewalledDDFile), cancellationToken))
@@ -227,7 +228,7 @@ namespace Tgstation.Server.Host.Components.Byond
/// The path to the BYOND installation.
/// The for the operation.
/// A representing the running operation.
- async ValueTask AddDreamDaemonToFirewall(Version version, string path, CancellationToken cancellationToken)
+ async ValueTask AddDreamDaemonToFirewall(ByondVersion version, string path, CancellationToken cancellationToken)
{
var dreamDaemonName = GetDreamDaemonName(version, out var usesDDExe, out var _);
diff --git a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs
index ecb0fa6498..6bc1ddc015 100644
--- a/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/ChatManager.cs
@@ -359,7 +359,7 @@ namespace Tgstation.Server.Host.Components.Chat
///
public Func> QueueDeploymentMessage(
Models.RevisionInformation revisionInformation,
- Version byondVersion,
+ ByondVersion byondVersion,
DateTimeOffset? estimatedCompletionTime,
string gitHubOwner,
string gitHubRepo,
diff --git a/src/Tgstation.Server.Host/Components/Chat/Commands/ByondCommand.cs b/src/Tgstation.Server.Host/Components/Chat/Commands/ByondCommand.cs
index f0c87ef4df..8f7b680293 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Commands/ByondCommand.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Commands/ByondCommand.cs
@@ -1,5 +1,4 @@
using System;
-using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -49,20 +48,45 @@ namespace Tgstation.Server.Host.Components.Chat.Commands
///
public ValueTask Invoke(string arguments, ChatUser user, CancellationToken cancellationToken)
{
- if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--ACTIVE"))
- return ValueTask.FromResult(new MessageContent
- {
- Text = byondManager.ActiveVersion == null ? "None!" : String.Format(CultureInfo.InvariantCulture, "{0}.{1}", byondManager.ActiveVersion.Major, byondManager.ActiveVersion.Minor),
- });
- if (watchdog.Status == WatchdogStatus.Offline)
- return ValueTask.FromResult(new MessageContent
- {
- Text = "Server offline!",
- });
- return ValueTask.FromResult(new MessageContent
+ if (arguments.Split(' ').Any(x => x.Equals("--active", StringComparison.OrdinalIgnoreCase)))
{
- Text = watchdog.ActiveCompileJob?.ByondVersion ?? "None!",
- });
+ string text;
+ if (byondManager.ActiveVersion == null)
+ text = "None!";
+ else
+ switch (byondManager.ActiveVersion.Engine.Value)
+ {
+ case EngineType.OpenDream:
+ text = $"OpenDream: {byondManager.ActiveVersion.SourceCommittish}";
+ break;
+ case EngineType.Byond:
+ text = $"BYOND {byondManager.ActiveVersion.Version.Major}.{byondManager.ActiveVersion.Version.Minor}";
+ if (byondManager.ActiveVersion.Version.Build != -1)
+ text += " (Custom Build)";
+
+ break;
+ default:
+ throw new InvalidOperationException($"Invalid EngineType: {byondManager.ActiveVersion.Engine.Value}");
+ }
+
+ return ValueTask.FromResult(
+ new MessageContent
+ {
+ Text = text,
+ });
+ }
+
+ if (watchdog.Status == WatchdogStatus.Offline)
+ return ValueTask.FromResult(
+ new MessageContent
+ {
+ Text = "Server offline!",
+ });
+ return ValueTask.FromResult(
+ new MessageContent
+ {
+ Text = watchdog.ActiveCompileJob?.ByondVersion ?? "None!",
+ });
}
}
}
diff --git a/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs b/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs
index 769ab7b251..3f21930cf5 100644
--- a/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/IChatManager.cs
@@ -61,7 +61,7 @@ namespace Tgstation.Server.Host.Components.Chat
/// Send the message for a deployment to configured deployment channels.
///
/// The of the deployment.
- /// The BYOND of the deployment.
+ /// The of the deployment.
/// The optional the deployment is expected to be completed at.
/// The repository GitHub owner, if any.
/// The repository GitHub name, if any.
@@ -69,7 +69,7 @@ namespace Tgstation.Server.Host.Components.Chat
/// A to call to update the message at the deployment's conclusion. Parameters: Error message if any, DreamMaker output if any. Returns an to call to mark the deployment as active/inactive. Parameter: If the deployment is being activated or inactivated.
Func> QueueDeploymentMessage(
Models.RevisionInformation revisionInformation,
- Version byondVersion,
+ ByondVersion byondVersion,
DateTimeOffset? estimatedCompletionTime,
string gitHubOwner,
string gitHubRepo,
diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
index bba9673ecf..492eb8e332 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
@@ -22,6 +22,7 @@ using Remora.Rest.Results;
using Remora.Results;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Common.Extensions;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Extensions;
@@ -129,25 +130,35 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// Create a of s for a discord update embed.
///
/// The of the deployment.
- /// The BYOND of the deployment.
+ /// The of the deployment.
/// The repository GitHub owner, if any.
/// The repository GitHub name, if any.
/// if the local deployment commit was pushed to the remote repository.
/// A new of s to use.
static List BuildUpdateEmbedFields(
Models.RevisionInformation revisionInformation,
- Version byondVersion,
+ ByondVersion byondVersion,
string gitHubOwner,
string gitHubRepo,
bool localCommitPushed)
{
bool gitHub = gitHubOwner != null && gitHubRepo != null;
+ var engineField = byondVersion.Engine.Value switch
+ {
+ EngineType.Byond => new EmbedField(
+ "BYOND Version",
+ $"{byondVersion.Version.Major}.{byondVersion.Version.Minor}{(byondVersion.Version.Build > 0 ? $".{byondVersion.Version.Build}" : String.Empty)}",
+ true),
+ EngineType.OpenDream => new EmbedField(
+ "OpenDream Version",
+ $"[{byondVersion.SourceCommittish[..7]}](https://github.com/OpenDreamProject/OpenDream/commit/{revisionInformation.CommitSha})",
+ true),
+ _ => throw new InvalidOperationException($"Invaild EngineType: {byondVersion.Engine.Value}"),
+ };
+
var fields = new List
{
- new EmbedField(
- "BYOND Version",
- $"{byondVersion.Major}.{byondVersion.Minor}{(byondVersion.Build > 0 ? $".{byondVersion.Build}" : String.Empty)}",
- true),
+ engineField,
new EmbedField(
"Local Commit",
localCommitPushed && gitHub
@@ -323,7 +334,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
///
public override async ValueTask>>> SendUpdateMessage(
Models.RevisionInformation revisionInformation,
- Version byondVersion,
+ ByondVersion byondVersion,
DateTimeOffset? estimatedCompletionTime,
string gitHubOwner,
string gitHubRepo,
diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs
index 641372c318..489d8f4288 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Models;
@@ -83,7 +84,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// Send the message for a deployment.
///
/// The of the deployment.
- /// The BYOND of the deployment.
+ /// The of the deployment.
/// The optional the deployment is expected to be completed at.
/// The repository GitHub owner, if any.
/// The repository GitHub name, if any.
@@ -92,8 +93,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
/// The for the operation.
/// A resulting in a to call to update the message at the deployment's conclusion. Parameters: Error message if any, DreamMaker output if any. Returns another callback which should be called to mark the deployment as active.
ValueTask>>> SendUpdateMessage(
- RevisionInformation revisionInformation,
- Version byondVersion,
+ Models.RevisionInformation revisionInformation,
+ ByondVersion byondVersion,
DateTimeOffset? estimatedCompletionTime,
string gitHubOwner,
string gitHubRepo,
diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs
index 605bad64b4..7cf73595c5 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs
@@ -12,6 +12,7 @@ using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Extensions;
using Tgstation.Server.Host.IO;
@@ -220,7 +221,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
///
public override async ValueTask>>> SendUpdateMessage(
Models.RevisionInformation revisionInformation,
- Version byondVersion,
+ ByondVersion byondVersion,
DateTimeOffset? estimatedCompletionTime,
string gitHubOwner,
string gitHubRepo,
@@ -271,9 +272,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
commitInsert,
testmergeInsert,
remoteCommitInsert,
- byondVersion.Build > 0
- ? byondVersion.ToString()
- : $"{byondVersion.Major}.{byondVersion.Minor}",
+ byondVersion.ToString(),
estimatedCompletionTime.HasValue
? $" ETA: {estimatedCompletionTime - DateTimeOffset.UtcNow}"
: String.Empty),
diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs
index 88cd5b2e2c..4cf04a8f32 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Rights;
using Tgstation.Server.Host.Components.Interop;
using Tgstation.Server.Host.Jobs;
@@ -182,8 +183,8 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
///
public abstract ValueTask>>> SendUpdateMessage(
- RevisionInformation revisionInformation,
- Version byondVersion,
+ Models.RevisionInformation revisionInformation,
+ ByondVersion byondVersion,
DateTimeOffset? estimatedCompletionTime,
string gitHubOwner,
string gitHubRepo,
@@ -273,7 +274,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
connectNow = false;
if (!Connected)
{
- var job = new Job
+ var job = new Models.Job
{
Description = $"Reconnect chat bot: {ChatBot.Name}",
CancelRight = (ulong)ChatBotRights.WriteEnabled,
diff --git a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs
index b4e333a41d..e5e361299b 100644
--- a/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs
+++ b/src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs
@@ -245,6 +245,12 @@ namespace Tgstation.Server.Host.Components.Deployment
.ThenInclude(x => x.MergedBy)
.FirstAsync(cancellationToken)); // can't wait to see that query
+ if (!Api.Models.Internal.ByondVersion.TryParse(compileJob.ByondVersion, out var byondVersion))
+ {
+ logger.LogWarning("Error loading compile job, bad BYOND version: {0}", compileJob.ByondVersion);
+ return null; // omae wa mou shinderu
+ }
+
if (!compileJob.Job.StoppedAt.HasValue)
{
// This happens when we're told to load the compile job that is currently finished up
@@ -262,7 +268,7 @@ namespace Tgstation.Server.Host.Components.Deployment
CleanRegisteredCompileJob(compileJob);
}
- var newProvider = new DmbProvider(compileJob, ioManager, CleanupAction);
+ var newProvider = new DmbProvider(compileJob, byondVersion, ioManager, CleanupAction);
try
{
const string LegacyADirectoryName = "A";
@@ -299,7 +305,7 @@ namespace Tgstation.Server.Host.Components.Deployment
// rebuild the provider because it's using the legacy style directories
// Don't dispose it
logger.LogDebug("Creating legacy two folder .dmb provider targeting {aDirName} directory...", LegacyADirectoryName);
- newProvider = new DmbProvider(compileJob, ioManager, CleanupAction, Path.DirectorySeparatorChar + LegacyADirectoryName);
+ newProvider = new DmbProvider(compileJob, byondVersion, ioManager, CleanupAction, Path.DirectorySeparatorChar + LegacyADirectoryName);
}
lock (jobLockCounts)
diff --git a/src/Tgstation.Server.Host/Components/Deployment/DmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/DmbProvider.cs
index f3711ede4f..554cc28cdd 100644
--- a/src/Tgstation.Server.Host/Components/Deployment/DmbProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Deployment/DmbProvider.cs
@@ -1,7 +1,7 @@
using System;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.IO;
-using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Components.Deployment
{
@@ -14,10 +14,11 @@ namespace Tgstation.Server.Host.Components.Deployment
///
public string Directory => ioManager.ResolvePath(CompileJob.DirectoryName.ToString() + directoryAppend);
- ///
- /// The for the .
- ///
- public CompileJob CompileJob { get; }
+ ///
+ public Models.CompileJob CompileJob { get; }
+
+ ///
+ public ByondVersion ByondVersion { get; }
///
/// The for the .
@@ -25,7 +26,7 @@ namespace Tgstation.Server.Host.Components.Deployment
readonly IIOManager ioManager;
///
- /// Extra path to add to the end of .
+ /// Extra path to add to the end of .
///
readonly string directoryAppend;
@@ -38,12 +39,14 @@ namespace Tgstation.Server.Host.Components.Deployment
/// Initializes a new instance of the class.
///
/// The value of .
+ /// The value of .
/// The value of .
/// The value of .
/// The optional value of .
- public DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose, string directoryAppend = null)
+ public DmbProvider(Models.CompileJob compileJob, ByondVersion byondVersion, IIOManager ioManager, Action onDispose, string directoryAppend = null)
{
CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
+ ByondVersion = byondVersion ?? throw new ArgumentNullException(nameof(byondVersion));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
this.directoryAppend = directoryAppend ?? String.Empty;
diff --git a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs
index 30f6a555df..d31de3c46f 100644
--- a/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs
+++ b/src/Tgstation.Server.Host/Components/Deployment/DreamMaker.cs
@@ -553,7 +553,7 @@ namespace Tgstation.Server.Host.Components.Deployment
/// The to run and populate.
/// The to use.
/// The to use.
- /// The to use.
+ /// The to use.
/// The to use.
/// The to use.
/// The for the operation.
@@ -563,7 +563,7 @@ namespace Tgstation.Server.Host.Components.Deployment
Models.CompileJob job,
Api.Models.Internal.DreamMakerSettings dreamMakerSettings,
DreamDaemonLaunchParameters launchParameters,
- IByondExecutableLock byondLock,
+ IEngineExecutableLock byondLock,
IRepository repository,
IRemoteDeploymentManager remoteDeploymentManager,
CancellationToken cancellationToken)
@@ -591,7 +591,7 @@ namespace Tgstation.Server.Host.Components.Deployment
{
resolvedOutputDirectory,
repoOrigin.ToString(),
- $"{byondLock.Version.Major}.{byondLock.Version.Minor}",
+ byondLock.Version.ToString(),
},
true,
cancellationToken);
@@ -630,14 +630,14 @@ namespace Tgstation.Server.Host.Components.Deployment
{
resolvedOutputDirectory,
repoOrigin.ToString(),
- $"{byondLock.Version.Major}.{byondLock.Version.Minor}",
+ byondLock.Version.ToString(),
},
true,
cancellationToken);
// run compiler
progressReporter.StageName = "Running DreamMaker";
- var exitCode = await RunDreamMaker(byondLock.DreamMakerPath, job, cancellationToken);
+ var compileSuceeded = await RunDreamMaker(byondLock, job, cancellationToken);
// Session takes ownership of the lock and Disposes it so save this for later
var byondVersion = byondLock.Version;
@@ -645,10 +645,10 @@ namespace Tgstation.Server.Host.Components.Deployment
// verify api
try
{
- if (exitCode != 0)
+ if (!compileSuceeded)
throw new JobException(
ErrorCode.DreamMakerExitCode,
- new JobException($"Exit code: {exitCode}{Environment.NewLine}{Environment.NewLine}{job.Output}"));
+ new JobException($"Compilation failed:{Environment.NewLine}{Environment.NewLine}{job.Output}"));
progressReporter.StageName = "Validating DMAPI";
await VerifyApi(
@@ -670,7 +670,7 @@ namespace Tgstation.Server.Host.Components.Deployment
new List
{
resolvedOutputDirectory,
- exitCode == 0 ? "1" : "0",
+ compileSuceeded ? "1" : "0",
byondVersion.ToString(),
},
true,
@@ -769,7 +769,7 @@ namespace Tgstation.Server.Host.Components.Deployment
/// The timeout in seconds for validation.
/// The level to use to validate the API.
/// The for the operation.
- /// The current .
+ /// The current .
/// The port to use for API validation.
/// If the API validation is required to complete the deployment.
/// If output should be logged to the DreamDaemon Diagnostics folder.
@@ -779,7 +779,7 @@ namespace Tgstation.Server.Host.Components.Deployment
uint timeout,
DreamDaemonSecurity securityLevel,
Models.CompileJob job,
- IByondExecutableLock byondLock,
+ IEngineExecutableLock byondLock,
ushort portToUse,
bool requireValidate,
bool logOutput,
@@ -803,7 +803,11 @@ namespace Tgstation.Server.Host.Components.Deployment
job.MinimumSecurityLevel = securityLevel; // needed for the TempDmbProvider
ApiValidationStatus validationStatus;
- using (var provider = new TemporaryDmbProvider(ioManager.ResolvePath(job.DirectoryName.ToString()), String.Concat(job.DmeName, DmbExtension), job))
+ using (var provider = new TemporaryDmbProvider(
+ ioManager.ResolvePath(job.DirectoryName.ToString()),
+ String.Concat(job.DmeName, DmbExtension),
+ job,
+ byondLock.Version))
await using (var controller = await sessionControllerFactory.LaunchNew(provider, byondLock, launchParameters, true, cancellationToken))
{
var launchResult = await controller.LaunchResult.WaitAsync(cancellationToken);
@@ -853,33 +857,46 @@ namespace Tgstation.Server.Host.Components.Deployment
///
/// Compiles a .dme with DreamMaker.
///
- /// The path to the DreamMaker executable.
+ /// The to use.
/// The for the operation.
/// The for the operation.
- /// A representing the running operation.
- async ValueTask RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
+ /// A resulting in if compilation succeeded, otherwise.
+ async ValueTask RunDreamMaker(IEngineExecutableLock engineLock, Models.CompileJob job, CancellationToken cancellationToken)
{
- await using var dm = processExecutor.LaunchProcess(
- dreamMakerPath,
- ioManager.ResolvePath(
- job.DirectoryName.ToString()),
- $"-clean {job.DmeName}.{DmeExtension}",
- readStandardHandles: true,
- noShellExecute: true);
+ var arguments = engineLock.FormatCompilerArguments($"{job.DmeName}.{DmeExtension}");
+ bool result;
+ if (arguments == null)
+ {
+ logger.LogTrace("Engine lock says compilation isn't necessary.");
+ job.Output = $"{engineLock.Version.Engine} does not require compilation.";
+ result = true;
+ }
+ else
+ {
+ await using var dm = processExecutor.LaunchProcess(
+ engineLock.CompilerExePath,
+ ioManager.ResolvePath(
+ job.DirectoryName.ToString()),
+ arguments,
+ readStandardHandles: true,
+ noShellExecute: true);
- if (sessionConfiguration.LowPriorityDeploymentProcesses)
- dm.AdjustPriority(false);
+ if (sessionConfiguration.LowPriorityDeploymentProcesses)
+ dm.AdjustPriority(false);
- int exitCode;
- using (cancellationToken.Register(() => dm.Terminate()))
- exitCode = (await dm.Lifetime).Value;
- cancellationToken.ThrowIfCancellationRequested();
+ int exitCode;
+ using (cancellationToken.Register(() => dm.Terminate()))
+ exitCode = (await dm.Lifetime).Value;
+ cancellationToken.ThrowIfCancellationRequested();
+
+ logger.LogDebug("DreamMaker exit code: {exitCode}", exitCode);
+ job.Output = $"{await dm.GetCombinedOutput(cancellationToken)}{Environment.NewLine}{Environment.NewLine}Exit Code: {exitCode}";
+ logger.LogDebug("DreamMaker output: {newLine}{output}", Environment.NewLine, job.Output);
+ result = exitCode == 0;
+ }
- logger.LogDebug("DreamMaker exit code: {exitCode}", exitCode);
- job.Output = await dm.GetCombinedOutput(cancellationToken);
currentDreamMakerOutput = job.Output;
- logger.LogDebug("DreamMaker output: {newLine}{output}", Environment.NewLine, job.Output);
- return exitCode;
+ return result;
}
///
diff --git a/src/Tgstation.Server.Host/Components/Deployment/IDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/IDmbProvider.cs
index efc773a919..8f81cb7fbc 100644
--- a/src/Tgstation.Server.Host/Components/Deployment/IDmbProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Deployment/IDmbProvider.cs
@@ -1,6 +1,6 @@
using System;
-using Tgstation.Server.Host.Models;
+using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Host.Components.Deployment
{
@@ -22,7 +22,12 @@ namespace Tgstation.Server.Host.Components.Deployment
///
/// The of the .dmb.
///
- CompileJob CompileJob { get; }
+ Models.CompileJob CompileJob { get; }
+
+ ///
+ /// The used to build the .dmb.
+ ///
+ ByondVersion ByondVersion { get; }
///
/// Disposing the won't cause a cleanup of the working directory.
diff --git a/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs
index b3d8505e65..cfa69ede08 100644
--- a/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Deployment/SwappableDmbProvider.cs
@@ -2,8 +2,8 @@
using System.Threading;
using System.Threading.Tasks;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.IO;
-using Tgstation.Server.Host.Models;
namespace Tgstation.Server.Host.Components.Deployment
{
@@ -24,7 +24,10 @@ namespace Tgstation.Server.Host.Components.Deployment
public string Directory => ioManager.ResolvePath(LiveGameDirectory);
///
- public CompileJob CompileJob => baseProvider.CompileJob;
+ public Models.CompileJob CompileJob => baseProvider.CompileJob;
+
+ ///
+ public ByondVersion ByondVersion => baseProvider.ByondVersion;
///
/// If has been run.
diff --git a/src/Tgstation.Server.Host/Components/Deployment/TemporaryDmbProvider.cs b/src/Tgstation.Server.Host/Components/Deployment/TemporaryDmbProvider.cs
index 0bf982cfa3..5ecc6b9670 100644
--- a/src/Tgstation.Server.Host/Components/Deployment/TemporaryDmbProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Deployment/TemporaryDmbProvider.cs
@@ -1,6 +1,6 @@
using System;
-using Tgstation.Server.Host.Models;
+using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Host.Components.Deployment
{
@@ -16,7 +16,10 @@ namespace Tgstation.Server.Host.Components.Deployment
public string Directory { get; }
///
- public CompileJob CompileJob { get; }
+ public Models.CompileJob CompileJob { get; }
+
+ ///
+ public ByondVersion ByondVersion { get; }
///
/// Initializes a new instance of the class.
@@ -24,11 +27,13 @@ namespace Tgstation.Server.Host.Components.Deployment
/// The value of .
/// The value of .
/// The value of .
- public TemporaryDmbProvider(string directory, string dmb, CompileJob compileJob)
+ /// The value of .
+ public TemporaryDmbProvider(string directory, string dmb, Models.CompileJob compileJob, ByondVersion byondVersion)
{
DmbName = dmb ?? throw new ArgumentNullException(nameof(dmb));
Directory = directory ?? throw new ArgumentNullException(nameof(directory));
CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
+ ByondVersion = byondVersion ?? throw new ArgumentNullException(nameof(byondVersion));
}
///
diff --git a/src/Tgstation.Server.Host/Components/Session/ISessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/ISessionControllerFactory.cs
index b5bbf07f90..4ece5faa3e 100644
--- a/src/Tgstation.Server.Host/Components/Session/ISessionControllerFactory.cs
+++ b/src/Tgstation.Server.Host/Components/Session/ISessionControllerFactory.cs
@@ -16,14 +16,14 @@ namespace Tgstation.Server.Host.Components.Session
/// Create a from a freshly launch DreamDaemon instance.
///
/// The to use.
- /// The current if any.
+ /// The current if any.
/// The to use. will be updated with the minumum required security level for the launch.
/// If the should only validate the DMAPI then exit.
/// The for the operation.
/// A resulting in a new .
ValueTask LaunchNew(
IDmbProvider dmbProvider,
- IByondExecutableLock currentByondLock,
+ IEngineExecutableLock currentByondLock,
DreamDaemonLaunchParameters launchParameters,
bool apiValidate,
CancellationToken cancellationToken);
diff --git a/src/Tgstation.Server.Host/Components/Session/SessionController.cs b/src/Tgstation.Server.Host/Components/Session/SessionController.cs
index d3749f0e9f..13e6d0705a 100644
--- a/src/Tgstation.Server.Host/Components/Session/SessionController.cs
+++ b/src/Tgstation.Server.Host/Components/Session/SessionController.cs
@@ -123,9 +123,9 @@ namespace Tgstation.Server.Host.Components.Session
readonly IProcess process;
///
- /// The for the .
+ /// The for the .
///
- readonly IByondExecutableLock byondLock;
+ readonly IEngineExecutableLock byondLock;
///
/// The for the .
@@ -244,7 +244,7 @@ namespace Tgstation.Server.Host.Components.Session
ReattachInformation reattachInformation,
Api.Models.Instance metadata,
IProcess process,
- IByondExecutableLock byondLock,
+ IEngineExecutableLock byondLock,
global::Byond.TopicSender.ITopicClient byondTopicSender,
IChatTrackingContext chatTrackingContext,
IBridgeRegistrar bridgeRegistrar,
diff --git a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
index 3bc79939c7..e45ed439d6 100644
--- a/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
+++ b/src/Tgstation.Server.Host/Components/Session/SessionControllerFactory.cs
@@ -6,8 +6,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using Byond.TopicSender;
-
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
@@ -128,38 +126,6 @@ namespace Tgstation.Server.Host.Components.Session
///
readonly Api.Models.Instance instance;
- ///
- /// Change a given into the appropriate DreamDaemon command line word.
- ///
- /// The level to change.
- /// A representation of the command line parameter.
- static string SecurityWord(DreamDaemonSecurity securityLevel)
- {
- return securityLevel switch
- {
- DreamDaemonSecurity.Safe => "safe",
- DreamDaemonSecurity.Trusted => "trusted",
- DreamDaemonSecurity.Ultrasafe => "ultrasafe",
- _ => throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel)),
- };
- }
-
- ///
- /// Change a given into the appropriate DreamDaemon command line word.
- ///
- /// The level to change.
- /// A representation of the command line parameter.
- static string VisibilityWord(DreamDaemonVisibility visibility)
- {
- return visibility switch
- {
- DreamDaemonVisibility.Public => "public",
- DreamDaemonVisibility.Private => "private",
- DreamDaemonVisibility.Invisible => "invisible",
- _ => throw new ArgumentOutOfRangeException(nameof(visibility), visibility, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon visibility level: {0}", visibility)),
- };
- }
-
///
/// Check if a given can be bound to.
///
@@ -242,7 +208,7 @@ namespace Tgstation.Server.Host.Components.Session
#pragma warning disable CA1506 // TODO: Decomplexify
public async ValueTask LaunchNew(
IDmbProvider dmbProvider,
- IByondExecutableLock currentByondLock,
+ IEngineExecutableLock currentByondLock,
DreamDaemonLaunchParameters launchParameters,
bool apiValidate,
CancellationToken cancellationToken)
@@ -274,7 +240,7 @@ namespace Tgstation.Server.Host.Components.Session
// get the byond lock
var byondLock = currentByondLock ?? await byond.UseExecutables(
- Version.Parse(dmbProvider.CompileJob.ByondVersion),
+ dmbProvider.ByondVersion,
gameIOManager.ConcatPath(dmbProvider.Directory, dmbProvider.DmbName),
cancellationToken);
try
@@ -289,7 +255,7 @@ namespace Tgstation.Server.Host.Components.Session
string outputFilePath = null;
var preserveLogFile = true;
- var cliSupported = byondLock.SupportsCli;
+ var hasStandardOutput = byondLock.HasStandardOutput;
if (launchParameters.LogOutput.Value)
{
var now = DateTimeOffset.UtcNow;
@@ -302,7 +268,7 @@ namespace Tgstation.Server.Host.Components.Session
logger.LogInformation("Logging DreamDaemon output to {path}...", outputFilePath);
}
- else if (!cliSupported)
+ else if (!hasStandardOutput)
{
outputFilePath = gameIOManager.ConcatPath(dmbProvider.Directory, $"{Guid.NewGuid()}.dd.log");
preserveLogFile = false;
@@ -310,17 +276,12 @@ namespace Tgstation.Server.Host.Components.Session
var accessIdentifier = cryptographySuite.GetSecureString();
- var byondTopicSender = topicClientFactory.CreateTopicClient(
- TimeSpan.FromMilliseconds(
- launchParameters.TopicRequestTimeout.Value));
-
if (!apiValidate && dmbProvider.CompileJob.DMApiVersion == null)
logger.LogDebug("Session will have no DMAPI support!");
// launch dd
- var process = await CreateDreamDaemonProcess(
+ var process = await CreateGameServerProcess(
dmbProvider,
- byondTopicSender,
byondLock,
launchParameters,
accessIdentifier,
@@ -347,6 +308,10 @@ namespace Tgstation.Server.Host.Components.Session
accessIdentifier,
launchParameters.Port.Value);
+ var byondTopicSender = topicClientFactory.CreateTopicClient(
+ TimeSpan.FromMilliseconds(
+ launchParameters.TopicRequestTimeout.Value));
+
var sessionController = new SessionController(
reattachInformation,
instance,
@@ -362,7 +327,7 @@ namespace Tgstation.Server.Host.Components.Session
() => LogDDOutput(
process,
outputFilePath,
- cliSupported,
+ hasStandardOutput,
preserveLogFile,
CancellationToken.None), // DCT: None available
launchParameters.StartupTimeout,
@@ -406,7 +371,7 @@ namespace Tgstation.Server.Host.Components.Session
logger.LogTrace("Begin session reattach...");
var byondTopicSender = topicClientFactory.CreateTopicClient(reattachInformation.TopicRequestTimeout);
var byondLock = await byond.UseExecutables(
- Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion),
+ reattachInformation.Dmb.ByondVersion,
null, // Doesn't matter if it's trusted or not on reattach
cancellationToken);
@@ -423,7 +388,7 @@ namespace Tgstation.Server.Host.Components.Session
try
{
- if (!byondLock.SupportsCli)
+ if (byondLock.PromptsForNetworkAccess)
networkPromptReaper.RegisterProcess(process);
var chatTrackingContext = chat.CreateTrackingContext();
@@ -479,60 +444,45 @@ namespace Tgstation.Server.Host.Components.Session
}
///
- /// Creates the DreamDaemon .
+ /// Creates the game server .
///
/// The .
- /// The to use for sanitization.
- /// The .
+ /// The .
/// The .
/// The secure string to use for the session.
/// The path to log DreamDaemon output to.
/// If we are only validating the DMAPI then exiting.
/// The for the operation.
/// A resulting in the DreamDaemon .
- async ValueTask CreateDreamDaemonProcess(
+ async ValueTask CreateGameServerProcess(
IDmbProvider dmbProvider,
- ITopicClient byondTopicSender,
- IByondExecutableLock byondLock,
+ IEngineExecutableLock byondLock,
DreamDaemonLaunchParameters launchParameters,
string accessIdentifier,
string logFilePath,
bool apiValidate,
CancellationToken cancellationToken)
{
- // set command line options
- // more sanitization here cause it uses the same scheme
- var parameters = $"{DMApiConstants.ParamApiVersion}={byondTopicSender.SanitizeString(DMApiConstants.InteropVersion.Semver().ToString())}&{byondTopicSender.SanitizeString(DMApiConstants.ParamServerPort)}={serverPortProvider.HttpApiPort}&{byondTopicSender.SanitizeString(DMApiConstants.ParamAccessIdentifier)}={byondTopicSender.SanitizeString(accessIdentifier)}";
-
- if (!String.IsNullOrEmpty(launchParameters.AdditionalParameters))
- parameters = $"{parameters}&{launchParameters.AdditionalParameters}";
-
// important to run on all ports to allow port changing
- var arguments = String.Format(
- CultureInfo.InvariantCulture,
- "{0} -port {1} -ports 1-65535 {2}-close -verbose -{3} -{4}{5}{6}{7} -params \"{8}\"",
- dmbProvider.DmbName,
- launchParameters.Port.Value,
- launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty,
- SecurityWord(launchParameters.SecurityLevel.Value),
- VisibilityWord(launchParameters.Visibility.Value),
- !byondLock.SupportsCli
- ? $" -logself -log {logFilePath}"
- : String.Empty, // DD doesn't output anything if -logself is set???
- launchParameters.StartProfiler.Value
- ? " -profile"
- : String.Empty,
- byondLock.SupportsMapThreads && launchParameters.MapThreads.Value != 0
- ? $" -map-threads {launchParameters.MapThreads.Value}"
- : String.Empty,
- parameters);
+ var arguments = byondLock.FormatServerArguments(
+ dmbProvider,
+ new Dictionary
+ {
+ { DMApiConstants.ParamApiVersion, DMApiConstants.InteropVersion.Semver().ToString() },
+ { DMApiConstants.ParamServerPort, serverPortProvider.HttpApiPort.ToString(CultureInfo.InvariantCulture) },
+ { DMApiConstants.ParamAccessIdentifier, accessIdentifier },
+ },
+ launchParameters,
+ !byondLock.HasStandardOutput
+ ? logFilePath
+ : null);
var process = processExecutor.LaunchProcess(
- byondLock.DreamDaemonPath,
+ byondLock.ServerExePath,
dmbProvider.Directory,
arguments,
logFilePath,
- byondLock.SupportsCli,
+ byondLock.HasStandardOutput,
true);
try
@@ -545,7 +495,7 @@ namespace Tgstation.Server.Host.Components.Session
else if (sessionConfiguration.LowPriorityDeploymentProcesses)
process.AdjustPriority(false);
- if (!byondLock.SupportsCli)
+ if (!byondLock.HasStandardOutput)
networkPromptReaper.RegisterProcess(process);
// If this isnt a staging DD (From a Deployment), fire off an event
diff --git a/src/Tgstation.Server.Host/Controllers/ByondController.cs b/src/Tgstation.Server.Host/Controllers/ByondController.cs
index 156ff784e9..19212d7c5b 100644
--- a/src/Tgstation.Server.Host/Controllers/ByondController.cs
+++ b/src/Tgstation.Server.Host/Controllers/ByondController.cs
@@ -43,7 +43,7 @@ namespace Tgstation.Server.Host.Controllers
///
/// The to normalize.
/// The normalized . May be a reference to .
- static Version NormalizeVersion(Version version) => version.Build == 0 ? new Version(version.Major, version.Minor) : version;
+ static Version NormalizeByondVersion(Version version) => version.Build == 0 ? new Version(version.Major, version.Minor) : version;
///
/// Initializes a new instance of the class.
@@ -72,23 +72,26 @@ namespace Tgstation.Server.Host.Controllers
}
///
- /// Gets the active .
+ /// Gets the active .
///
/// A resulting in the for the operation.
/// Retrieved version information successfully.
+ /// No BYOND versions installed.
[HttpGet]
[TgsAuthorize(ByondRights.ReadActive)]
[ProducesResponseType(typeof(ByondResponse), 200)]
+ [ProducesResponseType(typeof(ErrorMessageResponse), 409)]
public ValueTask Read()
=> WithComponentInstance(instance =>
ValueTask.FromResult(
- Json(new ByondResponse
- {
- Version = instance.ByondManager.ActiveVersion,
- })));
+ instance.ByondManager.ActiveVersion != null
+ ? Json(
+ new ByondResponse(
+ instance.ByondManager.ActiveVersion))
+ : Conflict(new ErrorMessageResponse(ErrorCode.ResourceNotPresent))));
///
- /// Lists installed s.
+ /// Lists installed s.
///
/// The current page.
/// The page size.
@@ -106,10 +109,7 @@ namespace Tgstation.Server.Host.Controllers
instance
.ByondManager
.InstalledVersions
- .Select(x => new ByondResponse
- {
- Version = x,
- })
+ .Select(x => new ByondResponse(x))
.AsQueryable()
.OrderBy(x => x.Version))),
null,
@@ -126,27 +126,42 @@ namespace Tgstation.Server.Host.Controllers
/// Switched active version successfully.
/// Created to install and switch active version successfully.
[HttpPost]
- [TgsAuthorize(ByondRights.InstallOfficialOrChangeActiveVersion | ByondRights.InstallCustomVersion)]
+ [TgsAuthorize(
+ ByondRights.InstallOfficialOrChangeActiveByondVersion
+ | ByondRights.InstallCustomByondVersion
+ | ByondRights.InstallOfficialOrChangeActiveOpenDreamVersion
+ | ByondRights.InstallCustomOpenDreamVersion)]
[ProducesResponseType(typeof(ByondInstallResponse), 200)]
[ProducesResponseType(typeof(ByondInstallResponse), 202)]
-#pragma warning disable CA1506 // TODO: Decomplexify
+#pragma warning disable CA1502 // TODO: Decomplexify
+#pragma warning disable CA1506
public async ValueTask Update([FromBody] ByondVersionRequest model, CancellationToken cancellationToken)
#pragma warning restore CA1506
+#pragma warning restore CA1502
{
ArgumentNullException.ThrowIfNull(model);
var uploadingZip = model.UploadCustomZip == true;
+ var isByondEngine = model.Engine.Value == EngineType.Byond;
- if (model.Version == null
- || model.Version.Revision != -1
- || (uploadingZip && model.Version.Build > 0))
+ if ((isByondEngine && (model.Version.Revision != -1 || (uploadingZip && model.Version.Build > 0) || model.SourceCommittish != null || model.SourceRepository != null))
+ || (!isByondEngine && (model.Version != null || String.IsNullOrWhiteSpace(model.SourceCommittish))))
return BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure));
- var version = NormalizeVersion(model.Version);
+ Uri sourceRepo;
+ if (isByondEngine)
+ {
+ model.Version = NormalizeByondVersion(model.Version);
+ sourceRepo = null;
+ }
+ else
+ {
+ sourceRepo = model.SourceRepository ?? new Uri("https://github.com/OpenDreamProject/OpenDream");
+ }
var userByondRights = AuthenticationContext.InstancePermissionSet.ByondRights.Value;
- if ((!userByondRights.HasFlag(ByondRights.InstallOfficialOrChangeActiveVersion) && !uploadingZip)
- || (!userByondRights.HasFlag(ByondRights.InstallCustomVersion) && uploadingZip))
+ if ((!userByondRights.HasFlag(ByondRights.InstallOfficialOrChangeActiveByondVersion) && !uploadingZip)
+ || (!userByondRights.HasFlag(ByondRights.InstallCustomByondVersion) && uploadingZip))
return Forbid();
// remove cruff fields
@@ -155,44 +170,50 @@ namespace Tgstation.Server.Host.Controllers
async instance =>
{
var byondManager = instance.ByondManager;
- var versionAlreadyInstalled = !uploadingZip && byondManager.InstalledVersions.Any(x => x == version);
+ var versionAlreadyInstalled = !uploadingZip && byondManager.InstalledVersions.Any(x => x.Equals(model));
if (versionAlreadyInstalled)
{
Logger.LogInformation(
- "User ID {userId} changing instance ID {instanceId} BYOND version to {newByondVersion}",
+ "User ID {userId} changing instance ID {instanceId} {engineType} version to {newByondVersion}",
AuthenticationContext.User.Id,
Instance.Id,
- version);
+ model.Engine,
+ model.Version);
try
{
- await byondManager.ChangeVersion(null, version, null, false, cancellationToken);
+ await byondManager.ChangeVersion(null, model, null, false, cancellationToken);
}
catch (InvalidOperationException ex)
{
Logger.LogDebug(
ex,
- "Race condition: BYOND version {version} uninstalled before we could switch to it. Creating install job instead...",
- version);
+ "Race condition: {engineType} version {version} uninstalled before we could switch to it. Creating install job instead...",
+ model.Engine.Value,
+ model.Version);
versionAlreadyInstalled = false;
}
}
if (!versionAlreadyInstalled)
{
- if (version.Build > 0)
+ if (model.Version.Build > 0)
return BadRequest(new ErrorMessageResponse(ErrorCode.ByondNonExistentCustomVersion));
Logger.LogInformation(
- "User ID {userId} installing BYOND version to {newByondVersion} on instance ID {instanceId}",
+ "User ID {userId} installing {engineType} version {newByondVersion}{sourceCommittish} on instance ID {instanceId}",
AuthenticationContext.User.Id,
- version,
+ model.Engine.Value,
+ model.Version,
+ model.SourceCommittish != null
+ ? $" ({model.SourceCommittish})"
+ : String.Empty,
Instance.Id);
// run the install through the job manager
var job = new Job
{
- Description = $"Install {(!uploadingZip ? String.Empty : "custom ")}BYOND version {version}",
+ Description = $"Install {(!uploadingZip ? String.Empty : "custom ")}{model.Engine.Value} version {model.Version}",
StartedBy = AuthenticationContext.User,
CancelRightsType = RightsType.Byond,
CancelRight = (ulong)ByondRights.CancelInstall,
@@ -209,7 +230,13 @@ namespace Tgstation.Server.Host.Controllers
job,
async (core, databaseContextFactory, paramJob, progressHandler, jobCancellationToken) =>
{
- Stream zipFileStream = null;
+ if (sourceRepo != null)
+ await core.ByondManager.EnsureEngineSource(
+ sourceRepo,
+ model.Engine.Value,
+ jobCancellationToken);
+
+ MemoryStream zipFileStream = null;
if (fileUploadTicket != null)
await using (fileUploadTicket)
{
@@ -229,7 +256,7 @@ namespace Tgstation.Server.Host.Controllers
await using (zipFileStream)
await core.ByondManager.ChangeVersion(
progressHandler,
- version,
+ model,
zipFileStream,
true,
jobCancellationToken);
@@ -260,7 +287,7 @@ namespace Tgstation.Server.Host.Controllers
/// A resulting in the for the operation.
/// Created to delete target version successfully.
/// Attempted to delete the active BYOND .
- /// The specified was not installed.
+ /// The specified was not installed.
[HttpDelete]
[TgsAuthorize(ByondRights.DeleteInstall)]
[ProducesResponseType(typeof(JobResponse), 202)]
@@ -270,22 +297,22 @@ namespace Tgstation.Server.Host.Controllers
{
ArgumentNullException.ThrowIfNull(model);
- if (model.Version == null
- || model.Version.Revision != -1)
+ if (model.Version.Revision != -1)
return BadRequest(new ErrorMessageResponse(ErrorCode.ModelValidationFailure));
- var version = NormalizeVersion(model.Version);
+ if (model.Engine == EngineType.Byond)
+ model.Version = NormalizeByondVersion(model.Version);
var notInstalledResponse = await WithComponentInstance(
instance =>
{
var byondManager = instance.ByondManager;
- if (version == byondManager.ActiveVersion)
+ if (model.Equals(byondManager.ActiveVersion))
return ValueTask.FromResult(
Conflict(new ErrorMessageResponse(ErrorCode.ByondCannotDeleteActiveVersion)));
- var versionNotInstalled = !byondManager.InstalledVersions.Any(x => x == version);
+ var versionNotInstalled = !byondManager.InstalledVersions.Any(x => x.Equals(model));
return ValueTask.FromResult(
versionNotInstalled
@@ -296,22 +323,27 @@ namespace Tgstation.Server.Host.Controllers
if (notInstalledResponse != null)
return notInstalledResponse;
- var isCustomVersion = version.Build != -1;
+ var isByondVersion = model.Engine.Value == EngineType.Byond;
// run the install through the job manager
var job = new Job
{
- Description = $"Delete installed BYOND version {version}",
+ Description = $"Delete installed {model.Engine.Value} version {model.Version}",
StartedBy = AuthenticationContext.User,
CancelRightsType = RightsType.Byond,
- CancelRight = (ulong)(isCustomVersion ? ByondRights.InstallOfficialOrChangeActiveVersion : ByondRights.InstallCustomVersion),
+ CancelRight = (ulong)(
+ isByondVersion
+ ? model.Version.Build != -1
+ ? ByondRights.InstallOfficialOrChangeActiveByondVersion
+ : ByondRights.InstallCustomByondVersion
+ : ByondRights.InstallCustomOpenDreamVersion | ByondRights.InstallOfficialOrChangeActiveOpenDreamVersion),
Instance = Instance,
};
await jobManager.RegisterOperation(
job,
(instanceCore, databaseContextFactory, job, progressReporter, jobCancellationToken)
- => instanceCore.ByondManager.DeleteVersion(progressReporter, version, jobCancellationToken),
+ => instanceCore.ByondManager.DeleteVersion(progressReporter, model, jobCancellationToken),
cancellationToken);
var apiResponse = job.ToApi();
diff --git a/src/Tgstation.Server.Host/Models/CompileJob.cs b/src/Tgstation.Server.Host/Models/CompileJob.cs
index 9ddde1344c..a5f5ac67d0 100644
--- a/src/Tgstation.Server.Host/Models/CompileJob.cs
+++ b/src/Tgstation.Server.Host/Models/CompileJob.cs
@@ -82,7 +82,7 @@ namespace Tgstation.Server.Host.Models
}
///
- public CompileJobResponse ToApi() => new CompileJobResponse
+ public CompileJobResponse ToApi() => new ()
{
DirectoryName = DirectoryName,
DmeName = DmeName,
@@ -90,7 +90,9 @@ namespace Tgstation.Server.Host.Models
Job = Job.ToApi(),
Output = Output,
RevisionInformation = RevisionInformation.ToApi(),
- ByondVersion = Version.Parse(ByondVersion),
+ ByondVersion = Api.Models.Internal.ByondVersion.TryParse(ByondVersion, out var version)
+ ? version
+ : throw new InvalidOperationException($"Failed to parse BYOND version: {ByondVersion}"),
MinimumSecurityLevel = MinimumSecurityLevel,
DMApiVersion = DMApiVersion,
RepositoryOrigin = RepositoryOrigin != null ? new Uri(RepositoryOrigin) : null,
diff --git a/tests/Tgstation.Server.Api.Tests/Rights/TestRights.cs b/tests/Tgstation.Server.Api.Tests/Rights/TestRights.cs
index 62e41b7d98..e773f4da94 100644
--- a/tests/Tgstation.Server.Api.Tests/Rights/TestRights.cs
+++ b/tests/Tgstation.Server.Api.Tests/Rights/TestRights.cs
@@ -40,7 +40,7 @@ namespace Tgstation.Server.Api.Rights.Tests
[TestMethod]
public void TestAllRightsWorks()
{
- var allByondRights = ByondRights.CancelInstall | ByondRights.InstallOfficialOrChangeActiveVersion | ByondRights.ListInstalled | ByondRights.ReadActive | ByondRights.InstallCustomVersion | ByondRights.DeleteInstall;
+ var allByondRights = ByondRights.CancelInstall | ByondRights.InstallOfficialOrChangeActiveByondVersion | ByondRights.ListInstalled | ByondRights.ReadActive | ByondRights.InstallCustomByondVersion | ByondRights.DeleteInstall;
var automaticByondRights = RightsHelper.AllRights();
Assert.AreEqual(allByondRights, automaticByondRights);
diff --git a/tests/Tgstation.Server.Client.Tests/TestApiClient.cs b/tests/Tgstation.Server.Client.Tests/TestApiClient.cs
index d4c81db6c3..3027f9ac45 100644
--- a/tests/Tgstation.Server.Client.Tests/TestApiClient.cs
+++ b/tests/Tgstation.Server.Client.Tests/TestApiClient.cs
@@ -11,6 +11,8 @@ using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
+using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Models.Response;
using Tgstation.Server.Common.Http;
@@ -22,10 +24,12 @@ namespace Tgstation.Server.Client.Tests
[TestMethod]
public async Task TestDeserializingByondModelsWork()
{
- var sample = new ByondResponse
- {
- Version = new Version(511, 1385, 0)
- };
+ var sample = new ByondResponse(
+ new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = new Version(511, 1385, 0)
+ });
var sampleJson = JsonConvert.SerializeObject(sample, new JsonSerializerSettings
{
@@ -51,10 +55,12 @@ namespace Tgstation.Server.Client.Tests
[TestMethod]
public async Task TestUnrecognizedResponse()
{
- var sample = new ByondResponse
- {
- Version = new Version(511, 1385)
- };
+ var sample = new ByondResponse(
+ new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = new Version(511, 1385)
+ });
var fakeJson = "asdfasd <>F#(*)U*#JLI";
diff --git a/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs b/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs
index dccf90d3e0..c57e72afa1 100644
--- a/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs
+++ b/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs
@@ -6,6 +6,8 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Components.Byond.Tests
@@ -62,7 +64,11 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
new MemoryStream(ourArray)))
.Verifiable();
- var result = await installer.DownloadVersion(new Version(511, 1385), default);
+ var result = await installer.DownloadVersion(new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = new Version(123, 252345),
+ }, default);
Assert.IsTrue(ourArray.SequenceEqual(result.ToArray()));
mockIOManager.Verify();
@@ -79,9 +85,17 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
const string FakePath = "fake";
await Assert.ThrowsExceptionAsync(() => installer.InstallByond(null, null, default).AsTask());
- await Assert.ThrowsExceptionAsync(() => installer.InstallByond(new Version(123,252345), null, default).AsTask());
- await installer.InstallByond(new Version(511, 1385), FakePath, default);
+ var byondVersion = new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = new Version(123, 252345),
+ };
+
+ await Assert.ThrowsExceptionAsync(() => installer.InstallByond(byondVersion, null, default).AsTask());
+
+ byondVersion.Version = new Version(511, 1385);
+ await installer.InstallByond(byondVersion, FakePath, default);
mockPostWriteHandler.Verify(x => x.HandleWrite(It.IsAny()), Times.Exactly(4));
}
diff --git a/tests/Tgstation.Server.Host.Tests/Security/TestAuthenticationContext.cs b/tests/Tgstation.Server.Host.Tests/Security/TestAuthenticationContext.cs
index 090f10f1ec..fb0bea813d 100644
--- a/tests/Tgstation.Server.Host.Tests/Security/TestAuthenticationContext.cs
+++ b/tests/Tgstation.Server.Host.Tests/Security/TestAuthenticationContext.cs
@@ -1,4 +1,4 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
@@ -50,7 +50,7 @@ namespace Tgstation.Server.Host.Security.Tests
var authContext = new AuthenticationContext(null, user, instanceUser);
user.PermissionSet.AdministrationRights = AdministrationRights.WriteUsers;
- instanceUser.ByondRights = ByondRights.InstallOfficialOrChangeActiveVersion | ByondRights.ReadActive;
+ instanceUser.ByondRights = ByondRights.InstallOfficialOrChangeActiveByondVersion | ByondRights.ReadActive;
Assert.AreEqual((ulong)user.PermissionSet.AdministrationRights, authContext.GetRight(RightsType.Administration));
Assert.AreEqual((ulong)instanceUser.ByondRights, authContext.GetRight(RightsType.Byond));
}
diff --git a/tests/Tgstation.Server.Tests/CachingFileDownloader.cs b/tests/Tgstation.Server.Tests/CachingFileDownloader.cs
index 17dcbbfaf5..e00206bfe0 100644
--- a/tests/Tgstation.Server.Tests/CachingFileDownloader.cs
+++ b/tests/Tgstation.Server.Tests/CachingFileDownloader.cs
@@ -9,6 +9,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Common.Http;
using Tgstation.Server.Host.Extensions;
using Tgstation.Server.Host.IO;
@@ -42,9 +43,9 @@ namespace Tgstation.Server.Tests
var logger = loggerFactory.CreateLogger("CachingFileDownloader");
var cfd = new CachingFileDownloader(loggerFactory.CreateLogger());
- var edgeVersion = await ByondTest.GetEdgeVersion(cfd, cancellationToken);
+ var edgeVersion = await ByondTest.GetEdgeVersion(Api.Models.EngineType.Byond, cfd, cancellationToken);
- await InitializeByondVersion(logger, edgeVersion, new PlatformIdentifier().IsWindows, cancellationToken);
+ await InitializeByondVersion(logger, edgeVersion.Version, new PlatformIdentifier().IsWindows, cancellationToken);
// predownload the target github release update asset
var gitHubToken = Environment.GetEnvironmentVariable("TGS_TEST_GITHUB_TOKEN");
@@ -76,10 +77,16 @@ namespace Tgstation.Server.Tests
ServiceCollectionExtensions.UseFileDownloader();
}
- public static async ValueTask InitializeByondVersion(ILogger logger, Version version, bool windows, CancellationToken cancellationToken)
+ public static async ValueTask InitializeByondVersion(ILogger logger, Version byondVersion, bool windows, CancellationToken cancellationToken)
{
+ var version = new ByondVersion
+ {
+ Engine = Api.Models.EngineType.Byond,
+ Version = byondVersion,
+ };
+
var url = new Uri(
- $"https://www.byond.com/download/build/{version.Major}/{version.Major}.{version.Minor}_byond{(!windows ? "_linux" : string.Empty)}.zip");
+ $"https://www.byond.com/download/build/{version.Version.Major}/{version.Version.Major}.{version.Version.Minor}_byond{(!windows ? "_linux" : string.Empty)}.zip");
string path = null;
if (TestingUtils.RunningInGitHubActions)
{
@@ -91,7 +98,7 @@ namespace Tgstation.Server.Tests
windows ? "windows" : "linux");
path = Path.Combine(
dir,
- $"{version.Major}.{version.Minor}.zip");
+ $"{version.Version.Major}.{version.Version.Minor}.zip");
}
await (await CacheFile(logger, url, null, path, cancellationToken)).DisposeAsync();
diff --git a/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs b/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs
index 4f1ddf7387..255e162c8d 100644
--- a/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs
+++ b/tests/Tgstation.Server.Tests/Live/DummyChatProvider.cs
@@ -12,6 +12,7 @@ using Moq;
using Newtonsoft.Json;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Host.Components.Chat;
using Tgstation.Server.Host.Components.Chat.Commands;
using Tgstation.Server.Host.Components.Chat.Providers;
@@ -100,7 +101,15 @@ namespace Tgstation.Server.Tests.Live
return ValueTask.CompletedTask;
}
- public override ValueTask>>> SendUpdateMessage(RevisionInformation revisionInformation, Version byondVersion, DateTimeOffset? estimatedCompletionTime, string gitHubOwner, string gitHubRepo, ulong channelId, bool localCommitPushed, CancellationToken cancellationToken)
+ public override ValueTask>>> SendUpdateMessage(
+ Host.Models.RevisionInformation revisionInformation,
+ ByondVersion byondVersion,
+ DateTimeOffset? estimatedCompletionTime,
+ string gitHubOwner,
+ string gitHubRepo,
+ ulong channelId,
+ bool localCommitPushed,
+ CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(revisionInformation);
ArgumentNullException.ThrowIfNull(byondVersion);
diff --git a/tests/Tgstation.Server.Tests/Live/Instance/ByondTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/ByondTest.cs
index eedac0cd0e..3e9f5ca84c 100644
--- a/tests/Tgstation.Server.Tests/Live/Instance/ByondTest.cs
+++ b/tests/Tgstation.Server.Tests/Live/Instance/ByondTest.cs
@@ -6,13 +6,17 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Elasticsearch.Net.Specification.IndexLifecycleManagementApi;
+
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Models.Request;
using Tgstation.Server.Api.Models.Response;
using Tgstation.Server.Client;
@@ -32,16 +36,22 @@ namespace Tgstation.Server.Tests.Live.Instance
readonly Api.Models.Instance metadata;
- static Version edgeVersion;
+ static Dictionary edgeVersions = new Dictionary
+ {
+ { EngineType.Byond, null },
+ { EngineType.OpenDream, null }
+ };
- Version testVersion;
+ ByondVersion testVersion;
+ EngineType testEngine;
- public ByondTest(IByondClient byondClient, IJobsClient jobsClient, IFileDownloader fileDownloader, Api.Models.Instance metadata)
+ public ByondTest(IByondClient byondClient, IJobsClient jobsClient, IFileDownloader fileDownloader, Api.Models.Instance metadata, EngineType engineType)
: base(jobsClient)
{
this.byondClient = byondClient ?? throw new ArgumentNullException(nameof(byondClient));
this.fileDownloader = fileDownloader ?? throw new ArgumentNullException(nameof(fileDownloader));
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
+ this.testEngine = engineType;
}
public Task Run(CancellationToken cancellationToken, out Task firstInstall)
@@ -50,42 +60,67 @@ namespace Tgstation.Server.Tests.Live.Instance
return RunContinued(firstInstall, cancellationToken);
}
- public static async Task GetEdgeVersion(IFileDownloader fileDownloader, CancellationToken cancellationToken)
+ public static async ValueTask GetEdgeVersion(EngineType engineType, IFileDownloader fileDownloader, CancellationToken cancellationToken)
{
+ var edgeVersion = edgeVersions[engineType];
+
if (edgeVersion != null)
return edgeVersion;
- await using var provider = fileDownloader.DownloadFile(new Uri("https://www.byond.com/download/version.txt"), null);
- var stream = await provider.GetResult(cancellationToken);
- using var reader = new StreamReader(stream, Encoding.UTF8, false, -1, true);
- var text = await reader.ReadToEndAsync();
- var splits = text.Split('\n', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
+ ByondVersion byondVersion;
+ if (engineType == EngineType.Byond)
+ {
+ await using var provider = fileDownloader.DownloadFile(new Uri("https://www.byond.com/download/version.txt"), null);
+ var stream = await provider.GetResult(cancellationToken);
+ using var reader = new StreamReader(stream, Encoding.UTF8, false, -1, true);
+ var text = await reader.ReadToEndAsync(cancellationToken);
+ var splits = text.Split('\n', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
- var targetVersion = splits.Last();
+ var targetVersion = splits.Last();
- var missingVersionMap = new PlatformIdentifier().IsWindows
- ? new Dictionary()
- {
- }
- // linux map also needs updating in CI
- : new Dictionary()
- {
+ var missingVersionMap = new PlatformIdentifier().IsWindows
+ ? new Dictionary()
+ {
+ }
+ // linux map also needs updating in CI
+ : new Dictionary()
+ {
{ "515.1612", "515.1611" }
- };
+ };
- if (missingVersionMap.TryGetValue(targetVersion, out var remappedVersion))
- targetVersion = remappedVersion;
+ if (missingVersionMap.TryGetValue(targetVersion, out var remappedVersion))
+ targetVersion = remappedVersion;
- return edgeVersion = Version.Parse(targetVersion);
+ Assert.IsTrue(ByondVersion.TryParse(targetVersion, out byondVersion), $"Bad version: {targetVersion}");
+ }
+ else
+ {
+ Assert.Fail($"Edge version retrieval for {engineType} not implemented!");
+ return null;
+ }
+
+ return edgeVersions[engineType] = byondVersion;
}
async Task RunPartOne(CancellationToken cancellationToken)
{
- testVersion = await GetEdgeVersion(fileDownloader, cancellationToken);
+ testVersion = await GetEdgeVersion(EngineType.Byond, fileDownloader, cancellationToken);
await TestNoVersion(cancellationToken);
+ await TestInstallNullVersion(cancellationToken);
await TestInstallStable(cancellationToken);
}
+ ValueTask TestInstallNullVersion(CancellationToken cancellationToken)
+ => ApiAssert.ThrowsException(
+ () => byondClient.SetActiveVersion(
+ new ByondVersionRequest
+ {
+ Engine = testEngine,
+ },
+ null,
+ cancellationToken),
+ ErrorCode.ModelValidationFailure);
+
async Task RunContinued(Task firstInstall, CancellationToken cancellationToken)
{
await firstInstall;
@@ -98,7 +133,8 @@ namespace Tgstation.Server.Tests.Live.Instance
{
var deleteThisOneBecauseItWasntPartOfTheOriginalTest = await byondClient.DeleteVersion(new ByondVersionDeleteRequest
{
- Version = new(testVersion.Major, testVersion.Minor, 2)
+ Engine = testEngine,
+ Version = new(testVersion.Version.Major, testVersion.Version.Minor, 2)
}, cancellationToken);
await WaitForJob(deleteThisOneBecauseItWasntPartOfTheOriginalTest, 30, false, null, cancellationToken);
@@ -112,14 +148,18 @@ namespace Tgstation.Server.Tests.Live.Instance
var uninstallResponseTask = byondClient.DeleteVersion(
new ByondVersionDeleteRequest
{
- Version = testVersion
+ Version = testVersion.Version,
+ Engine = testVersion.Engine,
+ SourceCommittish = testVersion.SourceCommittish,
},
cancellationToken);
var badBecauseActiveResponseTask = ApiAssert.ThrowsException(() => byondClient.DeleteVersion(
new ByondVersionDeleteRequest
{
- Version = new(testVersion.Major, testVersion.Minor, 1)
+ Version = new(testVersion.Version.Major, testVersion.Version.Minor, 1),
+ Engine = testVersion.Engine,
+ SourceCommittish = testVersion.SourceCommittish,
},
cancellationToken), ErrorCode.ByondCannotDeleteActiveVersion);
@@ -140,7 +180,7 @@ namespace Tgstation.Server.Tests.Live.Instance
var newVersions = await byondClient.InstalledVersions(null, cancellationToken);
Assert.IsNotNull(newVersions);
Assert.AreEqual(1, newVersions.Count);
- Assert.AreEqual(new Version(testVersion.Major, testVersion.Minor, 1), newVersions[0].Version);
+ Assert.AreEqual(new Version(testVersion.Version.Major, testVersion.Version.Minor, 1), newVersions[0].Version);
}
async Task TestInstallFakeVersion(CancellationToken cancellationToken)
@@ -158,7 +198,9 @@ namespace Tgstation.Server.Tests.Live.Instance
{
var newModel = new ByondVersionRequest
{
- Version = testVersion
+ Version = testVersion.Version,
+ Engine = testVersion.Engine,
+ SourceCommittish = testVersion.SourceCommittish,
};
var test = await byondClient.SetActiveVersion(newModel, null, cancellationToken);
Assert.IsNotNull(test.InstallJob);
@@ -220,7 +262,9 @@ namespace Tgstation.Server.Tests.Live.Instance
var test = await byondClient.SetActiveVersion(
new ByondVersionRequest
{
- Version = testVersion,
+ Engine = testVersion.Engine,
+ Version = testVersion.Version,
+ SourceCommittish = testVersion.SourceCommittish,
UploadCustomZip = true
},
stableBytesMs,
@@ -234,7 +278,9 @@ namespace Tgstation.Server.Tests.Live.Instance
var test2 = await byondClient.SetActiveVersion(
new ByondVersionRequest
{
- Version = testVersion,
+ Version = testVersion.Version,
+ SourceCommittish = testVersion.SourceCommittish,
+ Engine = testVersion.Engine,
UploadCustomZip = true
},
stableBytesMs,
@@ -244,22 +290,24 @@ namespace Tgstation.Server.Tests.Live.Instance
await WaitForJob(test2.InstallJob, 30, false, null, cancellationToken);
var newSettings = await byondClient.ActiveVersion(cancellationToken);
- Assert.AreEqual(new Version(testVersion.Major, testVersion.Minor, 2), newSettings.Version);
+ Assert.AreEqual(new Version(testVersion.Version.Major, testVersion.Version.Minor, 2), newSettings.Version);
// test a few switches
var installResponse = await byondClient.SetActiveVersion(new ByondVersionRequest
{
- Version = testVersion
+ Version = testVersion.Version,
+ SourceCommittish = testVersion.SourceCommittish,
+ Engine = testVersion.Engine,
}, null, cancellationToken);
Assert.IsNull(installResponse.InstallJob);
await ApiAssert.ThrowsException(() => byondClient.SetActiveVersion(new ByondVersionRequest
{
- Version = new Version(testVersion.Major, testVersion.Minor, 3)
+ Version = new Version(testVersion.Version.Major, testVersion.Version.Minor, 3)
}, null, cancellationToken), ErrorCode.ByondNonExistentCustomVersion);
installResponse = await byondClient.SetActiveVersion(new ByondVersionRequest
{
- Version = new Version(testVersion.Major, testVersion.Minor, 1)
+ Version = new Version(testVersion.Version.Major, testVersion.Version.Minor, 1)
}, null, cancellationToken);
Assert.IsNull(installResponse.InstallJob);
}
diff --git a/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs
index ed0edee01e..ea17e68033 100644
--- a/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs
+++ b/tests/Tgstation.Server.Tests/Live/Instance/InstanceTest.cs
@@ -10,6 +10,7 @@ using Microsoft.Extensions.Options;
using Moq;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Models.Request;
using Tgstation.Server.Api.Models.Response;
using Tgstation.Server.Client;
@@ -43,9 +44,10 @@ namespace Tgstation.Server.Tests.Live.Instance
ushort ddPort,
bool highPrioDD,
bool lowPrioDeployment,
+ EngineType engineType,
CancellationToken cancellationToken)
{
- var byondTest = new ByondTest(instanceClient.Byond, instanceClient.Jobs, fileDownloader, instanceClient.Metadata);
+ var byondTest = new ByondTest(instanceClient.Byond, instanceClient.Jobs, fileDownloader, instanceClient.Metadata, engineType);
var chatTest = new ChatTest(instanceClient.ChatBots, instanceManagerClient, instanceClient.Jobs, instanceClient.Metadata);
var configTest = new ConfigurationTest(instanceClient.Configuration, instanceClient.Metadata);
var repoTest = new RepositoryTest(instanceClient.Repository, instanceClient.Jobs);
@@ -66,17 +68,23 @@ namespace Tgstation.Server.Tests.Live.Instance
await byondTask;
await new WatchdogTest(
- await ByondTest.GetEdgeVersion(fileDownloader, cancellationToken), instanceClient, instanceManager, serverPort, highPrioDD, ddPort).Run(cancellationToken);
+ await ByondTest.GetEdgeVersion(engineType, fileDownloader, cancellationToken), instanceClient, instanceManager, serverPort, highPrioDD, ddPort).Run(cancellationToken);
}
public async Task RunCompatTests(
- Version compatVersion,
+ Version compatByondVersion,
IInstanceClient instanceClient,
ushort dmPort,
ushort ddPort,
bool highPrioDD,
CancellationToken cancellationToken)
{
+ var compatVersion = new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = compatByondVersion,
+ };
+
System.Console.WriteLine($"COMPAT TEST START: {compatVersion}");
const string Origin = "https://github.com/Cyberboss/common_core";
var cloneRequest = instanceClient.Repository.Clone(new RepositoryCreateRequest
@@ -155,7 +163,9 @@ namespace Tgstation.Server.Tests.Live.Instance
installJob2 = await instanceClient.Byond.SetActiveVersion(new ByondVersionRequest
{
UploadCustomZip = true,
- Version = compatVersion,
+ Version = compatVersion.Version,
+ Engine = compatVersion.Engine,
+ SourceCommittish = compatVersion.SourceCommittish
}, stableBytesMs, cancellationToken);
}
diff --git a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs
index 3c4b9cf460..2726b4a576 100644
--- a/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs
+++ b/tests/Tgstation.Server.Tests/Live/Instance/WatchdogTest.cs
@@ -18,6 +18,7 @@ using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Models.Request;
using Tgstation.Server.Api.Models.Response;
using Tgstation.Server.Client;
@@ -57,11 +58,11 @@ namespace Tgstation.Server.Tests.Live.Instance
readonly ushort ddPort;
readonly bool highPrioDD;
readonly TopicClient topicClient;
- readonly Version testVersion;
+ readonly ByondVersion testVersion;
bool ranTimeoutTest = false;
- public WatchdogTest(Version testVersion, IInstanceClient instanceClient, InstanceManager instanceManager, ushort serverPort, bool highPrioDD, ushort ddPort)
+ public WatchdogTest(ByondVersion testVersion, IInstanceClient instanceClient, InstanceManager instanceManager, ushort serverPort, bool highPrioDD, ushort ddPort)
: base(instanceClient.Jobs)
{
this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient));
@@ -94,8 +95,9 @@ namespace Tgstation.Server.Tests.Live.Instance
var byondVersion = list[0];
Assert.AreEqual(1, byondVersion.Version.Build);
- Assert.AreEqual(testVersion.Major, byondVersion.Version.Major);
- Assert.AreEqual(testVersion.Minor, byondVersion.Version.Minor);
+ Assert.AreEqual(testVersion.Version.Major, byondVersion.Version.Major);
+ Assert.AreEqual(testVersion.Version.Minor, byondVersion.Version.Minor);
+ Assert.AreEqual(testVersion.Engine, byondVersion.Engine);
}
await Task.WhenAll(
@@ -230,10 +232,10 @@ namespace Tgstation.Server.Tests.Live.Instance
async Task TestDeleteByondInstallErrorCasesAndQueing(CancellationToken cancellationToken)
{
- var testCustomVersion = new Version(testVersion.Major, testVersion.Minor, 1);
+ var testCustomVersion = new Version(testVersion.Version.Major, testVersion.Version.Minor, 1);
var currentByond = await instanceClient.Byond.ActiveVersion(cancellationToken);
Assert.IsNotNull(currentByond);
- Assert.AreEqual(testVersion.Semver(), currentByond.Version);
+ Assert.AreEqual(testVersion.Version.Semver(), currentByond.Version);
// Change the active version and check we get delayed while deleting the old one because the watchdog is using it
var setActiveResponse = await instanceClient.Byond.SetActiveVersion(
@@ -250,7 +252,8 @@ namespace Tgstation.Server.Tests.Live.Instance
var deleteJob = await instanceClient.Byond.DeleteVersion(
new ByondVersionDeleteRequest
{
- Version = testVersion,
+ Version = testVersion.Version,
+ SourceCommittish = testVersion.SourceCommittish,
},
cancellationToken);
@@ -265,7 +268,9 @@ namespace Tgstation.Server.Tests.Live.Instance
setActiveResponse = await instanceClient.Byond.SetActiveVersion(
new ByondVersionRequest
{
- Version = testVersion,
+ Version = testVersion.Version,
+ Engine = testVersion.Engine,
+ SourceCommittish = testVersion.SourceCommittish
},
null,
cancellationToken);
@@ -291,7 +296,9 @@ namespace Tgstation.Server.Tests.Live.Instance
deleteJob = await instanceClient.Byond.DeleteVersion(
new ByondVersionDeleteRequest
{
- Version = testVersion,
+ Version = testVersion.Version,
+ Engine = testVersion.Engine,
+ SourceCommittish = testVersion.SourceCommittish,
},
cancellationToken);
@@ -954,9 +961,8 @@ namespace Tgstation.Server.Tests.Live.Instance
System.Console.WriteLine("TEST: WATCHDOG BYOND VERSION UPDATE TEST");
var versionToInstall = testVersion;
- versionToInstall = versionToInstall.Semver();
var currentByondVersion = await instanceClient.Byond.ActiveVersion(cancellationToken);
- Assert.AreNotEqual(versionToInstall, currentByondVersion.Version);
+ Assert.AreNotEqual(versionToInstall, currentByondVersion);
var initialStatus = await instanceClient.DreamDaemon.Read(cancellationToken);
@@ -969,7 +975,9 @@ namespace Tgstation.Server.Tests.Live.Instance
var byondInstallJobTask = instanceClient.Byond.SetActiveVersion(
new ByondVersionRequest
{
- Version = versionToInstall
+ Version = versionToInstall.Version,
+ Engine = versionToInstall.Engine,
+ SourceCommittish = versionToInstall.SourceCommittish,
},
null,
cancellationToken);
diff --git a/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs b/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs
index fbfd2d92e6..0b98971e3e 100644
--- a/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs
+++ b/tests/Tgstation.Server.Tests/Live/TestLiveServer.cs
@@ -28,6 +28,7 @@ using Npgsql;
using Tgstation.Server.Api;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Api.Models.Internal;
using Tgstation.Server.Api.Models.Request;
using Tgstation.Server.Api.Models.Response;
using Tgstation.Server.Api.Rights;
@@ -955,7 +956,12 @@ namespace Tgstation.Server.Tests.Live
}
[TestMethod]
- public async Task TestStandardTgsOperation()
+ public Task TestStandardTgsOperation() => TestStandardTgsOperation(EngineType.Byond);
+
+ [TestMethod]
+ public Task TestOpenDreamTgsOperation() => TestStandardTgsOperation(EngineType.OpenDream);
+
+ async Task TestStandardTgsOperation(EngineType engineType)
{
using(var currentProcess = System.Diagnostics.Process.GetCurrentProcess())
{
@@ -980,7 +986,7 @@ namespace Tgstation.Server.Tests.Live
ServiceCollectionExtensions.UseAdditionalLoggerProvider();
var failureTask = HardFailLoggerProvider.FailureSource;
- var internalTask = TestTgsInternal(hardCancellationToken);
+ var internalTask = TestTgsInternal(engineType, hardCancellationToken);
await Task.WhenAny(
internalTask,
failureTask);
@@ -1012,7 +1018,7 @@ namespace Tgstation.Server.Tests.Live
await internalTask;
}
- async Task TestTgsInternal(CancellationToken hardCancellationToken)
+ async Task TestTgsInternal(EngineType engineType, CancellationToken hardCancellationToken)
{
var discordConnectionString = Environment.GetEnvironmentVariable("TGS_TEST_DISCORD_TOKEN");
var ircConnectionString = Environment.GetEnvironmentVariable("TGS_TEST_IRC_CONNECTION_STRING");
@@ -1118,7 +1124,7 @@ namespace Tgstation.Server.Tests.Live
async Task RunInstanceTests()
{
// Some earlier linux BYOND versions have a critical bug where replacing the directory in non-basic watchdogs causes the DreamDaemon cwd to change
- var canRunCompatTests = new PlatformIdentifier().IsWindows;
+ var canRunCompatTests = engineType == EngineType.Byond && new PlatformIdentifier().IsWindows;
var compatTests = canRunCompatTests
? FailFast(
instanceTest
@@ -1142,6 +1148,7 @@ namespace Tgstation.Server.Tests.Live
mainDDPort,
server.HighPriorityDreamDaemon,
server.LowPriorityDeployments,
+ engineType,
cancellationToken));
await compatTests;
@@ -1308,7 +1315,7 @@ namespace Tgstation.Server.Tests.Live
preStartupTime = DateTimeOffset.UtcNow;
serverTask = server.Run(cancellationToken).AsTask();
long expectedCompileJobId, expectedStaged;
- var edgeByond = await ByondTest.GetEdgeVersion(fileDownloader, cancellationToken);
+ var edgeVersion = await ByondTest.GetEdgeVersion(engineType, fileDownloader, cancellationToken);
using (var adminClient = await CreateAdminClient(server.Url, cancellationToken))
{
var instanceClient = adminClient.Instances.CreateClient(instance);
@@ -1319,7 +1326,7 @@ namespace Tgstation.Server.Tests.Live
Assert.AreEqual(WatchdogStatus.Online, dd.Status.Value);
var compileJob = await instanceClient.DreamMaker.Compile(cancellationToken);
- var wdt = new WatchdogTest(edgeByond, instanceClient, GetInstanceManager(), (ushort)server.Url.Port, server.HighPriorityDreamDaemon, mainDDPort);
+ var wdt = new WatchdogTest(edgeVersion, instanceClient, GetInstanceManager(), (ushort)server.Url.Port, server.HighPriorityDreamDaemon, mainDDPort);
await wdt.WaitForJob(compileJob, 30, false, null, cancellationToken);
dd = await instanceClient.DreamDaemon.Read(cancellationToken);
@@ -1366,7 +1373,7 @@ namespace Tgstation.Server.Tests.Live
Assert.AreEqual(WatchdogStatus.Online, currentDD.Status);
Assert.AreEqual(expectedStaged, currentDD.StagedCompileJob.Job.Id.Value);
- var wdt = new WatchdogTest(edgeByond, instanceClient, GetInstanceManager(), (ushort)server.Url.Port, server.HighPriorityDreamDaemon, mainDDPort);
+ var wdt = new WatchdogTest(edgeVersion, instanceClient, GetInstanceManager(), (ushort)server.Url.Port, server.HighPriorityDreamDaemon, mainDDPort);
currentDD = await wdt.TellWorldToReboot(cancellationToken);
Assert.AreEqual(expectedStaged, currentDD.ActiveCompileJob.Job.Id.Value);
Assert.IsNull(currentDD.StagedCompileJob);
diff --git a/tests/Tgstation.Server.Tests/TestDatabase.cs b/tests/Tgstation.Server.Tests/TestDatabase.cs
index df8ffd5e4c..8d629bcfb6 100644
--- a/tests/Tgstation.Server.Tests/TestDatabase.cs
+++ b/tests/Tgstation.Server.Tests/TestDatabase.cs
@@ -134,7 +134,7 @@ namespace Tgstation.Server.Tests
{
new Host.Models.InstancePermissionSet
{
- ByondRights = ByondRights.InstallCustomVersion,
+ ByondRights = ByondRights.InstallCustomByondVersion,
ChatBotRights = ChatBotRights.None,
ConfigurationRights = ConfigurationRights.Read,
DreamDaemonRights = DreamDaemonRights.ReadRevision,
diff --git a/tests/Tgstation.Server.Tests/TestVersions.cs b/tests/Tgstation.Server.Tests/TestVersions.cs
index 41c48a1196..387438b687 100644
--- a/tests/Tgstation.Server.Tests/TestVersions.cs
+++ b/tests/Tgstation.Server.Tests/TestVersions.cs
@@ -28,6 +28,8 @@ using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.System;
using System.Net;
+using Tgstation.Server.Api.Models.Internal;
+using Tgstation.Server.Api.Models;
namespace Tgstation.Server.Tests
{
@@ -125,12 +127,18 @@ namespace Tgstation.Server.Tests
const string ArchiveEntryPath = "byond/bin/dd.exe";
var hasEntry = ArchiveHasFileEntry(
- await byondInstaller.DownloadVersion(WindowsByondInstaller.DDExeVersion, default),
+ await byondInstaller.DownloadVersion(
+ new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = WindowsByondInstaller.DDExeVersion
+ },
+ default),
ArchiveEntryPath);
Assert.IsTrue(hasEntry);
- var (byondBytes, version) = await GetByondVersionPriorTo(byondInstaller, WindowsByondInstaller.DDExeVersion);
+ var (byondBytes, _) = await GetByondVersionPriorTo(byondInstaller, WindowsByondInstaller.DDExeVersion);
hasEntry = ArchiveHasFileEntry(
byondBytes,
ArchiveEntryPath);
@@ -203,8 +211,18 @@ namespace Tgstation.Server.Tests
try
{
await TestMapThreadsVersion(
- ByondInstallerBase.MapThreadsVersion,
- await byondInstaller.DownloadVersion(ByondInstallerBase.MapThreadsVersion, default),
+ new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = ByondInstallerBase.MapThreadsVersion,
+ },
+ await byondInstaller.DownloadVersion(
+ new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = ByondInstallerBase.MapThreadsVersion
+ },
+ default),
byondInstaller,
ioManager,
processExecutor,
@@ -380,22 +398,32 @@ namespace Tgstation.Server.Tests
Assert.AreEqual(latestMigrationSL, DatabaseContext.SLLatestMigration);
}
- static async Task> GetByondVersionPriorTo(IByondInstaller byondInstaller, Version version)
+ static async Task> GetByondVersionPriorTo(IByondInstaller byondInstaller, Version version)
{
var minusOneMinor = new Version(version.Major, version.Minor - 1);
+ var byondVersion = new ByondVersion
+ {
+ Engine = EngineType.Byond,
+ Version = minusOneMinor
+ };
try
{
- return Tuple.Create(await byondInstaller.DownloadVersion(minusOneMinor, default), minusOneMinor);
+ return Tuple.Create(await byondInstaller.DownloadVersion(
+ byondVersion,
+ CancellationToken.None), byondVersion);
}
catch (HttpRequestException)
{
var minusOneMajor = new Version(minusOneMinor.Major - 1, minusOneMinor.Minor);
- return Tuple.Create(await byondInstaller.DownloadVersion(minusOneMajor, default), minusOneMajor);
+ byondVersion.Version = minusOneMajor;
+ return Tuple.Create(await byondInstaller.DownloadVersion(
+ byondVersion,
+ CancellationToken.None), byondVersion);
}
}
static async Task TestMapThreadsVersion(
- Version byondVersion,
+ ByondVersion byondVersion,
Stream byondBytes,
IByondInstaller byondInstaller,
IIOManager ioManager,