Exemplo n.º 1
0
 /// <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.GenerateCredentialsHandler(username, password)
 };
Exemplo n.º 2
0
        /// <inheritdoc />
#pragma warning disable CA1506 // TODO: Decomplexify
        public async Task <bool?> AddTestMerge(
            TestMergeParameters testMergeParameters,
            string committerName,
            string committerEmail,
            string username,
            string password,
            Action <int> progressReporter,
            CancellationToken cancellationToken)
        {
            if (testMergeParameters == null)
            {
                throw new ArgumentNullException(nameof(testMergeParameters));
            }
            if (committerName == null)
            {
                throw new ArgumentNullException(nameof(committerName));
            }
            if (committerEmail == null)
            {
                throw new ArgumentNullException(nameof(committerEmail));
            }
            if (progressReporter == null)
            {
                throw new ArgumentNullException(nameof(progressReporter));
            }

            logger.LogDebug(
                "Begin AddTestMerge: #{0} at {1} ({2}) by <{3} ({4})>",
                testMergeParameters.Number,
                testMergeParameters.TargetCommitSha?.Substring(0, 7),
                testMergeParameters.Comment,
                committerName,
                committerEmail);

            if (RemoteGitProvider == Api.Models.RemoteGitProvider.Unknown)
            {
                throw new InvalidOperationException("Cannot test merge with an Unknown RemoteGitProvider!");
            }

            var commitMessage = String.Format(
                CultureInfo.InvariantCulture,
                "TGS Test merge #{0}{1}{2}",
                testMergeParameters.Number,
                testMergeParameters.Comment != null
                                        ? Environment.NewLine
                                        : String.Empty,
                testMergeParameters.Comment ?? String.Empty);

            var testMergeBranchName = String.Format(CultureInfo.InvariantCulture, "tm-{0}", testMergeParameters.Number);
            var localBranchName     = String.Format(CultureInfo.InvariantCulture, gitRemoteFeatures.TestMergeLocalBranchNameFormatter, testMergeParameters.Number, testMergeBranchName);

            var refSpec     = String.Format(CultureInfo.InvariantCulture, gitRemoteFeatures.TestMergeRefSpecFormatter, testMergeParameters.Number, testMergeBranchName);
            var refSpecList = new List <string> {
                refSpec
            };
            var logMessage = String.Format(CultureInfo.InvariantCulture, "Test merge #{0}", testMergeParameters.Number);

            var originalCommit = libGitRepo.Head;

            MergeResult result = null;

            var sig = new Signature(new Identity(committerName, committerEmail), DateTimeOffset.UtcNow);
            await Task.Factory.StartNew(
                () =>
            {
                try
                {
                    try
                    {
                        logger.LogTrace("Fetching refspec {0}...", refSpec);

                        var remote = libGitRepo.Network.Remotes.First();
                        progressReporter(0);
                        commands.Fetch(
                            libGitRepo,
                            refSpecList,
                            remote,
                            new FetchOptions
                        {
                            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),
                        },
                            logMessage);
                    }
                    catch (UserCancelledException)
                    {
                    }
                    catch (LibGit2SharpException ex)
                    {
                        CheckBadCredentialsException(ex);
                    }

                    cancellationToken.ThrowIfCancellationRequested();

                    libGitRepo.RemoveUntrackedFiles();

                    cancellationToken.ThrowIfCancellationRequested();

                    testMergeParameters.TargetCommitSha = libGitRepo.Lookup(testMergeParameters.TargetCommitSha ?? localBranchName).Sha;

                    cancellationToken.ThrowIfCancellationRequested();

                    logger.LogTrace("Merging {0} into {1}...", testMergeParameters.TargetCommitSha.Substring(0, 7), Reference);

                    result = libGitRepo.Merge(testMergeParameters.TargetCommitSha, sig, new MergeOptions
                    {
                        CommitOnSuccess     = commitMessage == null,
                        FailOnConflict      = true,
                        FastForwardStrategy = FastForwardStrategy.NoFastForward,
                        SkipReuc            = true,
                        OnCheckoutProgress  = (a, completedSteps, totalSteps) => progressReporter(50 + ((int)(((float)completedSteps) / totalSteps * 50))),
                    });
                }
                finally
                {
                    libGitRepo.Branches.Remove(localBranchName);
                }

                cancellationToken.ThrowIfCancellationRequested();

                if (result.Status == MergeStatus.Conflicts)
                {
                    var revertTo = originalCommit.CanonicalName ?? originalCommit.Tip.Sha;
                    logger.LogDebug("Merge conflict, aborting and reverting to {0}", revertTo);
                    RawCheckout(revertTo, progressReporter, cancellationToken);
                    cancellationToken.ThrowIfCancellationRequested();
                }

                libGitRepo.RemoveUntrackedFiles();
            },
                cancellationToken,
                DefaultIOManager.BlockingTaskCreationOptions,
                TaskScheduler.Current)
            .ConfigureAwait(false);

            if (result.Status == MergeStatus.Conflicts)
            {
                await eventConsumer.HandleEvent(
                    EventType.RepoMergeConflict,
                    new List <string>
                {
                    originalCommit.Tip.Sha,
                    testMergeParameters.TargetCommitSha,
                    originalCommit.FriendlyName ?? UnknownReference,
                    testMergeBranchName,
                },
                    cancellationToken)
                .ConfigureAwait(false);

                return(null);
            }

            if (commitMessage != null && result.Status != MergeStatus.UpToDate)
            {
                logger.LogTrace("Committing merge: \"{0}\"...", commitMessage);
                await Task.Factory.StartNew(
                    () => libGitRepo.Commit(commitMessage, sig, sig, new CommitOptions
                {
                    PrettifyMessage = true,
                }),
                    cancellationToken,
                    DefaultIOManager.BlockingTaskCreationOptions,
                    TaskScheduler.Current)
                .ConfigureAwait(false);
            }

            await eventConsumer.HandleEvent(
                EventType.RepoAddTestMerge,
                new List <string>
            {
                testMergeParameters.Number.ToString(CultureInfo.InvariantCulture),
                testMergeParameters.TargetCommitSha,
                testMergeParameters.Comment,
            },
                cancellationToken)
            .ConfigureAwait(false);

            return(result.Status != MergeStatus.NonFastForward);
        }