/// <summary> /// Generate a standard set of <see cref="PushOptions"/> /// </summary> /// <param name="progressReporter"><see cref="Action{T1}"/> to report 0-100 <see cref="int"/> progress of the operation</param> /// <param name="username">The username for the <see cref="credentialsProvider"/></param> /// <param name="password">The password for the <see cref="credentialsProvider"/></param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param> /// <returns>A new set of <see cref="PushOptions"/></returns> PushOptions GeneratePushOptions(Action <int> progressReporter, string username, string password, CancellationToken cancellationToken) => new PushOptions { OnPackBuilderProgress = (stage, current, total) => { var baseProgress = stage == PackBuilderStage.Counting ? 0 : 25; progressReporter(baseProgress + ((int)(25 * ((float)current) / total))); return(!cancellationToken.IsCancellationRequested); }, OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested, OnPushTransferProgress = (a, sentBytes, totalBytes) => { progressReporter(50 + ((int)(50 * ((float)sentBytes) / totalBytes))); return(!cancellationToken.IsCancellationRequested); }, CredentialsProvider = credentialsProvider.GenerateHandler(username, password) };
/// <inheritdoc /> public async Task <IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action <int> progressReporter, CancellationToken cancellationToken) { if (url == null) { throw new ArgumentNullException(nameof(url)); } if (progressReporter == null) { throw new ArgumentNullException(nameof(progressReporter)); } logger.LogInformation("Begin clone {0} (Branch: {1})", url, initialBranch); lock (this) { if (CloneInProgress) { throw new InvalidOperationException("The repository is already being cloned!"); } CloneInProgress = true; } try { using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { logger.LogTrace("Semaphore acquired"); if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false)) { try { await Task.Factory.StartNew(() => { string path = null; try { 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); } catch { try { logger.LogTrace("Deleting partially cloned repository..."); await ioManager.DeleteDirectory(".", default).ConfigureAwait(false); } catch (Exception e) { logger.LogDebug("Error deleting partially cloned repository! Exception: {0}", e); } throw; } } else { logger.LogDebug("Repository exists, clone aborted!"); return(null); } } logger.LogInformation("Clone complete!"); } finally { CloneInProgress = false; } return(await LoadRepository(cancellationToken).ConfigureAwait(false)); }