diff --git a/src/Tgstation.Server.Host/Components/InstanceFactory.cs b/src/Tgstation.Server.Host/Components/InstanceFactory.cs
index 41a91b5a25..4d02e969b6 100644
--- a/src/Tgstation.Server.Host/Components/InstanceFactory.cs
+++ b/src/Tgstation.Server.Host/Components/InstanceFactory.cs
@@ -91,11 +91,6 @@ namespace Tgstation.Server.Host.Components
///
readonly IJobManager jobManager;
- ///
- /// The for the
- ///
- readonly ICredentialsProvider credentialsProvider;
-
///
/// The for the
///
@@ -111,6 +106,11 @@ namespace Tgstation.Server.Host.Components
///
readonly IPlatformIdentifier platformIdentifier;
+ ///
+ /// The for the .
+ ///
+ readonly IRepositoryFactory repositoryFactory;
+
///
/// Construct an
///
@@ -128,10 +128,10 @@ namespace Tgstation.Server.Host.Components
/// The value of
/// The value of
/// The value of
- /// The value of
/// The value of
/// The value of
/// The value of
+ /// The value of .
public InstanceFactory(
IIOManager ioManager,
IDatabaseContextFactory databaseContextFactory,
@@ -147,10 +147,10 @@ namespace Tgstation.Server.Host.Components
IPostWriteHandler postWriteHandler,
IWatchdogFactory watchdogFactory,
IJobManager jobManager,
- ICredentialsProvider credentialsProvider,
INetworkPromptReaper networkPromptReaper,
IGitHubClientFactory gitHubClientFactory,
- IPlatformIdentifier platformIdentifier)
+ IPlatformIdentifier platformIdentifier,
+ IRepositoryFactory repositoryFactory)
{
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
@@ -166,10 +166,10 @@ namespace Tgstation.Server.Host.Components
this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
this.watchdogFactory = watchdogFactory ?? throw new ArgumentNullException(nameof(watchdogFactory));
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
- this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
+ this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
}
///
@@ -187,7 +187,13 @@ namespace Tgstation.Server.Host.Components
var configuration = new StaticFiles.Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, processExecutor, postWriteHandler, platformIdentifier, loggerFactory.CreateLogger());
var eventConsumer = new EventConsumer(configuration);
- var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager, eventConsumer, credentialsProvider, loggerFactory.CreateLogger(), loggerFactory.CreateLogger());
+ var repoManager = new RepositoryManager(
+ repositoryFactory,
+ repoIoManager,
+ eventConsumer,
+ loggerFactory.CreateLogger(),
+ loggerFactory.CreateLogger(),
+ metadata.RepositorySettings);
try
{
var byond = new ByondManager(byondIOManager, byondInstaller, eventConsumer, loggerFactory.CreateLogger());
diff --git a/src/Tgstation.Server.Host/Components/InstanceManager.cs b/src/Tgstation.Server.Host/Components/InstanceManager.cs
index 28fbc31558..d9c45691d1 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.System;
namespace Tgstation.Server.Host.Components
{
@@ -46,6 +47,11 @@ namespace Tgstation.Server.Host.Components
///
readonly IServerControl serverControl;
+ ///
+ /// The for the
+ ///
+ readonly IPlatformIdentifier platformIdentifier;
+
///
/// The for the
///
@@ -75,8 +81,17 @@ namespace Tgstation.Server.Host.Components
/// The value of
/// The value of
/// The value of
+ /// The value of .
/// The value of
- public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, IServerControl serverControl, ILogger logger)
+ public InstanceManager(
+ IInstanceFactory instanceFactory,
+ IIOManager ioManager,
+ IDatabaseContextFactory databaseContextFactory,
+ IApplication application,
+ IJobManager jobManager,
+ IServerControl serverControl,
+ IPlatformIdentifier platformIdentifier,
+ ILogger logger)
{
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
@@ -84,6 +99,7 @@ namespace Tgstation.Server.Host.Components
this.application = application ?? throw new ArgumentNullException(nameof(application));
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.logger = logger ?? throw new ArgumentNullException(nameof(logger));
serverControl.RegisterForRestart(this);
@@ -212,6 +228,7 @@ namespace Tgstation.Server.Host.Components
{
try
{
+ platformIdentifier.CheckCompatibility();
var factoryStartup = instanceFactory.StartAsync(cancellationToken);
await databaseContext.Initialize(cancellationToken).ConfigureAwait(false);
await jobManager.StartAsync(cancellationToken).ConfigureAwait(false);
diff --git a/src/Tgstation.Server.Host/Components/Repository/CredentialsProvider.cs b/src/Tgstation.Server.Host/Components/Repository/CredentialsProvider.cs
deleted file mode 100644
index 80112f3e47..0000000000
--- a/src/Tgstation.Server.Host/Components/Repository/CredentialsProvider.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using LibGit2Sharp;
-using LibGit2Sharp.Handlers;
-using Microsoft.Extensions.Logging;
-using System;
-using Tgstation.Server.Host.Jobs;
-
-namespace Tgstation.Server.Host.Components.Repository
-{
- ///
- sealed class CredentialsProvider : ICredentialsProvider
- {
- ///
- /// The for the
- ///
- readonly ILogger logger;
-
- ///
- /// Construct a
- ///
- /// The value of
- public CredentialsProvider(ILogger logger)
- {
- this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
- }
-
- ///
- public CredentialsHandler GenerateHandler(string username, string password) => (a, b, supportedCredentialTypes) =>
- {
- var hasCreds = username != null;
- var supportsUserPass = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.UsernamePassword);
- var supportsAnonymous = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.Default);
-
- logger.LogTrace("Credentials requested. Present: {0}. Supports anonymous: {1}. Supports user/pass: {2}", hasCreds, supportsAnonymous, supportsUserPass);
- if (supportsUserPass)
- {
- if (hasCreds)
- return new UsernamePasswordCredentials
- {
- Username = username,
- Password = password
- };
- }
-
- if (supportsAnonymous)
- return new DefaultCredentials();
-
- if (hasCreds)
- throw new JobException("Remote does not support anonymous authentication!");
-
- throw new JobException("Server does not support anonymous or username/password authentication!");
- };
- }
-}
diff --git a/src/Tgstation.Server.Host/Components/Repository/ICredentialsProvider.cs b/src/Tgstation.Server.Host/Components/Repository/ICredentialsProvider.cs
index c130b02a78..496a015187 100644
--- a/src/Tgstation.Server.Host/Components/Repository/ICredentialsProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Repository/ICredentialsProvider.cs
@@ -13,6 +13,6 @@ namespace Tgstation.Server.Host.Components.Repository
/// The optional username to use in the
/// The optional password to use in the
/// A new
- CredentialsHandler GenerateHandler(string username, string password);
+ CredentialsHandler GenerateCredentialsHandler(string username, string password);
}
}
\ No newline at end of file
diff --git a/src/Tgstation.Server.Host/Components/Repository/IRepositoryFactory.cs b/src/Tgstation.Server.Host/Components/Repository/IRepositoryFactory.cs
new file mode 100644
index 0000000000..a4e7d2b4c3
--- /dev/null
+++ b/src/Tgstation.Server.Host/Components/Repository/IRepositoryFactory.cs
@@ -0,0 +1,36 @@
+using LibGit2Sharp;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Tgstation.Server.Host.Components.Repository
+{
+ ///
+ /// Factory for creating s.
+ ///
+ interface IRepositoryFactory : ICredentialsProvider
+ {
+ ///
+ /// Create an in-memeory .
+ ///
+ /// A new in-memory .
+ LibGit2Sharp.IRepository CreateInMemory();
+
+ ///
+ /// Load a from a given .
+ ///
+ /// The full path to the .
+ /// The loaded .
+ LibGit2Sharp.IRepository CreateFromPath(string path);
+
+ ///
+ /// Clone a remote .
+ ///
+ /// The of the remote.
+ /// The .
+ /// The full path to the cloned .
+ /// The for the operation.
+ /// A representing the running operation.
+ Task Clone(Uri url, CloneOptions cloneOptions, string path, CancellationToken cancellationToken);
+ }
+}
\ No newline at end of file
diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryFactory.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryFactory.cs
new file mode 100644
index 0000000000..f687a75c33
--- /dev/null
+++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryFactory.cs
@@ -0,0 +1,84 @@
+using LibGit2Sharp;
+using LibGit2Sharp.Handlers;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Tgstation.Server.Host.Jobs;
+
+namespace Tgstation.Server.Host.Components.Repository
+{
+ ///
+ sealed class RepositoryFactory : IRepositoryFactory
+ {
+ ///
+ /// The for the .
+ ///
+ readonly ILogger logger;
+
+ ///
+ /// Initializes a new instance of the .
+ ///
+ /// The value of .
+ public RepositoryFactory(ILogger logger)
+ {
+ this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ ///
+ public LibGit2Sharp.IRepository CreateInMemory()
+ {
+ logger.LogTrace("Creating in-memory LibGit2Sharp...");
+ return new LibGit2Sharp.Repository();
+ }
+
+ ///
+ public LibGit2Sharp.IRepository CreateFromPath(string path)
+ {
+ if (path == null)
+ throw new ArgumentNullException(nameof(path));
+ logger.LogTrace("Creating LibGit2Sharp Repostory at {0}...", path);
+ return new LibGit2Sharp.Repository(path);
+ }
+
+ ///
+ public Task Clone(Uri url, CloneOptions cloneOptions, string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
+ {
+ try
+ {
+ LibGit2Sharp.Repository.Clone(url.ToString(), path, cloneOptions);
+ }
+ catch (UserCancelledException)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+ }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
+
+ ///
+ public CredentialsHandler GenerateCredentialsHandler(string username, string password) => (a, b, supportedCredentialTypes) =>
+ {
+ var hasCreds = username != null;
+ var supportsUserPass = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.UsernamePassword);
+ var supportsAnonymous = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.Default);
+
+ logger.LogTrace("Credentials requested. Present: {0}. Supports anonymous: {1}. Supports user/pass: {2}", hasCreds, supportsAnonymous, supportsUserPass);
+ if (supportsUserPass)
+ {
+ if (hasCreds)
+ return new UsernamePasswordCredentials
+ {
+ Username = username,
+ Password = password
+ };
+ }
+
+ if (supportsAnonymous)
+ return new DefaultCredentials();
+
+ if (hasCreds)
+ throw new JobException("Remote does not support anonymous authentication!");
+
+ throw new JobException("Server does not support anonymous or username/password authentication!");
+ };
+ }
+}
diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs
index 4feeb46897..f198ad0b4b 100644
--- a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs
+++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs
@@ -18,6 +18,11 @@ namespace Tgstation.Server.Host.Components.Repository
///
public bool CloneInProgress { get; private set; }
+ ///
+ /// The for the
+ ///
+ readonly IRepositoryFactory repositoryFactory;
+
///
/// The for the
///
@@ -28,11 +33,6 @@ namespace Tgstation.Server.Host.Components.Repository
///
readonly IEventConsumer eventConsumer;
- ///
- /// The for the
- ///
- readonly ICredentialsProvider credentialsProvider;
-
///
/// The created s
///
@@ -56,18 +56,23 @@ namespace Tgstation.Server.Host.Components.Repository
///
/// Construct a
///
- /// The value of
+ /// The value of .
/// The value of
/// The value of
- /// The value of
/// The value of
/// The value of
- public RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger repositoryLogger, ILogger logger)
+ /// The value of
+ public RepositoryManager(
+ IRepositoryFactory repositoryFactory,
+ IIOManager ioManager,
+ IEventConsumer eventConsumer,
+ ILogger repositoryLogger,
+ ILogger logger,
+ RepositorySettings repositorySettings)
{
this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
- this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
semaphore = new SemaphoreSlim(1);
@@ -104,30 +109,28 @@ namespace Tgstation.Server.Host.Components.Repository
if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false))
try
{
- await Task.Factory.StartNew(() =>
+ var cloneOptions = new CloneOptions
{
- string path = null;
- try
+ OnProgress = (a) => !cancellationToken.IsCancellationRequested,
+ OnTransferProgress = (a) =>
{
- path = LibGit2Sharp.Repository.Clone(url.ToString(), ioManager.ResolvePath("."), new CloneOptions
- {
- OnProgress = (a) => !cancellationToken.IsCancellationRequested,
- OnTransferProgress = (a) =>
- {
- var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
- progressReporter((int)percentage);
- return !cancellationToken.IsCancellationRequested;
- },
- RecurseSubmodules = true,
- OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
- RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
- BranchName = initialBranch,
- CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
- });
- }
- catch (UserCancelledException) { }
- cancellationToken.ThrowIfCancellationRequested();
- }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
+ var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
+ progressReporter((int)percentage);
+ return !cancellationToken.IsCancellationRequested;
+ },
+ RecurseSubmodules = true,
+ OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
+ RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
+ BranchName = initialBranch,
+ CredentialsProvider = repositoryFactory.GenerateCredentialsHandler(username, password)
+ };
+
+ await repositoryFactory.Clone(
+ url,
+ cloneOptions,
+ ioManager.ResolvePath("."),
+ cancellationToken)
+ .ConfigureAwait(false);
}
catch
{
@@ -168,13 +171,13 @@ namespace Tgstation.Server.Host.Components.Repository
if (CloneInProgress)
throw new InvalidOperationException("The repository is being cloned!");
await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
- LibGit2Sharp.Repository repo = null;
+ LibGit2Sharp.IRepository repo = null;
await Task.Factory.StartNew(() =>
{
try
{
logger.LogTrace("Creating LibGit2Sharp.Repository...");
- repo = new LibGit2Sharp.Repository(ioManager.ResolvePath("."));
+ repo = repositoryFactory.CreateFromPath(ioManager.ResolvePath("."));
}
catch (RepositoryNotFoundException e)
{
@@ -193,7 +196,7 @@ namespace Tgstation.Server.Host.Components.Repository
return null;
}
- return new Repository(repo, ioManager, eventConsumer, credentialsProvider, repositoryLogger, () =>
+ return new Repository(repo, ioManager, eventConsumer, repositoryFactory, repositoryLogger, () =>
{
logger.LogTrace("Releasing semaphore due to Repository disposal...");
semaphore.Release();
diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs
index bb372eae36..55021ccf9f 100644
--- a/src/Tgstation.Server.Host/Core/Application.cs
+++ b/src/Tgstation.Server.Host/Core/Application.cs
@@ -347,7 +347,7 @@ namespace Tgstation.Server.Host.Core
});
// configure component services
- services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
diff --git a/src/Tgstation.Server.Host/System/PlatformIdentifier.cs b/src/Tgstation.Server.Host/System/PlatformIdentifier.cs
index e0fe08363d..04c5ee01cb 100644
--- a/src/Tgstation.Server.Host/System/PlatformIdentifier.cs
+++ b/src/Tgstation.Server.Host/System/PlatformIdentifier.cs
@@ -1,7 +1,7 @@
-using LibGit2Sharp;
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging;
using System;
using System.Runtime.InteropServices;
+using Tgstation.Server.Host.Components.Repository;
using Tgstation.Server.Host.Security;
namespace Tgstation.Server.Host.System
@@ -20,6 +20,11 @@ namespace Tgstation.Server.Host.System
///
readonly ISystemIdentityFactory systemIdentityFactory;
+ ///
+ /// The for the .
+ ///
+ readonly IRepositoryFactory repositoryFactory;
+
///
/// The for the .
///
@@ -28,11 +33,16 @@ namespace Tgstation.Server.Host.System
///
/// Construct a
///
- /// The value of .
+ /// The value of .
+ /// The value of .
/// The value of .
- public PlatformIdentifier(ISystemIdentityFactory systemIdentityFactory, ILogger logger)
+ public PlatformIdentifier(
+ ISystemIdentityFactory systemIdentityFactory,
+ IRepositoryFactory repositoryFactory,
+ ILogger logger)
{
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);
@@ -44,7 +54,7 @@ namespace Tgstation.Server.Host.System
{
try
{
- new Repository().Dispose();
+ repositoryFactory.CreateInMemory().Dispose();
}
catch
{