diff --git a/src/Tgstation.Server.Host/Components/Repository/Repository.cs b/src/Tgstation.Server.Host/Components/Repository/Repository.cs index a3b81d2bad..125ceded30 100644 --- a/src/Tgstation.Server.Host/Components/Repository/Repository.cs +++ b/src/Tgstation.Server.Host/Components/Repository/Repository.cs @@ -247,20 +247,16 @@ namespace Tgstation.Server.Host.Components.Repository libGitRepo, refSpecList, remote, - new FetchOptions - { - Prune = true, - OnProgress = (a) => !cancellationToken.IsCancellationRequested, - OnTransferProgress = TransferProgressHandler( - progressReporter.CreateSection($"Fetch {refSpec}", progressFactor), - cancellationToken), - OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested, - CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password), - }, + new FetchOptions().Hydrate( + logger, + progressReporter.CreateSection($"Fetch {refSpec}", progressFactor), + credentialsProvider.GenerateCredentialsHandler(username, password), + cancellationToken), logMessage); } - catch (UserCancelledException) + catch (UserCancelledException ex) { + logger.LogTrace(ex, "Suppressing fetch cancel exception"); } catch (LibGit2SharpException ex) { @@ -439,14 +435,12 @@ namespace Tgstation.Server.Host.Components.Repository var fetchOptions = new FetchOptions { Prune = true, - OnProgress = (a) => !cancellationToken.IsCancellationRequested, - OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested, - CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password), TagFetchMode = TagFetchMode.All, - }; - - if (progressReporter != null) - fetchOptions.OnTransferProgress = TransferProgressHandler(progressReporter.CreateSection("Fetch Origin", 1.0), cancellationToken); + }.Hydrate( + logger, + progressReporter?.CreateSection("Fetch Origin", 1.0), + credentialsProvider.GenerateCredentialsHandler(username, password), + cancellationToken); commands.Fetch( libGitRepo, @@ -1041,19 +1035,18 @@ namespace Tgstation.Server.Host.Components.Repository var submoduleUpdateOptions = new SubmoduleUpdateOptions { Init = true, - OnProgress = output => !cancellationToken.IsCancellationRequested, - OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested, - CredentialsProvider = credentialsProvider.GenerateCredentialsHandler(username, password), + OnCheckoutNotify = (_, _) => !cancellationToken.IsCancellationRequested, }; + submoduleUpdateOptions.FetchOptions.Hydrate( + logger, + progressReporter?.CreateSection($"Fetch submodule {submodule.Name}", factor), + credentialsProvider.GenerateCredentialsHandler(username, password), + cancellationToken); + if (progressReporter != null) - { - submoduleUpdateOptions.OnTransferProgress = TransferProgressHandler( - progressReporter.CreateSection($"Fetch submodule {submodule.Name}", factor), - cancellationToken); submoduleUpdateOptions.OnCheckoutProgress = CheckoutProgressHandler( progressReporter.CreateSection($"Checkout submodule {submodule.Name}", factor)); - } logger.LogDebug("Updating submodule {submoduleName}...", submodule.Name); Task RawSubModuleUpdate() => Task.Factory.StartNew( @@ -1131,37 +1124,6 @@ namespace Tgstation.Server.Host.Components.Repository progressReporter.ReportProgress(percentage); }; - - /// - /// Generate a from a given and . - /// - /// The of the operation. - /// The for the operation. - /// A new based on . - TransferProgressHandler TransferProgressHandler(JobProgressReporter progressReporter, CancellationToken cancellationToken) => (transferProgress) => - { - double? percentage; - var totalObjectsToProcess = transferProgress.TotalObjects * 2; - var processedObjects = transferProgress.IndexedObjects + transferProgress.ReceivedObjects; - if (totalObjectsToProcess < processedObjects || totalObjectsToProcess == 0) - percentage = null; - else - { - percentage = (double)processedObjects / totalObjectsToProcess; - if (percentage < 0) - percentage = null; - } - - if (percentage == null) - logger.LogDebug( - "Bad transfer progress values (Please tell Cyberboss)! Indexed: {indexed}, Received: {received}, Total: {total}", - transferProgress.IndexedObjects, - transferProgress.ReceivedObjects, - transferProgress.TotalObjects); - - progressReporter.ReportProgress(percentage); - return !cancellationToken.IsCancellationRequested; - }; } #pragma warning restore CA1506 } diff --git a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs index 5852a58f97..8ce9b60318 100644 --- a/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs +++ b/src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using Tgstation.Server.Api.Models; using Tgstation.Server.Host.Components.Events; using Tgstation.Server.Host.Configuration; +using Tgstation.Server.Host.Extensions; using Tgstation.Server.Host.IO; using Tgstation.Server.Host.Jobs; using Tgstation.Server.Host.Utils; @@ -149,20 +150,7 @@ namespace Tgstation.Server.Host.Components.Repository var checkoutProgressReporter = progressReporter?.CreateSection(null, 0.25f); var cloneOptions = new CloneOptions { - OnProgress = (a) => !cancellationToken.IsCancellationRequested, - OnTransferProgress = (a) => - { - if (cloneProgressReporter != null) - { - var percentage = ((double)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2); - cloneProgressReporter.ReportProgress(percentage); - } - - return !cancellationToken.IsCancellationRequested; - }, RecurseSubmodules = recurseSubmodules, - OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested, - RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested, OnCheckoutProgress = (path, completed, remaining) => { if (checkoutProgressReporter == null) @@ -172,9 +160,14 @@ namespace Tgstation.Server.Host.Components.Repository checkoutProgressReporter.ReportProgress(percentage); }, BranchName = initialBranch, - CredentialsProvider = repositoryFactory.GenerateCredentialsHandler(username, password), }; + cloneOptions.FetchOptions.Hydrate( + logger, + cloneProgressReporter, + repositoryFactory.GenerateCredentialsHandler(username, password), + cancellationToken); + await repositoryFactory.Clone( url, cloneOptions, diff --git a/src/Tgstation.Server.Host/Extensions/FetchOptionsExtensions.cs b/src/Tgstation.Server.Host/Extensions/FetchOptionsExtensions.cs new file mode 100644 index 0000000000..e1b47d644a --- /dev/null +++ b/src/Tgstation.Server.Host/Extensions/FetchOptionsExtensions.cs @@ -0,0 +1,91 @@ +using System; +using System.Threading; + +using LibGit2Sharp; +using LibGit2Sharp.Handlers; + +using Microsoft.Extensions.Logging; + +using Tgstation.Server.Host.Jobs; + +namespace Tgstation.Server.Host.Extensions +{ + /// + /// Extension methods for . + /// + static class FetchOptionsExtensions + { + /// + /// Hydrate a given set of . + /// + /// The to hydrate. + /// The for the operation. + /// The optional . + /// The optional . + /// The for the operation. + /// The hydrated . + public static FetchOptions Hydrate( + this FetchOptions fetchOptions, + ILogger logger, + JobProgressReporter progressReporter, + CredentialsHandler credentialsHandler, + CancellationToken cancellationToken) + { + ArgumentNullException.ThrowIfNull(fetchOptions); + ArgumentNullException.ThrowIfNull(logger); + + fetchOptions.OnProgress = _ => !cancellationToken.IsCancellationRequested; + fetchOptions.OnTransferProgress = transferProgress => + { + if (progressReporter != null) + { + var percentage = ((double)transferProgress.IndexedObjects + transferProgress.ReceivedObjects) / (transferProgress.TotalObjects * 2); + progressReporter.ReportProgress(percentage); + } + + return !cancellationToken.IsCancellationRequested; + }; + fetchOptions.OnUpdateTips = (_, _, _) => !cancellationToken.IsCancellationRequested; + fetchOptions.CredentialsProvider = credentialsHandler; + fetchOptions.RepositoryOperationStarting = _ => !cancellationToken.IsCancellationRequested; + fetchOptions.OnTransferProgress = TransferProgressHandler( + logger, + progressReporter, + cancellationToken); + + return fetchOptions; + } + + /// + /// Generate a from a given and . + /// + /// The for the operation. + /// The optional of the operation. + /// The for the operation. + /// A new based on . + static TransferProgressHandler TransferProgressHandler(ILogger logger, JobProgressReporter progressReporter, CancellationToken cancellationToken) => transferProgress => + { + double? percentage; + var totalObjectsToProcess = transferProgress.TotalObjects * 2; + var processedObjects = transferProgress.IndexedObjects + transferProgress.ReceivedObjects; + if (totalObjectsToProcess < processedObjects || totalObjectsToProcess == 0) + percentage = null; + else + { + percentage = (double)processedObjects / totalObjectsToProcess; + if (percentage < 0) + percentage = null; + } + + if (percentage == null) + logger.LogDebug( + "Bad transfer progress values (Please tell Cyberboss)! Indexed: {indexed}, Received: {received}, Total: {total}", + transferProgress.IndexedObjects, + transferProgress.ReceivedObjects, + transferProgress.TotalObjects); + + progressReporter?.ReportProgress(percentage); + return !cancellationToken.IsCancellationRequested; + }; + } +} diff --git a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj index 04f82f6b2d..af8a133ea0 100644 --- a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj +++ b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj @@ -73,7 +73,7 @@ - + diff --git a/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs b/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs index bbf369efce..04e7cdb66b 100644 --- a/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs +++ b/tests/Tgstation.Server.Host.Tests/Components/Repository/TestRepositoryFactory.cs @@ -1,4 +1,4 @@ -using LibGit2Sharp; +using LibGit2Sharp; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -39,12 +39,11 @@ namespace Tgstation.Server.Host.Components.Repository.Tests try { var factory = CreateFactory(); + var cloneOpts = new CloneOptions(); + cloneOpts.FetchOptions.CredentialsProvider = factory.GenerateCredentialsHandler(null, null); await factory.Clone( new Uri("https://github.com/Cyberboss/Test"), - new CloneOptions - { - CredentialsProvider = factory.GenerateCredentialsHandler(null, null) - }, + cloneOpts, tempDir, default);