示例#1
0
 /// <summary>
 /// Runs a blocking force checkout to <paramref name="committish"/>
 /// </summary>
 /// <param name="committish">The committish to checkout</param>
 void RawCheckout(string committish)
 {
     Commands.Checkout(repository, committish, new CheckoutOptions
     {
         CheckoutModifiers = CheckoutModifiers.Force
     });
     repository.RemoveUntrackedFiles();
 }
        /// <summary>
        /// Runs a blocking force checkout to <paramref name="committish"/>
        /// </summary>
        /// <param name="committish">The committish to checkout</param>
        /// <param name="progressReporter">Progress reporter <see cref="Action{T}"/></param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        void RawCheckout(string committish, Action <int> progressReporter, CancellationToken cancellationToken)
        {
            logger.LogTrace("Checkout: {0}", committish);

            progressReporter(0);
            cancellationToken.ThrowIfCancellationRequested();

            Commands.Checkout(repository, committish, new CheckoutOptions
            {
                CheckoutModifiers  = CheckoutModifiers.Force,
                OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
            });

            cancellationToken.ThrowIfCancellationRequested();

            repository.RemoveUntrackedFiles();
        }
示例#3
0
        /// <summary>
        /// Runs a blocking force checkout to <paramref name="committish"/>
        /// </summary>
        /// <param name="committish">The committish to checkout</param>
        /// <param name="progressReporter">Progress reporter <see cref="Action{T}"/></param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
        void RawCheckout(string committish, Action <int> progressReporter, CancellationToken cancellationToken)
        {
            logger.LogTrace("Checkout: {0}", committish);

            progressReporter(0);
            cancellationToken.ThrowIfCancellationRequested();

            var checkoutOptions = new CheckoutOptions
            {
                CheckoutModifiers  = CheckoutModifiers.Force,
                OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
            };

            void RunCheckout() => commands.Checkout(
                libGitRepo,
                checkoutOptions,
                committish);

            try
            {
                RunCheckout();
            }
            catch (NotFoundException)
            {
                // Maybe (likely) a remote?
                var remoteName      = $"origin/{committish}";
                var potentialBranch = libGitRepo.Branches.FirstOrDefault(
                    branch => branch.FriendlyName.Equals(remoteName, StringComparison.Ordinal));
                cancellationToken.ThrowIfCancellationRequested();

                if (potentialBranch == default)
                {
                    throw;
                }

                logger.LogDebug("Creating local branch for {0}...", potentialBranch.FriendlyName);
                libGitRepo.CreateBranch(committish, potentialBranch.Tip);
                cancellationToken.ThrowIfCancellationRequested();

                RunCheckout();
            }

            cancellationToken.ThrowIfCancellationRequested();

            libGitRepo.RemoveUntrackedFiles();
        }
示例#4
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);
        }