diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs
index 4d02e969b6..c8774659b6 100644
--- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs
+++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs
@@ -250,12 +250,21 @@ namespace Tgstation.Server.Host.Components
throw;
}
}
- #pragma warning restore CA1506
+#pragma warning restore CA1506
///
- public Task StartAsync(CancellationToken cancellationToken) => byondInstaller.CleanCache(cancellationToken);
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ CheckSystemCompatibility();
+ return byondInstaller.CleanCache(cancellationToken);
+ }
///
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+
+ ///
+ /// Test that the is functional.
+ ///
+ private void CheckSystemCompatibility() => repositoryFactory.CreateInMemory().Dispose();
}
}
diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs
index d9c45691d1..b0c15cacd8 100644
--- a/src/Tgstation.Server.Host/Components/InstanceManager.cs
+++ b/src/Tgstation.Server.Host/Components/InstanceManager.cs
@@ -10,6 +10,7 @@ using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.Database;
using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Jobs;
+using Tgstation.Server.Host.Security;
using Tgstation.Server.Host.System;
namespace Tgstation.Server.Host.Components
@@ -52,6 +53,11 @@ namespace Tgstation.Server.Host.Components
///
readonly IPlatformIdentifier platformIdentifier;
+ ///
+ /// The for the
+ ///
+ readonly ISystemIdentityFactory systemIdentityFactory;
+
///
/// The for the
///
@@ -82,6 +88,7 @@ namespace Tgstation.Server.Host.Components
/// The value of
/// The value of
/// The value of .
+ /// The value of .
/// The value of
public InstanceManager(
IInstanceFactory instanceFactory,
@@ -91,6 +98,7 @@ namespace Tgstation.Server.Host.Components
IJobManager jobManager,
IServerControl serverControl,
IPlatformIdentifier platformIdentifier,
+ ISystemIdentityFactory systemIdentityFactory,
ILogger logger)
{
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
@@ -100,6 +108,7 @@ namespace Tgstation.Server.Host.Components
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
+ this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
serverControl.RegisterForRestart(this);
@@ -228,7 +237,7 @@ namespace Tgstation.Server.Host.Components
{
try
{
- platformIdentifier.CheckCompatibility();
+ CheckSystemCompatibility();
var factoryStartup = instanceFactory.StartAsync(cancellationToken);
await databaseContext.Initialize(cancellationToken).ConfigureAwait(false);
await jobManager.StartAsync(cancellationToken).ConfigureAwait(false);
@@ -283,5 +292,15 @@ namespace Tgstation.Server.Host.Components
downgradeVersion = updateVersion != null && updateVersion < application.Version ? updateVersion : null;
return Task.CompletedTask;
}
+
+ ///
+ /// Check we have a valid system identity.
+ ///
+ private void CheckSystemCompatibility()
+ {
+ using var systemIdentity = systemIdentityFactory.GetCurrent();
+ if (!systemIdentity.CanCreateSymlinks)
+ throw new InvalidOperationException("The user running tgstation-server cannot create symlinks! Please try running as an administrative user!");
+ }
}
}
diff --git a/src/Tgstation.Server.Host/Components/Repository/Repository.cs b/src/Tgstation.Server.Host/Components/Repository/Repository.cs
index dd64bcdb19..d180d541d7 100644
--- a/src/Tgstation.Server.Host/Components/Repository/Repository.cs
+++ b/src/Tgstation.Server.Host/Components/Repository/Repository.cs
@@ -175,7 +175,7 @@ namespace Tgstation.Server.Host.Components.Repository
progressReporter(50 + ((int)(50 * ((float)sentBytes) / totalBytes)));
return !cancellationToken.IsCancellationRequested;
},
- CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
+ CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
};
///
@@ -262,7 +262,7 @@ namespace Tgstation.Server.Host.Components.Repository
return !cancellationToken.IsCancellationRequested;
},
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
- CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
+ CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
}, logMessage);
}
catch (UserCancelledException) { }
@@ -375,7 +375,7 @@ namespace Tgstation.Server.Host.Components.Repository
return !cancellationToken.IsCancellationRequested;
},
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
- CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
+ CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
}, "Fetch origin commits");
}
catch (UserCancelledException)
diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs
index f495a56693..06ce0f0f41 100644
--- a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs
+++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs
@@ -70,11 +70,12 @@ namespace Tgstation.Server.Host.Components.Repository
ILogger logger,
RepositorySettings repositorySettings)
{
- this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
+ this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
semaphore = new SemaphoreSlim(1);
}
diff --git a/src/Tgstation.Server.Host/System/IPlatformIdentifier.cs b/src/Tgstation.Server.Host/System/IPlatformIdentifier.cs
index b42b0a8a19..2036796994 100644
--- a/src/Tgstation.Server.Host/System/IPlatformIdentifier.cs
+++ b/src/Tgstation.Server.Host/System/IPlatformIdentifier.cs
@@ -14,10 +14,5 @@
/// The extension of executable script files for the system
///
string ScriptFileExtension { get; }
-
- ///
- /// Check if the system is capable of running tgstation-server.
- ///
- void CheckCompatibility();
}
}
diff --git a/src/Tgstation.Server.Host/System/PlatformIdentifier.cs b/src/Tgstation.Server.Host/System/PlatformIdentifier.cs
index 04c5ee01cb..c2ec1382aa 100644
--- a/src/Tgstation.Server.Host/System/PlatformIdentifier.cs
+++ b/src/Tgstation.Server.Host/System/PlatformIdentifier.cs
@@ -1,8 +1,4 @@
-using Microsoft.Extensions.Logging;
-using System;
-using System.Runtime.InteropServices;
-using Tgstation.Server.Host.Components.Repository;
-using Tgstation.Server.Host.Security;
+using System.Runtime.InteropServices;
namespace Tgstation.Server.Host.System
{
@@ -15,56 +11,13 @@ namespace Tgstation.Server.Host.System
///
public string ScriptFileExtension { get; }
- ///
- /// The for the .
- ///
- readonly ISystemIdentityFactory systemIdentityFactory;
-
- ///
- /// The for the .
- ///
- readonly IRepositoryFactory repositoryFactory;
-
- ///
- /// The for the .
- ///
- readonly ILogger logger;
-
///
/// Construct a
///
- /// The value of .
- /// The value of .
- /// The value of .
- public PlatformIdentifier(
- ISystemIdentityFactory systemIdentityFactory,
- IRepositoryFactory repositoryFactory,
- ILogger logger)
+ public PlatformIdentifier()
{
- this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
- this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
- this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
-
IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
ScriptFileExtension = IsWindows ? "bat" : "sh";
}
-
- ///
- public void CheckCompatibility()
- {
- try
- {
- repositoryFactory.CreateInMemory().Dispose();
- }
- catch
- {
- logger.LogCritical("Unable to initialize libgit2! This is a common problem on POSIX installations. Try using Docker.");
- throw;
- }
-
- using var systemIdentity = systemIdentityFactory.GetCurrent();
- if (!systemIdentity.CanCreateSymlinks)
- throw new InvalidOperationException("The user running tgstation-server cannot create symlinks! Please try running as an administrative user!");
- }
}
}
diff --git a/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs b/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs
new file mode 100644
index 0000000000..1434f24e0a
--- /dev/null
+++ b/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs
@@ -0,0 +1,91 @@
+using LibGit2Sharp;
+using Microsoft.Extensions.Logging;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace Tgstation.Server.Host.Components.Repository.Tests
+{
+ ///
+ /// Tests for .
+ ///
+ [TestClass]
+ public sealed class TestRepositoryFactory
+ {
+ static IRepositoryFactory CreateFactory() => new RepositoryFactory(Mock.Of>());
+
+ static Task TestRepoLoading(
+ string path,
+ IRepositoryFactory repositoryFactory = null) =>
+ (repositoryFactory ?? CreateFactory())
+ .CreateFromPath(path, default);
+
+ [TestMethod]
+ public void TestConstructionThrows() => Assert.ThrowsException(() => new RepositoryFactory(null));
+
+ [TestMethod]
+ public void TestInMemoryRepoCreation()
+ {
+ using var repo = new RepositoryFactory(Mock.Of>()).CreateInMemory();
+ }
+
+ [TestMethod]
+ public async Task TestLoadedRepoCreation()
+ {
+ using var repo = await TestRepoLoading(Path.GetFullPath("../../../../.."));
+
+ // Checking the commit previous to the one that creates this function exists
+ var gitObject = repo.Lookup("4802806bdccee27cb3d5fa8c2d0dfbdc117fdb4d");
+ Assert.IsNotNull(gitObject);
+ var commit = gitObject.Peel();
+
+ Assert.AreEqual("Cleanup repository management code", commit.Message.Trim());
+ }
+
+ [TestMethod]
+ public async Task TestCloning()
+ {
+ var tempDir = Path.GetTempFileName();
+ File.Delete(tempDir);
+ try
+ {
+ var factory = CreateFactory();
+ await factory.Clone(
+ new Uri("https://github.com/Cyberboss/Test"),
+ new CloneOptions
+ {
+ CredentialsProvider = factory.GenerateCredentialsHandler(null, null)
+ },
+ tempDir,
+ default);
+
+ using (var repo = await TestRepoLoading(tempDir))
+ {
+ var gitObject = repo.Lookup("f636418bf47d238d33b0e4a34f0072b23a8aad0e");
+ Assert.IsNotNull(gitObject);
+ var commit = gitObject.Peel();
+
+ Assert.AreEqual("Update Test.md", commit.Message);
+ }
+ }
+ finally
+ {
+ // Takes a while to release the repo handle sometimes...
+ for (var i = 0; i < 5; ++i)
+ {
+ try
+ {
+ Directory.Delete(tempDir, true);
+ break;
+ }
+ catch (UnauthorizedAccessException)
+ {
+ await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
+ }
+ }
+ }
+ }
+ }
+}