2 using Microsoft.Extensions.Logging;
5 using System.Threading.Tasks;
16 public bool InUse => semaphore.CurrentCount == 0;
19 public bool CloneInProgress {
get;
private set; }
44 readonly ILogger<RepositoryManager>
logger;
67 this.repositorySettings = repositorySettings ??
throw new ArgumentNullException(nameof(repositorySettings));
68 this.ioManager = ioManager ??
throw new ArgumentNullException(nameof(ioManager));
69 this.eventConsumer = eventConsumer ??
throw new ArgumentNullException(nameof(eventConsumer));
70 this.credentialsProvider = credentialsProvider ??
throw new ArgumentNullException(nameof(credentialsProvider));
71 this.repositoryLogger = repositoryLogger ??
throw new ArgumentNullException(nameof(repositoryLogger));
72 this.logger = logger ??
throw new ArgumentNullException(nameof(logger));
73 semaphore =
new SemaphoreSlim(1);
79 logger.LogTrace(
"Disposing...");
84 public async Task<IRepository>
CloneRepository(Uri url,
string initialBranch,
string username,
string password, Action<int> progressReporter, CancellationToken cancellationToken)
87 throw new ArgumentNullException(nameof(url));
88 if (progressReporter == null)
89 throw new ArgumentNullException(nameof(progressReporter));
91 logger.LogInformation(
"Begin clone {0} (Branch: {1})", url, initialBranch);
95 throw new InvalidOperationException(
"The repository is already being cloned!");
96 CloneInProgress =
true;
102 logger.LogTrace(
"Semaphore acquired");
103 if (!await ioManager.DirectoryExists(
".", cancellationToken).ConfigureAwait(
false))
106 await Task.Factory.StartNew(() =>
111 path =
LibGit2Sharp.Repository.Clone(url.ToString(), ioManager.ResolvePath(
"."),
new CloneOptions
113 OnProgress = (a) => !cancellationToken.IsCancellationRequested,
114 OnTransferProgress = (a) =>
116 var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
117 progressReporter((
int)percentage);
118 return !cancellationToken.IsCancellationRequested;
120 RecurseSubmodules =
true,
121 OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
122 RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
123 BranchName = initialBranch,
127 catch (UserCancelledException) { }
128 cancellationToken.ThrowIfCancellationRequested();
129 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(
false);
135 logger.LogTrace(
"Deleting partially cloned repository...");
136 await ioManager.DeleteDirectory(
".",
default).ConfigureAwait(
false);
140 logger.LogDebug(
"Error deleting partially cloned repository! Exception: {0}", e);
146 logger.LogDebug(
"Repository exists, clone aborted!");
150 logger.LogInformation(
"Clone complete!");
154 CloneInProgress =
false;
156 return await LoadRepository(cancellationToken).ConfigureAwait(
false);
160 public async Task<IRepository>
LoadRepository(CancellationToken cancellationToken)
162 logger.LogTrace(
"Begin LoadRepository...");
165 throw new InvalidOperationException(
"The repository is being cloned!");
166 await semaphore.WaitAsync(cancellationToken).ConfigureAwait(
false);
168 await Task.Factory.StartNew(() =>
172 logger.LogTrace(
"Creating LibGit2Sharp.Repository...");
173 repo =
new LibGit2Sharp.Repository(ioManager.ResolvePath(
"."));
175 catch (RepositoryNotFoundException e)
177 logger.LogDebug(
"Repository not found!");
178 logger.LogTrace(
"Exception: {0}", e);
185 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(
false);
191 return new Repository(repo, ioManager, eventConsumer, credentialsProvider, repositoryLogger, () =>
193 logger.LogTrace(
"Releasing semaphore due to Repository disposal...");
201 logger.LogInformation(
"Deleting repository...");
204 logger.LogTrace(
"Semaphore acquired, deleting Repository directory...");
205 await ioManager.DeleteDirectory(
".", cancellationToken).ConfigureAwait(
false);
Represents configurable settings for a Repository
Consumes EventTypes and takes the appropriate actions
Use server authentication
RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > repositoryLogger, ILogger< RepositoryManager > logger)
Construct a RepositoryManager
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
readonly ILogger< RepositoryManager > logger
The ILogger for the RepositoryManager
readonly ILogger< Repository > repositoryLogger
The ILogger created Repositorys
readonly SemaphoreSlim semaphore
Used for controlling single access to the IRepository
For generating CredentialsHandlers
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the RepositoryManager
readonly IIOManager ioManager
The IIOManager for the RepositoryManager
Factory for creating and loading IRepositorys
readonly IEventConsumer eventConsumer
The IEventConsumer for the RepositoryManager
async Task< IRepository > CloneRepository(Uri url, string initialBranch, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Clone the repository at url
Interface for using filesystems
async Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
async Task DeleteRepository(CancellationToken cancellationToken)
Delete the current repository
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
readonly RepositorySettings repositorySettings
The RepositorySettings for the RepositoryManager
Async lock context helper