mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-07-14 09:33:22 +01:00
Code cleanup for libgit2 interop
This commit is contained in:
@@ -108,9 +108,14 @@ namespace Tgstation.Server.Host.Components
|
||||
readonly IPlatformIdentifier platformIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRepositoryFactory"/> for the <see cref="InstanceFactory"/>.
|
||||
/// The <see cref="ILibGit2RepositoryFactory"/> for the <see cref="InstanceFactory"/>.
|
||||
/// </summary>
|
||||
readonly IRepositoryFactory repositoryFactory;
|
||||
readonly ILibGit2RepositoryFactory repositoryFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILibGit2Commands"/> for the <see cref="InstanceFactory"/>.
|
||||
/// </summary>
|
||||
readonly ILibGit2Commands repositoryCommands;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IServerPortProvider"/> for the <see cref="InstanceFactory"/>.
|
||||
@@ -138,6 +143,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/></param>
|
||||
/// <param name="platformIdentifier">The value of <see cref="platformIdentifier"/></param>
|
||||
/// <param name="repositoryFactory">The value of <see cref="repositoryFactory"/>.</param>
|
||||
/// <param name="repositoryCommands">The value of <see cref="repositoryCommands"/>.</param>
|
||||
/// <param name="serverPortProvider">The value of <see cref="serverPortProvider"/>.</param>
|
||||
public InstanceFactory(
|
||||
IIOManager ioManager,
|
||||
@@ -157,7 +163,8 @@ namespace Tgstation.Server.Host.Components
|
||||
INetworkPromptReaper networkPromptReaper,
|
||||
IGitHubClientFactory gitHubClientFactory,
|
||||
IPlatformIdentifier platformIdentifier,
|
||||
IRepositoryFactory repositoryFactory,
|
||||
ILibGit2RepositoryFactory repositoryFactory,
|
||||
ILibGit2Commands repositoryCommands,
|
||||
IServerPortProvider serverPortProvider)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
@@ -178,6 +185,7 @@ namespace Tgstation.Server.Host.Components
|
||||
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
|
||||
this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
|
||||
this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
|
||||
this.repositoryCommands = repositoryCommands ?? throw new ArgumentNullException(nameof(repositoryCommands));
|
||||
this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
|
||||
}
|
||||
|
||||
@@ -198,6 +206,7 @@ namespace Tgstation.Server.Host.Components
|
||||
var eventConsumer = new EventConsumer(configuration);
|
||||
var repoManager = new RepositoryManager(
|
||||
repositoryFactory,
|
||||
repositoryCommands,
|
||||
repoIoManager,
|
||||
eventConsumer,
|
||||
loggerFactory.CreateLogger<Repository.Repository>(),
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using LibGit2Sharp;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <summary>
|
||||
/// For low level interactions with a <see cref="LibGit2Sharp.IRepository"/>.
|
||||
/// </summary>
|
||||
interface ILibGit2Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs a blocking fetch operation on a given <paramref name="repository"/>.
|
||||
/// </summary>
|
||||
/// <param name="repository">The <see cref="IRepository"/> to fetch with.</param>
|
||||
/// <param name="refSpecs">The refspecs to fetch.</param>
|
||||
/// <param name="remote">The <see cref="Remote"/> to fetch.</param>
|
||||
/// <param name="fetchOptions">The <see cref="FetchOptions"/>.</param>
|
||||
/// <param name="logMessage">The message to write in the git log.</param>
|
||||
void Fetch(LibGit2Sharp.IRepository repository, IEnumerable<string> refSpecs, Remote remote, FetchOptions fetchOptions, string logMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Runs a blocking checkout operation on a given <paramref name="repository"/>.
|
||||
/// </summary>
|
||||
/// <param name="repository">The <see cref="IRepository"/> to checkout with.</param>
|
||||
/// <param name="checkoutOptions">The <see cref="CheckoutOptions"/>.</param>
|
||||
/// <param name="commitish">The git object to checkout.</param>
|
||||
void Checkout(LibGit2Sharp.IRepository repository, CheckoutOptions checkoutOptions, string commitish);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -8,7 +8,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <summary>
|
||||
/// Factory for creating <see cref="LibGit2Sharp.IRepository"/>s.
|
||||
/// </summary>
|
||||
interface IRepositoryFactory : ICredentialsProvider
|
||||
interface ILibGit2RepositoryFactory : ICredentialsProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an in-memeory <see cref="LibGit2Sharp.IRepository"/>.
|
||||
@@ -0,0 +1,34 @@
|
||||
using LibGit2Sharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class LibGit2Commands : ILibGit2Commands
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void Checkout(LibGit2Sharp.IRepository libGit2Repo, CheckoutOptions checkoutOptions, string commitish)
|
||||
=> Commands.Checkout(libGit2Repo, commitish, checkoutOptions);
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Fetch(
|
||||
LibGit2Sharp.IRepository libGit2Repo,
|
||||
IEnumerable<string> refSpecs,
|
||||
Remote remote,
|
||||
FetchOptions fetchOptions,
|
||||
string logMessage)
|
||||
{
|
||||
if (libGit2Repo == null)
|
||||
throw new ArgumentNullException(nameof(libGit2Repo));
|
||||
|
||||
if (!(libGit2Repo is LibGit2Sharp.Repository concreteRepo))
|
||||
throw new ArgumentException("libGit2Repo must be an instance of LibGit2Sharp.Repository!", nameof(libGit2Repo));
|
||||
|
||||
if (remote == null)
|
||||
throw new ArgumentNullException(nameof(remote));
|
||||
|
||||
Commands.Fetch(concreteRepo, remote.Name, refSpecs, fetchOptions, logMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
-10
@@ -9,18 +9,18 @@ using Tgstation.Server.Host.Jobs;
|
||||
namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class RepositoryFactory : IRepositoryFactory
|
||||
sealed class LibGit2RepositoryFactory : ILibGit2RepositoryFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="RepositoryFactory"/>.
|
||||
/// The <see cref="ILogger"/> for the <see cref="LibGit2RepositoryFactory"/>.
|
||||
/// </summary>
|
||||
readonly ILogger<RepositoryFactory> logger;
|
||||
readonly ILogger<LibGit2RepositoryFactory> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RepositoryFactory"/> <see langword="class"/>.
|
||||
/// Initializes a new instance of the <see cref="LibGit2RepositoryFactory"/> <see langword="class"/>.
|
||||
/// </summary>
|
||||
/// <param name="logger">The value of <see cref="logger"/>.</param>
|
||||
public RepositoryFactory(ILogger<RepositoryFactory> logger)
|
||||
public LibGit2RepositoryFactory(ILogger<LibGit2RepositoryFactory> logger)
|
||||
{
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
@@ -28,8 +28,18 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <inheritdoc />
|
||||
public LibGit2Sharp.IRepository CreateInMemory()
|
||||
{
|
||||
logger.LogTrace("Creating in-memory repository...");
|
||||
return new LibGit2Sharp.Repository();
|
||||
logger.LogTrace("Creating in-memory libgit2 repository...");
|
||||
var repo = new LibGit2Sharp.Repository();
|
||||
try
|
||||
{
|
||||
logger.LogTrace("Successfully created in-memory libgit2 repository.");
|
||||
return repo;
|
||||
}
|
||||
catch
|
||||
{
|
||||
repo.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -37,9 +47,13 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
logger.LogTrace("Creating repostory at {0}...", path);
|
||||
return Task.Factory.StartNew(
|
||||
() => (LibGit2Sharp.IRepository)new LibGit2Sharp.Repository(path),
|
||||
|
||||
return Task.Factory.StartNew<LibGit2Sharp.IRepository>(
|
||||
() =>
|
||||
{
|
||||
logger.LogTrace("Creating libgit2 repostory at {0}...", path);
|
||||
return new LibGit2Sharp.Repository(path);
|
||||
},
|
||||
cancellationToken,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Current);
|
||||
@@ -43,21 +43,26 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
public string GitHubRepoName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Tracking => Reference != null && repository.Head.IsTracking;
|
||||
public bool Tracking => Reference != null && libGitRepo.Head.IsTracking;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Head => repository.Head.Tip.Sha;
|
||||
public string Head => libGitRepo.Head.Tip.Sha;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Reference => repository.Head.FriendlyName;
|
||||
public string Reference => libGitRepo.Head.FriendlyName;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Origin => repository.Network.Remotes.First().Url;
|
||||
public string Origin => libGitRepo.Network.Remotes.First().Url;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LibGit2Sharp.IRepository"/> for the <see cref="Repository"/>
|
||||
/// </summary>
|
||||
readonly LibGit2Sharp.IRepository repository;
|
||||
readonly LibGit2Sharp.IRepository libGitRepo;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILibGit2Commands"/> for the <see cref="Repository"/>.
|
||||
/// </summary>
|
||||
readonly ILibGit2Commands commands;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="Repository"/>
|
||||
@@ -99,21 +104,32 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// <summary>
|
||||
/// Construct a <see cref="Repository"/>
|
||||
/// </summary>
|
||||
/// <param name="repository">The value of <see cref="repository"/></param>
|
||||
/// <param name="libGitRepo">The value of <see cref="libGitRepo"/></param>
|
||||
/// <param name="commands">The value of <see cref="commands"/>.</param>
|
||||
/// <param name="ioMananger">The value of <see cref="ioMananger"/></param>
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
/// <param name="credentialsProvider">The value of <see cref="credentialsProvider"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
/// <param name="onDispose">The value if <see cref="onDispose"/></param>
|
||||
public Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger<Repository> logger, Action onDispose)
|
||||
public Repository(
|
||||
LibGit2Sharp.IRepository libGitRepo,
|
||||
ILibGit2Commands commands,
|
||||
IIOManager ioMananger,
|
||||
IEventConsumer eventConsumer,
|
||||
ICredentialsProvider credentialsProvider,
|
||||
ILogger<Repository> logger,
|
||||
Action onDispose)
|
||||
{
|
||||
this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
|
||||
this.libGitRepo = libGitRepo ?? throw new ArgumentNullException(nameof(libGitRepo));
|
||||
this.commands = commands ?? throw new ArgumentNullException(nameof(commands));
|
||||
this.ioMananger = ioMananger ?? throw new ArgumentNullException(nameof(ioMananger));
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
|
||||
|
||||
IsGitHubRepository = Origin.Contains(GitHubUrl, StringComparison.InvariantCultureIgnoreCase);
|
||||
|
||||
if (IsGitHubRepository)
|
||||
{
|
||||
GetRepositoryOwnerName(Origin, out var owner, out var name);
|
||||
@@ -134,7 +150,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
|
||||
logger.LogTrace("Disposing...");
|
||||
repository.Dispose();
|
||||
libGitRepo.Dispose();
|
||||
onDispose();
|
||||
}
|
||||
|
||||
@@ -191,15 +207,18 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
progressReporter(0);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
Commands.Checkout(repository, committish, new CheckoutOptions
|
||||
{
|
||||
CheckoutModifiers = CheckoutModifiers.Force,
|
||||
OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
|
||||
});
|
||||
commands.Checkout(
|
||||
libGitRepo,
|
||||
new CheckoutOptions
|
||||
{
|
||||
CheckoutModifiers = CheckoutModifiers.Force,
|
||||
OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
|
||||
},
|
||||
committish);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -248,7 +267,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
var refSpecList = new List<string> { refSpec };
|
||||
var logMessage = String.Format(CultureInfo.InvariantCulture, "Merge remote pull request #{0}", testMergeParameters.Number);
|
||||
|
||||
var originalCommit = repository.Head;
|
||||
var originalCommit = libGitRepo.Head;
|
||||
|
||||
MergeResult result = null;
|
||||
|
||||
@@ -261,37 +280,42 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
{
|
||||
logger.LogTrace("Fetching refspec {0}...", refSpec);
|
||||
|
||||
var remote = repository.Network.Remotes.First();
|
||||
var remote = libGitRepo.Network.Remotes.First();
|
||||
progressReporter(0);
|
||||
Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, refSpecList, new FetchOptions
|
||||
{
|
||||
Prune = true,
|
||||
OnProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnTransferProgress = (a) =>
|
||||
commands.Fetch(
|
||||
libGitRepo,
|
||||
refSpecList,
|
||||
remote,
|
||||
new FetchOptions
|
||||
{
|
||||
var percentage = 50 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
|
||||
progressReporter((int)percentage);
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
Prune = true,
|
||||
OnProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
OnTransferProgress = (a) =>
|
||||
{
|
||||
var percentage = 50 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
|
||||
progressReporter((int)percentage);
|
||||
return !cancellationToken.IsCancellationRequested;
|
||||
},
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
|
||||
},
|
||||
OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
|
||||
CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password)
|
||||
}, logMessage);
|
||||
logMessage);
|
||||
}
|
||||
catch (UserCancelledException) { }
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
testMergeParameters.PullRequestRevision = repository.Lookup(testMergeParameters.PullRequestRevision ?? localBranchName).Sha;
|
||||
testMergeParameters.PullRequestRevision = libGitRepo.Lookup(testMergeParameters.PullRequestRevision ?? localBranchName).Sha;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
logger.LogTrace("Merging {0} into {1}...", testMergeParameters.PullRequestRevision.Substring(0, 7), Reference);
|
||||
|
||||
result = repository.Merge(testMergeParameters.PullRequestRevision, sig, new MergeOptions
|
||||
result = libGitRepo.Merge(testMergeParameters.PullRequestRevision, sig, new MergeOptions
|
||||
{
|
||||
CommitOnSuccess = commitMessage == null,
|
||||
FailOnConflict = true,
|
||||
@@ -302,7 +326,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
finally
|
||||
{
|
||||
repository.Branches.Remove(localBranchName);
|
||||
libGitRepo.Branches.Remove(localBranchName);
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -315,7 +339,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
|
||||
if (result.Status == MergeStatus.Conflicts)
|
||||
@@ -327,7 +351,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
if (commitMessage != null && result.Status != MergeStatus.UpToDate)
|
||||
{
|
||||
logger.LogTrace("Committing merge: \"{0}\"...", commitMessage);
|
||||
await Task.Factory.StartNew(() => repository.Commit(commitMessage, sig, sig, new CommitOptions
|
||||
await Task.Factory.StartNew(() => libGitRepo.Commit(commitMessage, sig, sig, new CommitOptions
|
||||
{
|
||||
PrettifyMessage = true
|
||||
}), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
@@ -359,7 +383,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
await eventConsumer.HandleEvent(EventType.RepoCheckout, new List<string> { committish }, cancellationToken).ConfigureAwait(false);
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
RawCheckout(committish, progressReporter, cancellationToken);
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
}
|
||||
@@ -373,10 +397,10 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
await eventConsumer.HandleEvent(EventType.RepoFetch, Array.Empty<string>(), cancellationToken).ConfigureAwait(false);
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
var remote = repository.Network.Remotes.First();
|
||||
var remote = libGitRepo.Network.Remotes.First();
|
||||
try
|
||||
{
|
||||
Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, remote.FetchRefSpecs.Select(x => x.Specification), new FetchOptions
|
||||
Commands.Fetch((LibGit2Sharp.Repository)libGitRepo, remote.Name, remote.FetchRefSpecs.Select(x => x.Specification), new FetchOptions
|
||||
{
|
||||
Prune = true,
|
||||
OnProgress = (a) => !cancellationToken.IsCancellationRequested,
|
||||
@@ -408,17 +432,17 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
Task PushHeadToTemporaryBranch(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
|
||||
{
|
||||
logger.LogInformation("Pushing changes to temporary remote branch...");
|
||||
var branch = repository.CreateBranch(RemoteTemporaryBranchName);
|
||||
var branch = libGitRepo.CreateBranch(RemoteTemporaryBranchName);
|
||||
try
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var remote = repository.Network.Remotes.First();
|
||||
var remote = libGitRepo.Network.Remotes.First();
|
||||
try
|
||||
{
|
||||
var forcePushString = String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName);
|
||||
repository.Network.Push(remote, forcePushString, GeneratePushOptions(progress => progressReporter((int)(0.9f * progress)), username, password, cancellationToken));
|
||||
libGitRepo.Network.Push(remote, forcePushString, GeneratePushOptions(progress => progressReporter((int)(0.9f * progress)), username, password, cancellationToken));
|
||||
var removalString = String.Format(CultureInfo.InvariantCulture, ":{0}", branch.CanonicalName);
|
||||
repository.Network.Push(remote, removalString, GeneratePushOptions(progress => progressReporter(90 + (int)(0.1f * progress)), username, password, cancellationToken));
|
||||
libGitRepo.Network.Push(remote, removalString, GeneratePushOptions(progress => progressReporter(90 + (int)(0.1f * progress)), username, password, cancellationToken));
|
||||
}
|
||||
catch (UserCancelledException)
|
||||
{
|
||||
@@ -431,7 +455,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
}
|
||||
finally
|
||||
{
|
||||
repository.Branches.Remove(branch);
|
||||
libGitRepo.Branches.Remove(branch);
|
||||
}
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
|
||||
|
||||
@@ -443,7 +467,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
if (!Tracking)
|
||||
throw new JobException("Cannot reset to origin while not on a tracked reference!");
|
||||
logger.LogTrace("Reset to origin...");
|
||||
var trackedBranch = repository.Head.TrackedBranch;
|
||||
var trackedBranch = libGitRepo.Head.TrackedBranch;
|
||||
await eventConsumer.HandleEvent(EventType.RepoResetOrigin, new List<string> { trackedBranch.FriendlyName, trackedBranch.Tip.Sha }, cancellationToken).ConfigureAwait(false);
|
||||
await ResetToSha(trackedBranch.Tip.Sha, progressReporter, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
@@ -458,16 +482,16 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
|
||||
logger.LogDebug("Reset to sha: {0}", sha.Substring(0, 7));
|
||||
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
var gitObject = repository.Lookup(sha, ObjectType.Commit);
|
||||
var gitObject = libGitRepo.Lookup(sha, ObjectType.Commit);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (gitObject == null)
|
||||
throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot reset to non-existent SHA: {0}", sha));
|
||||
|
||||
repository.Reset(ResetMode.Hard, gitObject.Peel<Commit>(), new CheckoutOptions
|
||||
libGitRepo.Reset(ResetMode.Hard, gitObject.Peel<Commit>(), new CheckoutOptions
|
||||
{
|
||||
OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
|
||||
});
|
||||
@@ -491,7 +515,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
MergeResult result = null;
|
||||
Branch trackedBranch = null;
|
||||
|
||||
var oldHead = repository.Head;
|
||||
var oldHead = libGitRepo.Head;
|
||||
var oldTip = oldHead.Tip;
|
||||
|
||||
await Task.Factory.StartNew(() =>
|
||||
@@ -499,13 +523,13 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
if (!Tracking)
|
||||
throw new JobException("Cannot reset to origin while not on a tracked reference!");
|
||||
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
trackedBranch = repository.Head.TrackedBranch;
|
||||
trackedBranch = libGitRepo.Head.TrackedBranch;
|
||||
logger.LogDebug("Merge origin/{2}: <{0} ({1})>", committerName, committerEmail, trackedBranch.FriendlyName);
|
||||
result = repository.Merge(trackedBranch, new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now), new MergeOptions
|
||||
result = libGitRepo.Merge(trackedBranch, new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now), new MergeOptions
|
||||
{
|
||||
CommitOnSuccess = true,
|
||||
FailOnConflict = true,
|
||||
@@ -519,14 +543,14 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
if (result.Status == MergeStatus.Conflicts)
|
||||
{
|
||||
logger.LogDebug("Merge conflict, aborting and reverting to {0}", oldHead.FriendlyName);
|
||||
repository.Reset(ResetMode.Hard, oldTip, new CheckoutOptions
|
||||
libGitRepo.Reset(ResetMode.Hard, oldTip, new CheckoutOptions
|
||||
{
|
||||
OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
|
||||
});
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
|
||||
if (result.Status == MergeStatus.Conflicts)
|
||||
@@ -566,9 +590,9 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
logger.LogTrace("Configuring <{0} ({1})> as author/committer", committerName, committerEmail);
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
repository.Config.Set("user.name", committerName);
|
||||
libGitRepo.Config.Set("user.name", committerName);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
repository.Config.Set("user.email", committerEmail);
|
||||
libGitRepo.Config.Set("user.email", committerEmail);
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
@@ -592,9 +616,9 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
logger.LogTrace("Resetting and cleaning untracked files...");
|
||||
await Task.Factory.StartNew(() =>
|
||||
{
|
||||
repository.RemoveUntrackedFiles();
|
||||
libGitRepo.RemoveUntrackedFiles();
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
repository.Reset(ResetMode.Hard, repository.Head.Tip, new CheckoutOptions
|
||||
libGitRepo.Reset(ResetMode.Hard, libGitRepo.Head.Tip, new CheckoutOptions
|
||||
{
|
||||
OnCheckoutProgress = CheckoutProgressHandler(progress => progressReporter(progress / 10))
|
||||
});
|
||||
@@ -620,10 +644,10 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
|
||||
return await Task.Factory.StartNew(() =>
|
||||
{
|
||||
var remote = repository.Network.Remotes.First();
|
||||
var remote = libGitRepo.Network.Remotes.First();
|
||||
try
|
||||
{
|
||||
repository.Network.Push(repository.Head, GeneratePushOptions(FinalReporter, username, password, cancellationToken));
|
||||
libGitRepo.Network.Push(libGitRepo.Head, GeneratePushOptions(FinalReporter, username, password, cancellationToken));
|
||||
return true;
|
||||
}
|
||||
catch (NonFastForwardException)
|
||||
@@ -648,18 +672,18 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
public Task<bool> IsSha(string committish, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
|
||||
{
|
||||
// check if it's a tag
|
||||
var gitObject = repository.Lookup(committish, ObjectType.Tag);
|
||||
var gitObject = libGitRepo.Lookup(committish, ObjectType.Tag);
|
||||
if (gitObject != null)
|
||||
return false;
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// check if it's a branch
|
||||
if (repository.Branches[committish] != null)
|
||||
if (libGitRepo.Branches[committish] != null)
|
||||
return false;
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// err on the side of references, if we can't look it up, assume its a reference
|
||||
if (repository.Lookup<Commit>(committish) != null)
|
||||
if (libGitRepo.Lookup<Commit>(committish) != null)
|
||||
return true;
|
||||
return false;
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
|
||||
|
||||
@@ -19,9 +19,14 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
public bool CloneInProgress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRepositoryFactory"/> for the <see cref="RepositoryManager"/>
|
||||
/// The <see cref="ILibGit2RepositoryFactory"/> for the <see cref="RepositoryManager"/>
|
||||
/// </summary>
|
||||
readonly IRepositoryFactory repositoryFactory;
|
||||
readonly ILibGit2RepositoryFactory repositoryFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILibGit2Commands"/> for the <see cref="RepositoryManager"/>.
|
||||
/// </summary>
|
||||
readonly ILibGit2Commands commands;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="RepositoryManager"/>
|
||||
@@ -57,13 +62,15 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
/// Construct a <see cref="RepositoryManager"/>
|
||||
/// </summary>
|
||||
/// <param name="repositoryFactory">The value of <see cref="repositoryFactory"/>.</param>
|
||||
/// <param name="commands">The value of <see cref="commands"/>.</param>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
/// <param name="repositoryLogger">The value of <see cref="repositoryLogger"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
/// <param name="repositorySettings">The value of <see cref="repositorySettings"/></param>
|
||||
public RepositoryManager(
|
||||
IRepositoryFactory repositoryFactory,
|
||||
ILibGit2RepositoryFactory repositoryFactory,
|
||||
ILibGit2Commands commands,
|
||||
IIOManager ioManager,
|
||||
IEventConsumer eventConsumer,
|
||||
ILogger<Repository> repositoryLogger,
|
||||
@@ -71,6 +78,7 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
RepositorySettings repositorySettings)
|
||||
{
|
||||
this.repositoryFactory = repositoryFactory ?? throw new ArgumentNullException(nameof(repositoryFactory));
|
||||
this.commands = commands ?? throw new ArgumentNullException(nameof(commands));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
|
||||
this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
|
||||
@@ -175,12 +183,18 @@ namespace Tgstation.Server.Host.Components.Repository
|
||||
using (var context = await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
|
||||
try
|
||||
{
|
||||
var repo = await repositoryFactory.CreateFromPath(ioManager.ResolvePath(), cancellationToken).ConfigureAwait(false);
|
||||
var libGitRepo = await repositoryFactory.CreateFromPath(ioManager.ResolvePath(), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (repo == null)
|
||||
if (libGitRepo == null)
|
||||
return null;
|
||||
|
||||
return new Repository(repo, ioManager, eventConsumer, repositoryFactory, repositoryLogger, () =>
|
||||
return new Repository(
|
||||
libGitRepo,
|
||||
commands,
|
||||
ioManager,
|
||||
eventConsumer,
|
||||
repositoryFactory,
|
||||
repositoryLogger, () =>
|
||||
{
|
||||
logger.LogTrace("Releasing semaphore due to Repository disposal...");
|
||||
semaphore.Release();
|
||||
|
||||
@@ -289,7 +289,8 @@ namespace Tgstation.Server.Host.Core
|
||||
});
|
||||
|
||||
// configure component services
|
||||
services.AddSingleton<IRepositoryFactory, RepositoryFactory>();
|
||||
services.AddSingleton<ILibGit2RepositoryFactory, LibGit2RepositoryFactory>();
|
||||
services.AddSingleton<ILibGit2Commands, LibGit2Commands>();
|
||||
services.AddSingleton<IProviderFactory, ProviderFactory>();
|
||||
services.AddSingleton<IChatManagerFactory, ChatManagerFactory>();
|
||||
services.AddSingleton<IInstanceFactory, InstanceFactory>();
|
||||
|
||||
@@ -9,26 +9,26 @@ using System.Threading.Tasks;
|
||||
namespace Tgstation.Server.Host.Components.Repository.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="RepositoryFactory"/>.
|
||||
/// Tests for <see cref="LibGit2RepositoryFactory"/>.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public sealed class TestRepositoryFactory
|
||||
{
|
||||
static IRepositoryFactory CreateFactory() => new RepositoryFactory(Mock.Of<ILogger<RepositoryFactory>>());
|
||||
static ILibGit2RepositoryFactory CreateFactory() => new LibGit2RepositoryFactory(Mock.Of<ILogger<LibGit2RepositoryFactory>>());
|
||||
|
||||
static Task<LibGit2Sharp.IRepository> TestRepoLoading(
|
||||
string path,
|
||||
IRepositoryFactory repositoryFactory = null) =>
|
||||
ILibGit2RepositoryFactory repositoryFactory = null) =>
|
||||
(repositoryFactory ?? CreateFactory())
|
||||
.CreateFromPath(path, default);
|
||||
|
||||
[TestMethod]
|
||||
public void TestConstructionThrows() => Assert.ThrowsException<ArgumentNullException>(() => new RepositoryFactory(null));
|
||||
public void TestConstructionThrows() => Assert.ThrowsException<ArgumentNullException>(() => new LibGit2RepositoryFactory(null));
|
||||
|
||||
[TestMethod]
|
||||
public void TestInMemoryRepoCreation()
|
||||
{
|
||||
new RepositoryFactory(Mock.Of<ILogger<RepositoryFactory>>()).CreateInMemory().Dispose();
|
||||
new LibGit2RepositoryFactory(Mock.Of<ILogger<LibGit2RepositoryFactory>>()).CreateInMemory().Dispose();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
Reference in New Issue
Block a user