Beispiel #1
0
 public GitHubPullDogRepositoryClient(
     IGitHubClient gitHubClient,
     GitReference gitReference)
 {
     this.gitHubClient = gitHubClient;
     this.gitReference = gitReference;
 }
Beispiel #2
0
        internal string ZeroString()
        {
            switch (Type)
            {
            case GitUpdateReferenceType.Update:
                if (!GitReference.ValidName(Name, true))
                {
                    throw new InvalidOperationException($"'{Name}' is not a valid reference name");
                }
                if (Target != null && OldTarget != null)
                {
                    return($"update {Name}\0{Target}\0{OldTarget}\0");
                }
                else if (Target != null)
                {
                    return($"update {Name}\0{Target}\0\0");
                }
                else if (SymbolicTarget != null)
                {
                    if (!GitReference.ValidName(SymbolicTarget, true))
                    {
                        throw new InvalidOperationException($"'{SymbolicTarget}' is not a valid reference name");
                    }

                    return($"update {Name}\0{SymbolicTarget}\0");
                }
                else
                {
                    throw new InvalidOperationException();
                }

            default:
                throw new NotImplementedException($"Update reference type {Type} not implemented yet");
            }
        }
Beispiel #3
0
        public async Task Given_Parameters_When_FindShaAsync_Invoked_Then_It_Should_Return_Property()
        {
            var sha  = this._fixture.Create <string>();
            var @ref = this._fixture.Create <string>();

            var head = new GitReference().SetValue("Sha", sha).SetValue("Ref", @ref);
            var pr   = new PullRequest().SetValue("Head", head);

            var prc = new Mock <IPullRequestsClient>();

            prc.Setup(p => p.Get(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>())).ReturnsAsync(pr);

            var client = new Mock <IGitHubClient>();

            client.SetupGet(p => p.PullRequest).Returns(prc.Object);

            var handler = new MessageHandler()
                          .WithGitHubClient(client.Object);

            var options = new Options();

            await handler.FindShaAsync(options).ConfigureAwait(false);

            handler.Sha.Should().BeEquivalentTo(pr.Head.Sha);
            handler.Ref.Should().BeEquivalentTo(pr.Head.Ref);
        }
Beispiel #4
0
        public override async Task ExecuteAsync()
        {
            Uri       imageInfoPathIdentifier = GitHelper.GetBlobUrl(Options.GitOptions);
            GitObject imageInfoGitObject      = await GetUpdatedImageInfoGitObjectAsync();

            if (imageInfoGitObject is null)
            {
                loggerService.WriteMessage($"No changes to the '{imageInfoPathIdentifier}' file were needed.");
                return;
            }

            loggerService.WriteMessage(
                $"The '{imageInfoPathIdentifier}' file has been updated with the following content:" +
                Environment.NewLine + imageInfoGitObject.Content + Environment.NewLine);

            if (!Options.IsDryRun)
            {
                using IGitHubClient gitHubClient = this.gitHubClientFactory.GetClient(Options.GitOptions.ToGitHubAuth(), Options.IsDryRun);
                await GitHelper.ExecuteGitOperationsWithRetryAsync(async() =>
                {
                    GitReference gitRef = await GitHelper.PushChangesAsync(
                        gitHubClient, Options, "Merging image info updates from build.",
                        branch => Task.FromResult <IEnumerable <GitObject> >(new GitObject[] { imageInfoGitObject }));

                    Uri commitUrl = GitHelper.GetCommitUrl(Options.GitOptions, gitRef.Object.Sha);
                    loggerService.WriteMessage($"The '{imageInfoPathIdentifier}' file was updated ({commitUrl}).");
                });
            }
        }
Beispiel #5
0
        protected internal override async ValueTask <GitReference?> ResolveAsync(GitReference gitReference)
        {
            string dir      = gitReference.Name.Contains('/', StringComparison.Ordinal) ? GitDir : WorkTreeDir;
            string fileName = Path.Combine(dir, gitReference.Name);

            if (!File.Exists(fileName))
            {
                return(null);
            }

            if (GitRepository.TryReadRefFile(fileName, null, out var body))
            {
                if (body.StartsWith("ref: ", StringComparison.OrdinalIgnoreCase))
                {
                    body = body.Substring("ref: ".Length);
                    var ob = await Repository.ReferenceRepository.GetAsync(body.Trim()).ConfigureAwait(false);

                    if (ob is not null)
                    {
                        return(ob);
                    }
                }
                else if (GitId.TryParse(body, out var id))
                {
                    return(new GitReference(Repository.ReferenceRepository, gitReference.Name, id));
                }
            }

            return(gitReference); // Not symbolic, and exists. Or error and exists
        }
Beispiel #6
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        public override async IAsyncEnumerable <GitReference> GetAll(HashSet <string> alreadyReturned)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            string baseDir = Path.GetFullPath(GitDir);

            foreach (string file in Directory.EnumerateFiles(Path.Combine(baseDir, "refs"), "*", SearchOption.AllDirectories))
            {
                if (file.Length > baseDir.Length + 1 && file[baseDir.Length] == Path.DirectorySeparatorChar)
                {
                    string name = file.Substring(baseDir.Length + 1).Replace(Path.DirectorySeparatorChar, '/');

                    yield return(new GitReference(this, name, (GitId?)null));
                }
            }

            foreach (string file in Directory.EnumerateFiles(GitDir))
            {
                string name = Path.GetFileName(file);

                if (GitReference.AllUpper(name) && !alreadyReturned.Contains(name))
                {
                    yield return(new GitSymbolicReference(this, file.Substring(GitDir.Length + 1)));
                }
            }
        }
Beispiel #7
0
        public override async Task ExecuteAsync()
        {
            _loggerService.WriteHeading("PUBLISHING MCR DOCS");

            // Hookup a TraceListener in order to capture details from Microsoft.DotNet.VersionTools
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

            IEnumerable <GitObject> gitObjects =
                GetUpdatedReadmes()
                .Concat(GetUpdatedTagsMetadata());

            foreach (GitObject gitObject in gitObjects)
            {
                _loggerService.WriteMessage(
                    $"Updated file '{gitObject.Path}' with contents:{Environment.NewLine}{gitObject.Content}{Environment.NewLine}");
            }

            if (!Options.IsDryRun)
            {
                using IGitHubClient gitHubClient = _gitHubClientFactory.GetClient(Options.GitOptions.ToGitHubAuth(), Options.IsDryRun);

                await RetryHelper.GetWaitAndRetryPolicy <HttpRequestException>(_loggerService).ExecuteAsync(async() =>
                {
                    GitReference gitRef = await GitHelper.PushChangesAsync(gitHubClient, Options, $"Mirroring readmes", branch =>
                    {
                        return(FilterUpdatedGitObjectsAsync(gitObjects, gitHubClient, branch));
                    });

                    if (gitRef != null)
                    {
                        _loggerService.WriteMessage(PipelineHelper.FormatOutputVariable("readmeCommitDigest", gitRef.Object.Sha));
                    }
                });
            }
        }
        public ValueTask <GitReference?> GetAsync(string name)
        {
            if (!GitReference.ValidName(name, true))
            {
                throw new ArgumentOutOfRangeException(nameof(name), name, "Invalid Reference name");
            }

            return(GetUnsafeAsync(name));
        }
Beispiel #9
0
 private Commit GetCommitFromGithubCommit(GitReference commit)
 {
     return(new Commit
     {
         //Author = commit.Author.Name,
         //Message = commit.Message,
         Revision = commit.Sha
     });
 }
Beispiel #10
0
        internal GitRevisionSet AddReference(GitReference gitReference)
        {
            if (gitReference?.Commit is GitCommit q)
            {
                return(AddCommit(q));
            }

            return(this);
        }
Beispiel #11
0
        internal GitReferenceChangeSet(GitRepository repository, GitReference reference)
            : base(repository)
        {
            _reference = reference;
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
            Expression = Expression.Property(Expression.Property(Expression.Property(Expression.Constant(Repository), nameof(Repository.References)),
                                                                 "Item", Expression.Constant(_reference.Name)), nameof(GitReference.ReferenceChanges));
#pragma warning restore IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
        }
Beispiel #12
0
        private static string CreateLink(GitReference reference)
        {
            if (reference.Repository != null)
            {
                var baseHtml = reference.Repository.HtmlUrl + "/tree/" + reference.Ref;
                return(string.Format("<a href='{0}'>{1}</a>", baseHtml, reference.Label));
            }

            return("<a href='#'>unknown repository</a>");
        }
Beispiel #13
0
        protected internal override async ValueTask <GitReference?> ResolveAsync(GitReference gitReference)
        {
            await Read().ConfigureAwait(false);

            if (_peelRefs !.TryGetValue(gitReference.Name, out var v))
            {
                return(new GitReference(this, v.Name, v.Id).SetPeeled(v.Peeled));
            }

            return(null);
        }
Beispiel #14
0
        public override IAsyncEnumerable <GitReferenceChange>?GetChanges(GitReference reference)
        {
            string fileName = Path.Combine(GitDir, "logs", reference.Name);

            if (File.Exists(fileName))
            {
                return(GetChangesFromRefLogFile(fileName));
            }

            return(null);
        }
        public MockPullRequest()
        {
            Title = "Title";
            Body  = @"# 1st head
paragraph1
# 2nd head
paragraph2
";
            Base  = new GitReference("", "BASE", "", "1212", null, null);
            Head  = new GitReference("", "HEAD", "", "asdfasdf", null, null);
        }
Beispiel #16
0
        private protected void ParseLineToPeel(BucketBytes line, ref GitRefPeel?last, int idLength)
        {
            if (char.IsLetterOrDigit((char)line[0]) && line.Length > idLength + 1)
            {
                if (GitId.TryParse(line.Slice(0, idLength), out var oid))
                {
                    string name = line.Slice(idLength + 1).Trim().ToUTF8String();

                    if (GitReference.ValidName(name, false))
                    {
                        _peelRefs ![name] = last = new GitRefPeel {
        protected internal override async ValueTask <GitReference?> ResolveAsync(GitReference gitReference)
        {
            foreach (var v in Sources)
            {
                var r = await v.ResolveAsync(gitReference).ConfigureAwait(false);

                if (r is not null)
                {
                    return(r);
                }
            }

            return(null);
        }
        public override IAsyncEnumerable <GitReferenceChange> GetChanges(GitReference reference)
        {
            foreach (var v in Sources)
            {
                var r = v.GetChanges(reference);

                if (r is not null)
                {
                    return(r);
                }
            }

            return(AsyncEnumerable.Empty <GitReferenceChange>());
        }
        private static async Task CreatePullRequestAsync(GitHubClient client, GitRepo gitRepo, Config config)
        {
            GitHubProject project       = new GitHubProject(gitRepo.Name, gitRepo.Owner);
            GitHubProject forkedProject = new GitHubProject(gitRepo.Name, Options.GitUser);
            GitHubBranch  baseBranch    = new GitHubBranch(gitRepo.Branch, project);
            GitHubBranch  headBranch    = new GitHubBranch(
                $"{gitRepo.Name}-{gitRepo.Branch}{config.WorkingBranchSuffix}",
                forkedProject);

            IEnumerable <GitObject> changes = await GetUpdatedFiles(config.SourcePath, client, baseBranch);

            if (!changes.Any())
            {
                return;
            }

            GitReference currentRef = await client.GetReferenceAsync(project, $"heads/{baseBranch.Name}");

            string  parentSha = currentRef.Object.Sha;
            GitTree tree      = await client.PostTreeAsync(forkedProject, parentSha, changes.ToArray());

            GitCommit commit = await client.PostCommitAsync(forkedProject, config.CommitMessage, tree.Sha, new[] { parentSha });

            string workingReference = $"heads/{headBranch.Name}";

            if (await BranchExists(client, forkedProject, workingReference))
            {
                await client.PatchReferenceAsync(forkedProject, workingReference, commit.Sha, force : true);
            }
            else
            {
                await client.PostReferenceAsync(forkedProject, workingReference, commit.Sha);
            }

            GitHubPullRequest pullRequestToUpdate = await client.SearchPullRequestsAsync(
                project,
                headBranch.Name,
                await client.GetMyAuthorIdAsync());

            if (pullRequestToUpdate == null)
            {
                await client.PostGitHubPullRequestAsync(
                    $"[{gitRepo.Branch}] {config.PullRequestTitle}",
                    config.PullRequestDescription,
                    headBranch,
                    baseBranch,
                    maintainersCanModify : true);
            }
        }
        public override async Task ExecuteAsync()
        {
            Logger.WriteHeading("UPDATING VERSIONS");

            // Hookup a TraceListener in order to capture details from Microsoft.DotNet.VersionTools
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

            DockerHelper.PullBaseImages(Manifest, Options);

            GitHubAuth githubAuth = new GitHubAuth(Options.GitAuthToken, Options.GitUsername, Options.GitEmail);

            using (GitHubClient client = new GitHubClient(githubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        GitHubProject project    = new GitHubProject(Options.GitRepo, Options.GitOwner);
                        GitHubBranch  branch     = new GitHubBranch(Options.GitBranch, project);
                        GitObject[]   gitObjects = await GetUpdatedVerionInfo(client, branch);

                        if (gitObjects.Any())
                        {
                            string       masterRef     = $"heads/{Options.GitBranch}";
                            GitReference currentMaster = await client.GetReferenceAsync(project, masterRef);

                            string  masterSha = currentMaster.Object.Sha;
                            GitTree tree      = await client.PostTreeAsync(project, masterSha, gitObjects);

                            string    commitMessage = "Update Docker image digests";
                            GitCommit commit        = await client.PostCommitAsync(
                                project, commitMessage, tree.Sha, new[] { masterSha });

                            // Only fast-forward. Don't overwrite other changes: throw exception instead.
                            await client.PatchReferenceAsync(project, masterRef, commit.Sha, force : false);
                        }

                        break;
                    }
                    catch (HttpRequestException ex) when(i < (MaxTries - 1))
                    {
                        Logger.WriteMessage($"Encountered exception committing build-info update: {ex.Message}");
                        Logger.WriteMessage($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - i - 1} tries left.");
                        await Task.Delay(RetryMillisecondsDelay);
                    }
                }
            }
        }
Beispiel #21
0
        public static async Task <GitReference> PushChangesAsync(IGitHubClient client, IGitOptionsHost options, string commitMessage, Func <GitHubBranch, Task <IEnumerable <GitObject> > > getChanges)
        {
            GitOptions    gitOptions = options.GitOptions;
            GitHubProject project    = new GitHubProject(gitOptions.Repo, gitOptions.Owner);
            GitHubBranch  branch     = new GitHubBranch(gitOptions.Branch, project);

            IEnumerable <GitObject> changes = await getChanges(branch);

            if (!changes.Any())
            {
                return(null);
            }

            string       masterRef     = $"heads/{gitOptions.Branch}";
            GitReference currentMaster = await client.GetReferenceAsync(project, masterRef);

            string masterSha = currentMaster.Object.Sha;

            if (!options.IsDryRun)
            {
                GitTree tree = await client.PostTreeAsync(project, masterSha, changes.ToArray());

                GitCommit commit = await client.PostCommitAsync(
                    project, commitMessage, tree.Sha, new[] { masterSha });

                // Only fast-forward. Don't overwrite other changes: throw exception instead.
                return(await client.PatchReferenceAsync(project, masterRef, commit.Sha, force : false));
            }
            else
            {
                Logger.WriteMessage($"The following files would have been updated at {gitOptions.Owner}/{gitOptions.Repo}/{gitOptions.Branch}:");
                Logger.WriteMessage();
                foreach (GitObject gitObject in changes)
                {
                    Logger.WriteMessage($"{gitObject.Path}:");
                    Logger.WriteMessage(gitObject.Content);
                    Logger.WriteMessage();
                }

                return(null);
            }
        }
        public async Task PushNewBuildAsync(
            BuildManifestLocation location,
            OrchestratedBuildModel build,
            IEnumerable <SupplementaryUploadRequest> supplementaryUploads,
            string message)
        {
            await Retry.RunAsync(async attempt =>
            {
                GitReference remoteRef = await _github.GetReferenceAsync(
                    location.GitHubProject,
                    location.GitHubRef);

                string remoteCommit = remoteRef.Object.Sha;

                Trace.TraceInformation($"Creating update on remote commit: {remoteCommit}");

                IEnumerable <SupplementaryUploadRequest> uploads = supplementaryUploads.NullAsEmpty()
                                                                   .Concat(new[]
                {
                    new SupplementaryUploadRequest
                    {
                        Path     = BuildManifestXmlName,
                        Contents = build.ToXml().ToString()
                    },
                    new SupplementaryUploadRequest
                    {
                        Path     = SemaphoreModel.BuildSemaphorePath,
                        Contents = new SemaphoreModel
                        {
                            BuildId = build.Identity.BuildId
                        }.ToFileContent()
                    }
                })
                                                                   .ToArray();

                return(await PushUploadsAsync(location, message, remoteCommit, uploads));
            });
        }
Beispiel #23
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GitHubCommit"/> class.
 /// </summary>
 /// <param name="branch">The branch with this commit.</param>
 /// <param name="source">The Octokit commit.</param>
 internal GitHubCommit(GitHubBranch branch, GitReference source)
 {
     Branch = branch;
     Source = source;
 }
        /// <param name="updateLatestVersion">If true, updates Latest.txt with a prerelease moniker. If there isn't one, makes the file empty.</param>
        /// <param name="updateLatestPackageList">If true, updates Latest_Packages.txt.</param>
        /// <param name="updateLastBuildPackageList">If true, updates Last_Build_Packages.txt, and enables keeping old packages in Latest_Packages.txt.</param>
        public async Task UpdateBuildInfoAsync(
            IEnumerable <string> packagePaths,
            string versionsRepoPath,
            bool updateLatestPackageList    = true,
            bool updateLatestVersion        = true,
            bool updateLastBuildPackageList = true)
        {
            if (packagePaths == null)
            {
                throw new ArgumentNullException(nameof(packagePaths));
            }
            if (versionsRepoPath == null)
            {
                throw new ArgumentNullException(nameof(versionsRepoPath));
            }

            NupkgInfo[] packages = CreatePackageInfos(packagePaths).ToArray();

            string prereleaseVersion = GetPrereleaseVersion(packages);

            Dictionary <string, string> packageDictionary = CreatePackageInfoDictionary(packages);

            using (GitHubClient client = new GitHubClient(_gitHubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        // Master commit to use as new commit's parent.
                        string       masterRef     = "heads/master";
                        GitReference currentMaster = await client.GetReferenceAsync(_project, masterRef);

                        string masterSha = currentMaster.Object.Sha;

                        List <GitObject> objects = new List <GitObject>();

                        if (updateLastBuildPackageList)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/{BuildInfo.LastBuildPackagesTxtFilename}",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(packageDictionary)
                            });
                        }

                        if (updateLatestPackageList)
                        {
                            var allPackages = new Dictionary <string, string>(packageDictionary);

                            if (updateLastBuildPackageList)
                            {
                                await AddExistingPackages(
                                    client,
                                    new GitHubBranch("master", _project),
                                    versionsRepoPath,
                                    allPackages);
                            }

                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/{BuildInfo.LatestPackagesTxtFilename}",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(allPackages)
                            });
                        }

                        if (updateLatestVersion)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/{BuildInfo.LatestTxtFilename}",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = prereleaseVersion
                            });
                        }

                        string message = $"Updating {versionsRepoPath}";
                        if (string.IsNullOrEmpty(prereleaseVersion))
                        {
                            message += ". No prerelease versions published.";
                        }
                        else
                        {
                            message += $" for {prereleaseVersion}";
                        }

                        GitTree tree = await client.PostTreeAsync(_project, masterSha, objects.ToArray());

                        GitCommit commit = await client.PostCommitAsync(_project, message, tree.Sha, new[] { masterSha });

                        // Only fast-forward. Don't overwrite other changes: throw exception instead.
                        await client.PatchReferenceAsync(_project, masterRef, commit.Sha, force : false);

                        Trace.TraceInformation($"Committed build-info update on attempt {i + 1}.");
                        break;
                    }
                    catch (Exception ex) when(ex is HttpRequestException || ex is NotFastForwardUpdateException)
                    {
                        int nextTry = i + 1;

                        if (nextTry < MaxTries)
                        {
                            Trace.TraceInformation($"Encountered exception committing build-info update: {ex.Message}");
                            Trace.TraceInformation($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - nextTry} tries left.");
                            await Task.Delay(RetryMillisecondsDelay);
                        }
                        else
                        {
                            Trace.TraceInformation("Encountered exception committing build-info update.");
                            throw;
                        }
                    }
                }
            }
        }
Beispiel #25
0
        /// <param name="updateLatestVersion">If true, updates Latest.txt with a prerelease moniker. If there isn't one, makes the file empty.</param>
        /// <param name="updateLatestPackageList">If true, updates Latest_Packages.txt.</param>
        /// <param name="updateLastBuildPackageList">If true, updates Last_Build_Packages.txt, and enables keeping old packages in Latest_Packages.txt.</param>
        public async Task UpdateBuildInfoAsync(
            IEnumerable <string> packagePaths,
            string versionsRepoPath,
            bool updateLatestPackageList    = true,
            bool updateLatestVersion        = true,
            bool updateLastBuildPackageList = true)
        {
            if (packagePaths == null)
            {
                throw new ArgumentNullException(nameof(packagePaths));
            }
            if (versionsRepoPath == null)
            {
                throw new ArgumentNullException(nameof(versionsRepoPath));
            }

            NupkgInfo[] packages = CreatePackageInfos(packagePaths).ToArray();

            string prereleaseVersion = packages
                                       .Select(t => t.Prerelease)
                                       .FirstOrDefault(prerelease => !string.IsNullOrEmpty(prerelease))
                                       ?? "stable";

            Dictionary <string, string> packageDictionary = CreatePackageInfoDictionary(packages);

            using (GitHubClient client = new GitHubClient(_gitHubAuth))
            {
                for (int i = 0; i < MaxTries; i++)
                {
                    try
                    {
                        // Master commit to use as new commit's parent.
                        string       masterRef     = "heads/master";
                        GitReference currentMaster = await client.GetReferenceAsync(_project, masterRef);

                        string masterSha = currentMaster.Object.Sha;

                        List <GitObject> objects = new List <GitObject>();

                        if (updateLastBuildPackageList)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/Last_Build_Packages.txt",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(packageDictionary)
                            });
                        }

                        if (updateLatestPackageList)
                        {
                            string latestPackagesPath = $"{versionsRepoPath}/Latest_Packages.txt";

                            var allPackages = new Dictionary <string, string>(packageDictionary);

                            if (updateLastBuildPackageList)
                            {
                                Dictionary <string, string> existingPackages = await GetPackagesAsync(client, latestPackagesPath);

                                if (existingPackages == null)
                                {
                                    Trace.TraceInformation(
                                        "No exising Latest_Packages file found; one will be " +
                                        $"created in '{versionsRepoPath}'");
                                }
                                else
                                {
                                    // Add each existing package if there isn't a new package with the same id.
                                    foreach (var package in existingPackages)
                                    {
                                        if (!allPackages.ContainsKey(package.Key))
                                        {
                                            allPackages[package.Key] = package.Value;
                                        }
                                    }
                                }
                            }

                            objects.Add(new GitObject
                            {
                                Path    = latestPackagesPath,
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = CreatePackageListContent(allPackages)
                            });
                        }

                        if (updateLatestVersion)
                        {
                            objects.Add(new GitObject
                            {
                                Path    = $"{versionsRepoPath}/Latest.txt",
                                Type    = GitObject.TypeBlob,
                                Mode    = GitObject.ModeFile,
                                Content = prereleaseVersion
                            });
                        }

                        string message = $"Updating {versionsRepoPath}";
                        if (string.IsNullOrEmpty(prereleaseVersion))
                        {
                            message += ". No prerelease versions published.";
                        }
                        else
                        {
                            message += $" for {prereleaseVersion}";
                        }

                        GitTree tree = await client.PostTreeAsync(_project, masterSha, objects.ToArray());

                        GitCommit commit = await client.PostCommitAsync(_project, message, tree.Sha, new[] { masterSha });

                        // Only fast-forward. Don't overwrite other changes: throw exception instead.
                        await client.PatchReferenceAsync(_project, masterRef, commit.Sha, force : false);

                        Trace.TraceInformation($"Committed build-info update on attempt {i + 1}.");
                        break;
                    }
                    catch (HttpRequestException ex)
                    {
                        int nextTry = i + 1;
                        if (nextTry < MaxTries)
                        {
                            Trace.TraceInformation($"Encountered exception committing build-info update: {ex.Message}");
                            Trace.TraceInformation($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - nextTry} tries left.");
                            await Task.Delay(RetryMillisecondsDelay);
                        }
                        else
                        {
                            Trace.TraceInformation("Encountered exception committing build-info update.");
                            throw;
                        }
                    }
                }
            }
        }
        public async Task PushChangeAsync(BuildManifestChange change)
        {
            await Retry.RunAsync(async attempt =>
            {
                BuildManifestLocation location = change.Location;

                // Get the current commit. Use this throughout to ensure a clean transaction.
                GitReference remoteRef = await _github.GetReferenceAsync(
                    location.GitHubProject,
                    location.GitHubRef);

                string remoteCommit = remoteRef.Object.Sha;

                Trace.TraceInformation($"Creating update on remote commit: {remoteCommit}");

                XElement remoteModelXml = await FetchModelXmlAsync(
                    location.GitHubProject,
                    remoteCommit,
                    location.GitHubBasePath);

                OrchestratedBuildModel remoteModel = OrchestratedBuildModel.Parse(remoteModelXml);

                // This is a subsequent publish step: make sure a new build hasn't happened already.
                if (change.OrchestratedBuildId != remoteModel.Identity.BuildId)
                {
                    throw new ManifestChangeOutOfDateException(
                        change.OrchestratedBuildId,
                        remoteModel.Identity.BuildId);
                }

                OrchestratedBuildModel modifiedModel = OrchestratedBuildModel.Parse(remoteModelXml);
                change.ApplyModelChanges(modifiedModel);

                if (modifiedModel.Identity.BuildId != change.OrchestratedBuildId)
                {
                    throw new ArgumentException(
                        "Change action shouldn't modify BuildId. Changed from " +
                        $"'{change.OrchestratedBuildId}' to '{modifiedModel.Identity.BuildId}'.",
                        nameof(change));
                }

                XElement modifiedModelXml = modifiedModel.ToXml();

                string[] changedSemaphorePaths = change.SemaphorePaths.ToArray();

                // Check if any join groups are completed by this change.
                var joinCompleteCheckTasks = change.JoinSemaphoreGroups.NullAsEmpty()
                                             .Select(async g => new
                {
                    Group    = g,
                    Joinable = await IsGroupJoinableAsync(
                        location,
                        remoteCommit,
                        change.OrchestratedBuildId,
                        changedSemaphorePaths,
                        g)
                });

                var completeJoinedSemaphores = (await Task.WhenAll(joinCompleteCheckTasks))
                                               .Where(g => g.Joinable)
                                               .Select(g => g.Group.JoinSemaphorePath)
                                               .ToArray();

                IEnumerable <SupplementaryUploadRequest> semaphoreUploads = completeJoinedSemaphores
                                                                            .Concat(changedSemaphorePaths)
                                                                            .Select(p => new SupplementaryUploadRequest
                {
                    Path     = p,
                    Contents = new SemaphoreModel
                    {
                        BuildId = change.OrchestratedBuildId
                    }.ToFileContent()
                });

                IEnumerable <SupplementaryUploadRequest> uploads =
                    semaphoreUploads.Concat(change.SupplementaryUploads.NullAsEmpty());

                if (!XNode.DeepEquals(modifiedModelXml, remoteModelXml))
                {
                    uploads = uploads.Concat(new[]
                    {
                        new SupplementaryUploadRequest
                        {
                            Path     = BuildManifestXmlName,
                            Contents = modifiedModelXml.ToString()
                        }
                    });
                }

                return(await PushUploadsAsync(
                           location,
                           change.CommitMessage,
                           remoteCommit,
                           uploads));
            });
        }
Beispiel #27
0
        public void UseGitClient()
        {
            GitCommitArgs ga = new GitCommitArgs();

            ga.Author.Name            = "Tester";
            ga.Author.EmailAddress    = "*****@*****.**";
            ga.Signature.Name         = "Other";
            ga.Signature.EmailAddress = "*****@*****.**";

            // Use stable time and offset to always produce the same hash
            DateTime ct = new DateTime(2002, 01, 01, 0, 0, 0, DateTimeKind.Utc);

            ga.Author.When = ct;
            ga.Author.TimeOffsetInMinutes    = 120;
            ga.Signature.When                = ct;
            ga.Signature.TimeOffsetInMinutes = 120;

            string repoDir  = GetTempPath();
            string repo2Dir = GetTempPath();
            GitId  firstResult;
            GitId  lastCommit;

            using (GitRepository repo = GitRepository.Create(repoDir))
                using (GitClient git = new GitClient())
                {
                    string ignoreFile   = Path.Combine(repoDir, ".gitignore");
                    string file         = Path.Combine(repoDir, "newfile");
                    string subDir       = Path.Combine(repoDir, "dir");
                    string fileInSubDir = Path.Combine(subDir, "file2");
                    string file3        = Path.Combine(repoDir, "other");
                    string file4        = Path.Combine(repoDir, "q.ignore");
                    File.WriteAllText(file, "Some body");
                    Directory.CreateDirectory(subDir);
                    File.WriteAllText(fileInSubDir, "Some other body");
                    File.WriteAllText(file3, "file3");

                    File.WriteAllText(ignoreFile, "*.ignore\n");
                    File.WriteAllText(file4, "file4");

                    git.Add(ignoreFile);
                    git.Add(file);
                    git.Commit(repoDir, ga, out firstResult);

                    git.Add(fileInSubDir);

                    int ticked = 0;

                    File.AppendAllText(file, "\nExtra Line");

                    GitStatusArgs gsa = new GitStatusArgs();
                    gsa.IncludeIgnored    = true;
                    gsa.IncludeUnmodified = true;

                    Assert.That(git.Status(repoDir, gsa,
                                           delegate(object sender, GitStatusEventArgs e)
                    {
                        switch (e.RelativePath)
                        {
                        case "newfile":
                            //Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Added));
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Normal), "newfile index normal");
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal), "newfile wc modified");
                            Assert.That(e.WorkingDirectoryModified);
                            Assert.That(e.Ignored, Is.False);
                            break;

                        case "dir/file2":
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.New), "file2 index added");
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal), "file2 wc normal");
                            Assert.That(e.Ignored, Is.False);
                            break;

                        case "other":
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None));
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New));
                            Assert.That(e.Ignored, Is.False);
                            break;

                        case ".gitignore":
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Normal));
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal));
                            Assert.That(e.Ignored, Is.False);
                            break;

                        case "q.ignore":
                            // TODO: Make this ignored
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None));
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Normal));
                            Assert.That(e.Ignored, Is.True);
                            break;

                        default:
                            Assert.Fail("Invalid node found: {0}", e.RelativePath);
                            break;
                        }

                        Assert.That(e.FullPath, Is.EqualTo(Path.GetFullPath(Path.Combine(repoDir, e.RelativePath))));
                        ticked++;
                    }), Is.True);

                    Assert.That(ticked, Is.EqualTo(5), "Ticked");

                    ga.LogMessage = "Intermediate";
                    git.Commit(repoDir, ga);

                    Assert.That(git.Delete(fileInSubDir));
                    Assert.That(git.Add(file));

                    GitId commit;

                    ga.LogMessage = "A log message to remember";

                    // The passed path is currently just used to find the local repository
                    lastCommit = new GitId("996cf198b49ed6fce3bcba232e2d88eb473560f9");

                    Assert.That(git.Commit(repoDir, ga, out commit));
                    Assert.That(commit, Is.EqualTo(lastCommit));

                    File.Move(file, file + ".a");

                    ticked                 = 0;
                    gsa.IncludeIgnored     = false;
                    gsa.IncludeUnversioned = true;
                    gsa.IncludeUnmodified  = false;
                    Assert.That(git.Status(repoDir, gsa,
                                           delegate(object sender, GitStatusEventArgs e)
                    {
                        switch (e.RelativePath)
                        {
                        /*case "dir":
                         *  Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.Normal), "dir index normal");
                         *  Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New), "dir wc normal");
                         *  break;*/
                        case "newfile":
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None), "newfile index normal");
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.Deleted), "newfile wc deleted");
                            break;

                        case "newfile.a":
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None), "newfile.a index normal");
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New), "newfile.a wc new");
                            break;

                        case "other":
                            Assert.That(e.IndexStatus, Is.EqualTo(GitStatus.None), "other index normal");
                            Assert.That(e.WorkingDirectoryStatus, Is.EqualTo(GitStatus.New), "other wc normal");
                            break;

                        default:
                            Assert.Fail("Invalid node found: {0}", e.RelativePath);
                            break;
                        }

                        Assert.That(e.FullPath, Is.EqualTo(Path.GetFullPath(Path.Combine(repoDir, e.RelativePath))));
                        ticked++;
                    }), Is.True);

                    Assert.That(ticked, Is.EqualTo(3));

                    GitCloneArgs gc = new GitCloneArgs();
                    gc.Synchronous = true;

                    git.Clone(repoDir, repo2Dir, gc);

                    GitCommit theCommit;
                    Assert.That(repo.Lookup(commit, out theCommit));
                    Assert.That(repo.Branches.Create(theCommit, "vNext"));
                    Assert.That(repo.Branches, Is.Not.Empty);
                }

            using (GitRepository repo1 = new GitRepository(repoDir))
                using (GitRepository repo2 = new GitRepository(repo2Dir))
                {
                    GitReference head = repo1.HeadReference;
                    Assert.That(head, Is.Not.Null, "Has head");

                    Assert.That(head.Name, Is.EqualTo("refs/heads/master"));
                    //Assert.That(repo2.Head, Is.Not.Null);

                    GitId headId;
                    Assert.That(repo1.ResolveReference(repo1.HeadReference, out headId));
                    Assert.That(headId, Is.EqualTo(lastCommit));
                    GitCommit commit;

                    Assert.That(repo1.Lookup(headId, out commit));
                    Assert.That(commit, Is.Not.Null, "Have a commit");

                    Assert.That(commit.Id, Is.EqualTo(lastCommit));
                    Assert.That(commit.Ancestors, Is.Not.Empty);
                    Assert.That(commit.Ancestor, Is.Not.Null);
                    Assert.That(commit.Ancestor.Ancestor, Is.Not.Null);
                    Assert.That(commit.Ancestor.Ancestor.Ancestor, Is.Null);
                    Assert.That(commit.Ancestor.Ancestor.Id, Is.EqualTo(firstResult));

                    Assert.That(commit.Author, Is.Not.Null);
                    Assert.That(commit.Author.Name, Is.EqualTo("Tester"));
                    Assert.That(commit.Author.EmailAddress, Is.EqualTo("*****@*****.**"));

                    Assert.That(commit.Committer, Is.Not.Null);
                    Assert.That(commit.Committer.Name, Is.EqualTo("Other"));
                    Assert.That(commit.Committer.EmailAddress, Is.EqualTo("*****@*****.**"));

                    Assert.That(commit.Committer.TimeOffsetInMinutes, Is.EqualTo(120), "Time offset"); // CEST dependent
                    Assert.That(commit.Committer.When, Is.EqualTo(ct), "Exact time");
                    Assert.That(commit.LogMessage, Is.EqualTo("A log message to remember\n"));

                    Assert.That(commit.Parents, Is.Not.Empty);
                    Assert.That(commit.ParentIds, Is.Not.Empty);

                    Assert.That(commit.Tree, Is.Not.Empty);
                    Assert.That(commit.Tree.Count, Is.EqualTo(2));
                    Assert.That(commit.Ancestor.Tree.Count, Is.EqualTo(3));
                    Assert.That(commit.Ancestor.Ancestor.Tree.Count, Is.EqualTo(2));
                    Assert.That(commit.Tree.Id, Is.Not.EqualTo(commit.Ancestor.Tree.Id));

                    GitId id;
                    Assert.That(repo1.LookupViaPrefix(commit.Id.ToString(), out id));
                    Assert.That(id, Is.EqualTo(commit.Id));

                    Assert.That(repo1.LookupViaPrefix(commit.Id.ToString().Substring(0, 10), out id));
                    Assert.That(id, Is.EqualTo(commit.Id));

                    Assert.That(commit.Peel <GitObject>().Id, Is.EqualTo(commit.Tree.Id));
                    Assert.That(commit.Peel <GitTree>(), Is.EqualTo(commit.Tree)); // Compares members
                    Assert.That(commit.Tree.Peel <GitObject>(), Is.Null);

                    GitTagArgs ta = new GitTagArgs();
                    ta.Signature.When             = ct;
                    ta.Signature.Name             = "Me";
                    ta.Signature.EmailAddress     = "[email protected]";
                    ta.LogMessage                 = "Some message";
                    ga.Author.TimeOffsetInMinutes = 120;
                    Assert.That(commit.Tag("MyTag", ta, out id));
                    Assert.That(id, Is.EqualTo(new GitId("db31f8333fc64d7e7921ea91f6e007b755dcfcbb")));

                    GitTag tag;
                    Assert.That(repo1.Lookup(id, out tag));
                    Assert.That(tag, Is.Not.Null);
                    Assert.That(tag.Name, Is.EqualTo("MyTag"));
                    Assert.That(tag.LogMessage, Is.EqualTo("Some message\n"));
                    Assert.That(tag.Tagger.Name, Is.EqualTo("Me"));

                    Assert.That(tag.Target.Id, Is.EqualTo(commit.Id));
                    Assert.That(tag.Peel <GitTree>(), Is.EqualTo(commit.Peel <GitTree>()));

                    repo1.CheckOut(commit.Tree);

                    //Console.WriteLine("1:");
                    //foreach (GitTreeEntry e in commit.Tree)
                    //{
                    //    Console.WriteLine(string.Format("{0}: {1} ({2})", e.Name, e.Kind, e.Children.Count));
                    //}

                    //Console.WriteLine("2:");
                    //foreach (GitTreeEntry e in commit.Ancestor.Tree)
                    //{
                    //    Console.WriteLine(string.Format("{0}: {1} ({2})", e.Name, e.Kind, e.Children.Count));
                    //}

                    //Console.WriteLine("3:");
                    //foreach (GitTreeEntry e in commit.Ancestor.Ancestor.Tree)
                    //{
                    //    Console.WriteLine(string.Format("{0}: {1} ({2})", e.Name, e.Kind, e.Children.Count));
                    //}
                    //Console.WriteLine("-");
                }
        }
Beispiel #28
0
        public void PerformsCommitSerialization()
        {
            var tree = new GitReference {
                Sha = "tree-reference", Url = "tree-url"
            };
            var parent1 = new GitReference {
                Sha = "parent1-reference", Url = "parent1-url"
            };
            var parent2 = new GitReference {
                Sha = "parent2-reference", Url = "parent2-url"
            };

            var author = new Signature
            {
                Name  = "author-name",
                Email = "author-email",
                Date  = new DateTime(2013, 10, 15, 13, 40, 14, DateTimeKind.Utc)
            };

            var committer = new Signature {
                Name  = "committer-name",
                Email = "committer-email",
                Date  = new DateTime(2013, 06, 29, 10, 12, 50, DateTimeKind.Utc)
            };

            var commit = new Commit
            {
                Sha       = "commit-reference",
                Url       = "commit-url",
                Message   = "commit-message",
                Parents   = new[] { parent1, parent2 },
                Tree      = tree,
                Author    = author,
                Committer = committer,
            };

            var json = new SimpleJsonSerializer().Serialize(commit);

            const string expectedResult = "{\"message\":\"commit-message\"," +
                                          "\"author\":{" +
                                          "\"name\":\"author-name\"," +
                                          "\"email\":\"author-email\"," +
                                          "\"date\":\"2013-10-15T13:40:14Z\"" +
                                          "}," +
                                          "\"committer\":{" +
                                          "\"name\":\"committer-name\"," +
                                          "\"email\":\"committer-email\"," +
                                          "\"date\":\"2013-06-29T10:12:50Z\"" +
                                          "}," +
                                          "\"tree\":{" +
                                          "\"url\":\"tree-url\"," +
                                          "\"sha\":\"tree-reference\"" +
                                          "}," +
                                          "\"parents\":[{" +
                                          "\"url\":\"parent1-url\"," +
                                          "\"sha\":\"parent1-reference\"" +
                                          "}," +
                                          "{" +
                                          "\"url\":\"parent2-url\"," +
                                          "\"sha\":\"parent2-reference\"" +
                                          "}]," +
                                          "\"url\":\"commit-url\"," +
                                          "\"sha\":\"commit-reference\"" +
                                          "}";

            Assert.Equal(expectedResult, json);
        }
Beispiel #29
0
 public virtual IAsyncEnumerable <GitReferenceChange>?GetChanges(GitReference reference)
 {
     return(default);
Beispiel #30
0
        private async ValueTask CommitUpdateFileReferences()
        {
            foreach (var v in Updates.Where(x => x.Type == UpdateType.Verify))
            {
                var r = await _referenceRepository.GetAsync(v.Name).ConfigureAwait(false);

                if (r is null || r.Id != v.Id)
                {
                    throw new GitException($"Reference {v.Name} is not {v.Id}, but {r?.Id ?? Zero}");
                }
            }

            Action?unlock        = null;
            string?hookData      = null;
            bool?  logRefUpdates = null;

            try
            {
                foreach (var v in Updates.Select(x => x.Name).Distinct())
                {
                    var name = v;
                    if (GitReference.AllUpper(name))
                    {
                        var rf = await _referenceRepository.GetAsync(v).ConfigureAwait(false);

                        if (rf is GitSymbolicReference sr)
                        {
                            rf = await sr.ResolveAsync().ConfigureAwait(false);

                            name = (rf as GitSymbolicReference)?.ReferenceName ?? rf.Name ?? name;
                        }
                    }

                    string path = Path.Combine(Repository.GitDirectory, name);
                    Directory.CreateDirectory(Path.GetDirectoryName(path) !);

                    string p = path + ".lock";
#pragma warning disable CA2000 // Dispose objects before losing scope
                    var f = new FileStream(path + ".lock", FileMode.CreateNew);
#pragma warning restore CA2000 // Dispose objects before losing scope

                    unlock += () => { f.Close(); File.Delete(p); };
                }


                bool allowContinue = true;

                if (!string.IsNullOrEmpty(GitConfiguration.GitProgramPath) &&
                    await Repository.Configuration.HookExistsAsync("reference-transaction").ConfigureAwait(false))
                {
                    StringBuilder sb = new StringBuilder();

                    foreach (var v in Updates)
                    {
                        GitReference?rf;

                        // We might record 'HEAD' when we really update something like 'refs/heads/main'
                        // This might need fixing when things are fixed in git itself
                        switch (v.Type)
                        {
                        case UpdateType.Create:
                            sb.Append(Zero);
                            sb.Append(' ');
                            sb.Append(v.Id);
                            sb.Append(' ');
                            sb.Append(v.Name);
                            sb.Append('\n');
                            break;

                        case UpdateType.Update:
                            rf = await _referenceRepository.GetAsync(v.Name).ConfigureAwait(false);

                            sb.Append(rf?.Id ?? Zero);
                            sb.Append(' ');
                            sb.Append(v.Id);
                            sb.Append(' ');
                            sb.Append(v.Name);
                            sb.Append('\n');
                            break;

                        case UpdateType.Delete:
                            rf = await _referenceRepository.GetAsync(v.Name).ConfigureAwait(false);

                            if (rf?.Id != null)
                            {
                                sb.Append(rf.Id);
                                sb.Append(' ');
                                sb.Append(Zero);
                                sb.Append(' ');
                                sb.Append(v.Name);
                                sb.Append('\n');
                            }
                            break;
                        }
                    }

                    if (sb.Length > 0)
                    {
                        hookData = sb.ToString();
                    }

                    if (hookData is not null)
                    {
                        var r = await Repository.RunHookErrAsync("reference-transaction", new[] { "prepared" }, stdinText : hookData, expectedResults : Array.Empty <int>()).ConfigureAwait(false);

                        if (r.ExitCode != 0)
                        {
                            throw new GitException($"Git reference-transaction denied update: {r.OutputText} ({r.ErrorText})");
                        }
                    }
                }

                if (allowContinue)
                {
                    var signature = Repository.Configuration.Identity.AsRecord();
                    foreach (var v in Updates)
                    {
                        GitId?       originalId = null;
                        GitReference?rf         = null;
                        switch (v.Type)
                        {
                        case UpdateType.Create:
                            using (var fs = new FileStream(Path.Combine(Repository.GitDirectory, v.TargetName), FileMode.CreateNew))
                                using (var sw = new StreamWriter(fs))
                                {
                                    await sw.WriteLineAsync(v.Id !.ToString()).ConfigureAwait(false);
                                }
                            break;

                        case UpdateType.Update:
                            rf = await _referenceRepository.GetAsync(v.Name).ConfigureAwait(false);

                            if (rf is GitSymbolicReference sr)
                            {
                                rf = await sr.ResolveAsync().ConfigureAwait(false);

                                v.TargetName = (rf as GitSymbolicReference)?.ReferenceName ?? rf.Name ?? v.Name;
                            }
                            originalId = rf?.Id;
                            using (var fs = new FileStream(Path.Combine(Repository.GitDirectory, v.TargetName), FileMode.Create))
                                using (var sw = new StreamWriter(fs))
                                {
                                    fs.SetLength(0);
                                    await sw.WriteLineAsync(v.Id !.ToString()).ConfigureAwait(false);
                                }
                            break;

                        case UpdateType.Delete:
                            rf = await _referenceRepository.GetAsync(v.Name).ConfigureAwait(false);

                            if (rf is GitSymbolicReference sr2)
                            {
                                rf = await sr2.ResolveAsync().ConfigureAwait(false);

                                v.TargetName = rf.Name ?? v.Name;
                            }
                            originalId = rf?.Id;
                            File.Delete(Path.Combine(Repository.GitDirectory, v.TargetName));
                            // If failed here, we need to cleanup packed references!!
                            break;

                        default:
                            continue;
                        }

                        logRefUpdates ??= await Repository.Configuration.GetBoolAsync("core", "logallrefupdates").ConfigureAwait(false) ?? false;

                        if (logRefUpdates == true &&
                            (GitReference.AllUpper(v.Name) || v.Name.StartsWith("refs/heads/", StringComparison.OrdinalIgnoreCase) ||
                             v.Name.StartsWith("refs/remotes/", StringComparison.OrdinalIgnoreCase) || v.Name.StartsWith("refs/notes/", StringComparison.OrdinalIgnoreCase)))
                        {
                            var log = new GitReferenceLogRecord {
                                Original = originalId ?? Zero, Target = v.Id ?? Zero, Signature = signature, Reason = Reason
                            };

                            await AppendLog(v.Name, log).ConfigureAwait(false);

                            if (rf is not null && rf.Name != v.Name)
                            {
                                await AppendLog(rf.Name !, log).ConfigureAwait(false);
                            }
                        }
                    }

                    if (hookData is not null)
                    {
                        var hd = hookData;
                        hookData = null;
                        // Ignore errors
                        await Repository.RunHookErrAsync("run", new[] { "committed" }, stdinText : hd, expectedResults : Array.Empty <int>()).ConfigureAwait(false);
                    }
                }
            }
            catch when(hookData is not null)
            {
                // Ignore errors
                await Repository.RunHookErrAsync("run", new[] { "abort" }, stdinText : hookData, expectedResults : Array.Empty <int>()).ConfigureAwait(false);

                throw;
            }
            finally
            {
                unlock?.Invoke();
            }
        }