/// <summary>
        /// Create a pull request.
        /// </summary>
        /// <param name="log">The Cake log context.</param>
        /// <param name="gitClientFactory">Git client factory.</param>
        /// <param name="settings">Settings for accessing AzureDevOps.</param>
        /// <returns>Instance of the created pull request.</returns>
        internal static AzureDevOpsPullRequest Create(ICakeLog log, IGitClientFactory gitClientFactory, AzureDevOpsCreatePullRequestSettings settings)
        {
            log.NotNull(nameof(log));
            gitClientFactory.NotNull(nameof(gitClientFactory));
            settings.NotNull(nameof(settings));

            var repositoryDescription = new RepositoryDescription(settings.RepositoryUrl);

            using (var gitClient = gitClientFactory.CreateGitClient(repositoryDescription.CollectionUrl, settings.Credentials))
            {
                var repository =
                    gitClient
                    .GetRepositoryAsync(repositoryDescription.ProjectName, repositoryDescription.RepositoryName)
                    .ConfigureAwait(false)
                    .GetAwaiter()
                    .GetResult();

                if (repository == null)
                {
                    throw new AzureDevOpsException("Could not read repository.");
                }

                var targetBranchName = settings.TargetRefName;
                if (targetBranchName == null)
                {
                    targetBranchName = repository.DefaultBranch;
                }

                var refs =
                    gitClient
                    .GetRefsAsync(
                        repositoryDescription.ProjectName,
                        repositoryDescription.RepositoryName,
                        filter: targetBranchName.Replace("refs/", string.Empty))
                    .ConfigureAwait(false)
                    .GetAwaiter()
                    .GetResult();

                if (refs == null)
                {
                    throw new AzureDevOpsBranchNotFoundException(targetBranchName);
                }

                var targetBranch = refs.SingleOrDefault();

                if (targetBranch == null)
                {
                    throw new AzureDevOpsBranchNotFoundException(targetBranchName);
                }

                var pullRequest = new GitPullRequest()
                {
                    SourceRefName = settings.SourceRefName,
                    TargetRefName = targetBranch.Name,
                    Title         = settings.Title,
                    Description   = settings.Description,
                };

                var createdPullRequest =
                    gitClient
                    .CreatePullRequestAsync(
                        pullRequest,
                        repositoryDescription.ProjectName,
                        repositoryDescription.RepositoryName)
                    .ConfigureAwait(false)
                    .GetAwaiter()
                    .GetResult();

                var pullRequestReadSettings =
                    new AzureDevOpsPullRequestSettings(
                        settings.RepositoryUrl,
                        createdPullRequest.PullRequestId,
                        settings.Credentials);

                return(new AzureDevOpsPullRequest(log, pullRequestReadSettings, gitClientFactory));
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AzureDevOpsPullRequest"/> class.
        /// </summary>
        /// <param name="log">The Cake log context.</param>
        /// <param name="settings">Settings for accessing AzureDevOps.</param>
        /// <param name="gitClientFactory">A factory to communicate with Git client.</param>
        /// <exception cref="AzureDevOpsPullRequestNotFoundException">If <see cref="AzureDevOpsPullRequestSettings.ThrowExceptionIfPullRequestCouldNotBeFound"/>
        /// is set to <c>true</c> and no pull request could be found.</exception>
        internal AzureDevOpsPullRequest(ICakeLog log, AzureDevOpsPullRequestSettings settings, IGitClientFactory gitClientFactory)
        {
            log.NotNull(nameof(log));
            settings.NotNull(nameof(settings));
            gitClientFactory.NotNull(nameof(gitClientFactory));

            this.log = log;
            this.gitClientFactory = gitClientFactory;
            this.credentials      = settings.Credentials;
            this.throwExceptionIfPullRequestCouldNotBeFound = settings.ThrowExceptionIfPullRequestCouldNotBeFound;

            this.repositoryDescription = new RepositoryDescription(settings.RepositoryUrl);

            this.log.Verbose(
                "Repository information:\n  CollectionName: {0}\n  CollectionUrl: {1}\n  ProjectName: {2}\n  RepositoryName: {3}",
                this.repositoryDescription.CollectionName,
                this.repositoryDescription.CollectionUrl,
                this.repositoryDescription.ProjectName,
                this.repositoryDescription.RepositoryName);

            using (var gitClient = this.gitClientFactory.CreateGitClient(this.repositoryDescription.CollectionUrl, settings.Credentials, out var authorizedIdenity))
            {
                this.log.Verbose(
                    "Authorized Identity:\n  Id: {0}\n  DisplayName: {1}",
                    authorizedIdenity.Id,
                    authorizedIdenity.DisplayName);

                if (settings.PullRequestId.HasValue)
                {
                    this.log.Verbose("Read pull request with ID {0}", settings.PullRequestId.Value);
                    this.pullRequest =
                        gitClient
                        .GetPullRequestAsync(
                            this.repositoryDescription.ProjectName,
                            this.repositoryDescription.RepositoryName,
                            settings.PullRequestId.Value)
                        .ConfigureAwait(false)
                        .GetAwaiter()
                        .GetResult();
                }
                else if (!string.IsNullOrWhiteSpace(settings.SourceRefName))
                {
                    this.log.Verbose("Read pull request for branch {0}", settings.SourceRefName);

                    var pullRequestSearchCriteria =
                        new GitPullRequestSearchCriteria()
                    {
                        Status        = Microsoft.TeamFoundation.SourceControl.WebApi.PullRequestStatus.Active,
                        SourceRefName = settings.SourceRefName,
                    };

                    this.pullRequest =
                        gitClient
                        .GetPullRequestsAsync(
                            this.repositoryDescription.ProjectName,
                            this.repositoryDescription.RepositoryName,
                            pullRequestSearchCriteria,
                            top: 1)
                        .ConfigureAwait(false)
                        .GetAwaiter()
                        .GetResult()
                        .SingleOrDefault();
                }
                else
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(settings),
                              "Either PullRequestId or SourceRefName needs to be set");
                }
            }

            if (this.pullRequest == null)
            {
                if (this.throwExceptionIfPullRequestCouldNotBeFound)
                {
                    throw new AzureDevOpsPullRequestNotFoundException("Pull request not found");
                }

                this.log.Warning("Could not find pull request");
                return;
            }

            this.log.Verbose(
                "Pull request information:\n  PullRequestId: {0}\n  RepositoryId: {1}\n  RepositoryName: {2}\n  SourceRefName: {3}",
                this.pullRequest.PullRequestId,
                this.pullRequest.Repository.Id,
                this.pullRequest.Repository.Name,
                this.pullRequest.SourceRefName);
        }