From 8c3c8b6d9df4fd4fab7c1a48d4d6b0ec811790d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Sep 2025 01:02:34 +0000 Subject: [PATCH] Add objectformat extension support for SHA256 repositories --- .../GitConfigTests.cs | 29 +++++ .../GitReferenceResolverTests.cs | 118 +++++++++++++++--- .../GitRepositoryTests.cs | 31 +++++ .../GitDataReader/GitConfig.cs | 29 ++++- .../GitDataReader/GitReferenceResolver.cs | 22 ++-- .../GitDataReader/GitRepository.cs | 4 +- .../GitDataReader/ObjectNameFormat.cs | 4 + 7 files changed, 205 insertions(+), 32 deletions(-) diff --git a/src/Microsoft.Build.Tasks.Git.UnitTests/GitConfigTests.cs b/src/Microsoft.Build.Tasks.Git.UnitTests/GitConfigTests.cs index 3627f609..19bee0d7 100644 --- a/src/Microsoft.Build.Tasks.Git.UnitTests/GitConfigTests.cs +++ b/src/Microsoft.Build.Tasks.Git.UnitTests/GitConfigTests.cs @@ -475,5 +475,34 @@ public void RefStorage_Invalid(string value) new GitConfig(ImmutableDictionary>.Empty .Add(new GitVariableName("extensions", "", "refStorage"), [value]))); } + + [Theory] + [InlineData(null, ObjectNameFormat.Sha1)] + [InlineData("sha1", ObjectNameFormat.Sha1)] + [InlineData("sha256", ObjectNameFormat.Sha256)] + internal void ParseObjectFormat(string? value, ObjectNameFormat expected) + { + var variables = ImmutableDictionary>.Empty; + if (value != null) + { + variables = variables.Add(new GitVariableName("extensions", "", "objectFormat"), [value]); + } + + Assert.Equal(expected, new GitConfig(variables).ObjectNameFormat); + } + + [Theory] + [InlineData("")] + [InlineData("Sha1")] + [InlineData("sha-1")] + [InlineData("sha-256")] + [InlineData("sha384")] + [InlineData("sha512")] + internal void ParseObjectFormat_Invalid(string value) + { + Assert.Throws(() => + new GitConfig(ImmutableDictionary>.Empty + .Add(new GitVariableName("extensions", "", "objectFormat"), [value]))); + } } } diff --git a/src/Microsoft.Build.Tasks.Git.UnitTests/GitReferenceResolverTests.cs b/src/Microsoft.Build.Tasks.Git.UnitTests/GitReferenceResolverTests.cs index abc3ddd4..d7d77300 100644 --- a/src/Microsoft.Build.Tasks.Git.UnitTests/GitReferenceResolverTests.cs +++ b/src/Microsoft.Build.Tasks.Git.UnitTests/GitReferenceResolverTests.cs @@ -25,7 +25,7 @@ public void ResolveReference() refsHeadsDir.CreateFile("br1").WriteAllText("ref: refs/heads/br2"); refsHeadsDir.CreateFile("br2").WriteAllText("ref: refs/heads/master"); - var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles); + using var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha1); Assert.Equal("0123456789ABCDEFabcdef000000000000000000", resolver.ResolveReference("0123456789ABCDEFabcdef000000000000000000")); @@ -33,13 +33,40 @@ public void ResolveReference() Assert.Equal("0000000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/br1")); Assert.Equal("0000000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/br2")); - // branch without commits (emtpy repository) will have not file in refs/heads: + // branch without commits (empty repository) will have not file in refs/heads: Assert.Null(resolver.ResolveReference("ref: refs/heads/none")); Assert.Null(resolver.ResolveReference("ref: refs/heads/rec1 ")); Assert.Null(resolver.ResolveReference("ref: refs/heads/none" + string.Join("/", Path.GetInvalidPathChars()))); } + [Fact] + public void ResolveReference_SHA256() + { + using var temp = new TempRoot(); + + var gitDir = temp.CreateDirectory(); + + var commonDir = temp.CreateDirectory(); + var refsHeadsDir = commonDir.CreateDirectory("refs").CreateDirectory("heads"); + + // SHA256 hash (64 characters) + refsHeadsDir.CreateFile("master").WriteAllText("0000000000000000000000000000000000000000000000000000000000000000"); + refsHeadsDir.CreateFile("br1").WriteAllText("ref: refs/heads/br2"); + refsHeadsDir.CreateFile("br2").WriteAllText("ref: refs/heads/master"); + + using var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha256); + + // Verify SHA256 hash is accepted directly + Assert.Equal( + "0123456789ABCDEFabcdef000000000000000000000000000000000000000000", + resolver.ResolveReference("0123456789ABCDEFabcdef000000000000000000000000000000000000000000")); + + Assert.Equal("0000000000000000000000000000000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/master")); + Assert.Equal("0000000000000000000000000000000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/br1")); + Assert.Equal("0000000000000000000000000000000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/br2")); + } + [Fact] public void ResolveReference_Errors() { @@ -53,14 +80,24 @@ public void ResolveReference_Errors() refsHeadsDir.CreateFile("rec1").WriteAllText("ref: refs/heads/rec2"); refsHeadsDir.CreateFile("rec2").WriteAllText("ref: refs/heads/rec1"); - var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles); + using var resolver1 = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha1); + + Assert.Throws(() => resolver1.ResolveReference("ref: refs/heads/rec1")); + Assert.Throws(() => resolver1.ResolveReference("ref: xyz/heads/rec1")); + Assert.Throws(() => resolver1.ResolveReference("ref:refs/heads/rec1")); + Assert.Throws(() => resolver1.ResolveReference("refs/heads/rec1")); + + // Invalid SHA1 hash lengths + Assert.Throws(() => resolver1.ResolveReference(new string('0', ObjectNameFormat.Sha1.HashSize * 2 - 1))); + Assert.Throws(() => resolver1.ResolveReference(new string('0', ObjectNameFormat.Sha1.HashSize * 2 + 1))); + Assert.Throws(() => resolver1.ResolveReference(new string('0', ObjectNameFormat.Sha256.HashSize * 2))); - Assert.Throws(() => resolver.ResolveReference("ref: refs/heads/rec1")); - Assert.Throws(() => resolver.ResolveReference("ref: xyz/heads/rec1")); - Assert.Throws(() => resolver.ResolveReference("ref:refs/heads/rec1")); - Assert.Throws(() => resolver.ResolveReference("refs/heads/rec1")); - Assert.Throws(() => resolver.ResolveReference(new string('0', 39))); - Assert.Throws(() => resolver.ResolveReference(new string('0', 41))); + using var resolver2 = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha256); + + // Invalid SHA256 hash lengths + Assert.Throws(() => resolver2.ResolveReference(new string('0', ObjectNameFormat.Sha256.HashSize * 2 - 1))); + Assert.Throws(() => resolver2.ResolveReference(new string('0', ObjectNameFormat.Sha256.HashSize * 2 + 1))); + Assert.Throws(() => resolver2.ResolveReference(new string('0', ObjectNameFormat.Sha1.HashSize * 2))); } [Fact] @@ -80,13 +117,38 @@ 2222222222222222222222222222222222222222 refs/heads/br2 refsHeadsDir.CreateFile("br1").WriteAllText("ref: refs/heads/br2"); - var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles); + using var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha1); Assert.Equal("1111111111111111111111111111111111111111", resolver.ResolveReference("ref: refs/heads/master")); Assert.Equal("2222222222222222222222222222222222222222", resolver.ResolveReference("ref: refs/heads/br1")); Assert.Equal("2222222222222222222222222222222222222222", resolver.ResolveReference("ref: refs/heads/br2")); } + [Fact] + public void ResolveReference_Packed_SHA256() + { + using var temp = new TempRoot(); + + var gitDir = temp.CreateDirectory(); + + // Packed refs with SHA256 hashes (64 characters) + gitDir.CreateFile("packed-refs").WriteAllText( +@"# pack-refs with: peeled fully-peeled sorted +1111111111111111111111111111111111111111111111111111111111111111 refs/heads/master +2222222222222222222222222222222222222222222222222222222222222222 refs/heads/br2 +"); + var commonDir = temp.CreateDirectory(); + var refsHeadsDir = commonDir.CreateDirectory("refs").CreateDirectory("heads"); + + refsHeadsDir.CreateFile("br1").WriteAllText("ref: refs/heads/br2"); + + using var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha256); + + Assert.Equal("1111111111111111111111111111111111111111111111111111111111111111", resolver.ResolveReference("ref: refs/heads/master")); + Assert.Equal("2222222222222222222222222222222222222222222222222222222222222222", resolver.ResolveReference("ref: refs/heads/br1")); + Assert.Equal("2222222222222222222222222222222222222222222222222222222222222222", resolver.ResolveReference("ref: refs/heads/br2")); + } + [Fact] public void ReadPackedReferences() { @@ -101,7 +163,8 @@ 6666666666666666666666666666666666666666 y z 7777777777777777777777777777777777777777 refs/heads/br "; - var actual = GitReferenceResolver.ReadPackedReferences(new StringReader(packedRefs), ""); + using var resolver = new GitReferenceResolver(TempRoot.Root, TempRoot.Root, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha1); + var actual = resolver.ReadPackedReferences(new StringReader(packedRefs), ""); AssertEx.SetEqual(new[] { @@ -110,26 +173,53 @@ 7777777777777777777777777777777777777777 refs/heads/br }, actual.Select(e => $"{e.Key}:{e.Value}")); } + [Fact] + public void ReadPackedReferences_SHA256() + { + var packedRefs = +@"# pack-refs with: +1111111111111111111111111111111111111111111111111111111111111111 refs/heads/master +2222222222222222222222222222222222222222222222222222222222222222 refs/heads/br +^3333333333333333333333333333333333333333333333333333333333333333 +4444444444444444444444444444444444444444444444444444444444444444 x +5555555555555555555555555555555555555555555555555555555555555555 y +6666666666666666666666666666666666666666666666666666666666666666 y z +7777777777777777777777777777777777777777777777777777777777777777 refs/heads/br +"; + + using var resolver = new GitReferenceResolver(TempRoot.Root, TempRoot.Root, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha256); + var actual = resolver.ReadPackedReferences(new StringReader(packedRefs), ""); + + AssertEx.SetEqual(new[] + { + "refs/heads/br:2222222222222222222222222222222222222222222222222222222222222222", + "refs/heads/master:1111111111111111111111111111111111111111111111111111111111111111" + }, actual.Select(e => $"{e.Key}:{e.Value}")); + } + [Theory] [InlineData("# pack-refs with:")] [InlineData("# pack-refs with:xyz")] [InlineData("# pack-refs with:xyz\n")] public void ReadPackedReferences_Empty(string content) { - Assert.Empty(GitReferenceResolver.ReadPackedReferences(new StringReader(content), "")); + using var resolver = new GitReferenceResolver(TempRoot.Root, TempRoot.Root, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha256); + Assert.Empty(resolver.ReadPackedReferences(new StringReader(content), "")); } [Theory] [InlineData("")] // missing header [InlineData("# pack-refs with")] // invalid header prefix [InlineData("# pack-refs with:xyz\n1")] // bad object id + [InlineData("# pack-refs with:xyz\n^2222222222222222222222222222222222222222222222222222222222222222")] // bad object id: sha256 [InlineData("# pack-refs with:xyz\n1111111111111111111111111111111111111111")] // no reference name [InlineData("# pack-refs with:xyz\n^1111111111111111111111111111111111111111")] // tag dereference without previous ref [InlineData("# pack-refs with:xyz\n1111111111111111111111111111111111111111 x\n^1")] // bad object id [InlineData("# pack-refs with:xyz\n^1111111111111111111111111111111111111111\n^2222222222222222222222222222222222222222")] // tag dereference without previous ref public void ReadPackedReferences_Errors(string content) { - Assert.Throws(() => GitReferenceResolver.ReadPackedReferences(new StringReader(content), "")); + using var resolver = new GitReferenceResolver(TempRoot.Root, TempRoot.Root, ReferenceStorageFormat.LooseFiles, ObjectNameFormat.Sha1); + Assert.Throws(() => resolver.ReadPackedReferences(new StringReader(content), "")); } [Fact] @@ -150,7 +240,7 @@ public void ResolveReference_RefTable() var ref1 = refTableDir.CreateFile("1.ref").WriteAllBytes(GitRefTableTestWriter.GetRefTableBlob([("refs/heads/a", 0x01), ("refs/heads/c", 0x02)])); TempFile ref2; - using (var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.RefTable)) + using (var resolver = new GitReferenceResolver(gitDir.Path, commonDir.Path, ReferenceStorageFormat.RefTable, ObjectNameFormat.Sha1)) { Assert.Equal("0100000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/a")); Assert.Equal("0200000000000000000000000000000000000000", resolver.ResolveReference("ref: refs/heads/c")); diff --git a/src/Microsoft.Build.Tasks.Git.UnitTests/GitRepositoryTests.cs b/src/Microsoft.Build.Tasks.Git.UnitTests/GitRepositoryTests.cs index 5e1d8d95..895b9a96 100644 --- a/src/Microsoft.Build.Tasks.Git.UnitTests/GitRepositoryTests.cs +++ b/src/Microsoft.Build.Tasks.Git.UnitTests/GitRepositoryTests.cs @@ -226,6 +226,7 @@ public void OpenRepository_Version1_Extensions() preciousObjects = true partialClone = promisor_remote worktreeConfig = true + objectformat = sha256 "); Assert.True(GitRepository.TryFindRepository(gitDir.Path, out var location)); @@ -264,6 +265,36 @@ public void OpenRepository_Version1_UnknownExtension() Assert.Throws(() => GitRepository.OpenRepository(src.Path, new GitEnvironment(homeDir.Path))); } + [Fact] + public void OpenRepository_Version1_ObjectFormatExtension() + { + using var temp = new TempRoot(); + + var homeDir = temp.CreateDirectory(); + + var workingDir = temp.CreateDirectory(); + var gitDir = workingDir.CreateDirectory(".git"); + + gitDir.CreateFile("HEAD").WriteAllText("ref: refs/heads/master"); + gitDir.CreateDirectory("refs").CreateDirectory("heads").CreateFile("master").WriteAllText("0000000000000000000000000000000000000000"); + gitDir.CreateDirectory("objects"); + + gitDir.CreateFile("config").WriteAllText(@" +[core] + repositoryformatversion = 1 +[extensions] + objectformat = sha256"); + + var src = workingDir.CreateDirectory("src"); + + // Should not throw - objectformat extension should be supported + var repository = GitRepository.OpenRepository(src.Path, new GitEnvironment(homeDir.Path)); + Assert.NotNull(repository); + Assert.Equal(gitDir.Path, repository.GitDirectory); + Assert.Equal(gitDir.Path, repository.CommonDirectory); + Assert.Equal(workingDir.Path, repository.WorkingDirectory); + } + [Fact] public void OpenRepository_VersionNotSupported() { diff --git a/src/Microsoft.Build.Tasks.Git/GitDataReader/GitConfig.cs b/src/Microsoft.Build.Tasks.Git/GitDataReader/GitConfig.cs index 28fd5814..576306da 100644 --- a/src/Microsoft.Build.Tasks.Git/GitDataReader/GitConfig.cs +++ b/src/Microsoft.Build.Tasks.Git/GitDataReader/GitConfig.cs @@ -16,25 +16,42 @@ internal sealed partial class GitConfig private const int SupportedGitRepoFormatVersion = 1; - private const string ExtensionSectionName = "extensions"; + private const string CoreSectionName = "core"; + private const string ExtensionsSectionName = "extensions"; + private const string RefStorageExtensionName = "refstorage"; + private const string ObjectFormatExtensionName = "objectFormat"; + private const string RepositoryFormatVersionVariableName = "repositoryformatversion"; private static readonly ImmutableArray s_knownExtensions = - ["noop", "preciousObjects", "partialclone", "worktreeConfig", RefStorageExtensionName]; + ["noop", "preciousObjects", "partialclone", "worktreeConfig", RefStorageExtensionName, ObjectFormatExtensionName]; public readonly ImmutableDictionary> Variables; public readonly ReferenceStorageFormat ReferenceStorageFormat; - internal GitConfig(ImmutableDictionary> variables) + /// + /// The parsed value of "extensions.objectFormat" variable. + /// + public ObjectNameFormat ObjectNameFormat { get; } + + /// + public GitConfig(ImmutableDictionary> variables) { Variables = variables; - ReferenceStorageFormat = GetVariableValue(ExtensionSectionName, RefStorageExtensionName) switch + ReferenceStorageFormat = GetVariableValue(ExtensionsSectionName, RefStorageExtensionName) switch { null => ReferenceStorageFormat.LooseFiles, "reftable" => ReferenceStorageFormat.RefTable, _ => throw new InvalidDataException(), }; + + ObjectNameFormat = GetVariableValue(ExtensionsSectionName, ObjectFormatExtensionName) switch + { + null or "sha1" => ObjectNameFormat.Sha1, + "sha256" => ObjectNameFormat.Sha256, + _ => throw new InvalidDataException(), + }; } /// @@ -60,7 +77,7 @@ public static GitConfig ReadSubmoduleConfig(string gitDirectory, string commonDi private void ValidateRepositoryConfig() { // See https://github.com/git/git/blob/master/Documentation/technical/repository-version.txt - var versionStr = GetVariableValue("core", "repositoryformatversion"); + var versionStr = GetVariableValue(CoreSectionName, RepositoryFormatVersionVariableName); if (TryParseInt64Value(versionStr, out var version) && version > SupportedGitRepoFormatVersion) { throw new NotSupportedException(string.Format(Resources.UnsupportedRepositoryVersion, versionStr, SupportedGitRepoFormatVersion)); @@ -71,7 +88,7 @@ private void ValidateRepositoryConfig() // All variables defined under extensions section must be known, otherwise a git implementation is not allowed to proceed. foreach (var variable in Variables) { - if (variable.Key.SectionNameEquals(ExtensionSectionName) && + if (variable.Key.SectionNameEquals(ExtensionsSectionName) && !s_knownExtensions.Contains(variable.Key.VariableName, StringComparer.OrdinalIgnoreCase)) { throw new NotSupportedException(string.Format( diff --git a/src/Microsoft.Build.Tasks.Git/GitDataReader/GitReferenceResolver.cs b/src/Microsoft.Build.Tasks.Git/GitDataReader/GitReferenceResolver.cs index 3c7bd8e9..8f06c0f4 100644 --- a/src/Microsoft.Build.Tasks.Git/GitDataReader/GitReferenceResolver.cs +++ b/src/Microsoft.Build.Tasks.Git/GitDataReader/GitReferenceResolver.cs @@ -23,7 +23,8 @@ internal sealed class GitReferenceResolver : IDisposable private readonly string _commonDirectory; private readonly string _gitDirectory; - private readonly ReferenceStorageFormat _format; + private readonly ReferenceStorageFormat _storageFormat; + private readonly ObjectNameFormat _objectNameFormat; // maps refs/heads references to the correspondign object ids: private readonly Lazy> _lazyPackedReferences; @@ -32,14 +33,15 @@ internal sealed class GitReferenceResolver : IDisposable // lock on access: private readonly List _openedRefTableReaders = []; - public GitReferenceResolver(string gitDirectory, string commonDirectory, ReferenceStorageFormat format) + public GitReferenceResolver(string gitDirectory, string commonDirectory, ReferenceStorageFormat storageFormat, ObjectNameFormat objectNameFormat) { Debug.Assert(PathUtils.IsNormalized(gitDirectory)); Debug.Assert(PathUtils.IsNormalized(commonDirectory)); _gitDirectory = gitDirectory; _commonDirectory = commonDirectory; - _format = format; + _storageFormat = storageFormat; + _objectNameFormat = objectNameFormat; _lazyPackedReferences = new(() => ReadPackedReferences(_gitDirectory)); _lazyRefTableReferenceReaders = new(() => CreateRefTableReaders(_gitDirectory, _openedRefTableReaders)); } @@ -57,7 +59,7 @@ public void Dispose() } } - private static ImmutableDictionary ReadPackedReferences(string gitDirectory) + private ImmutableDictionary ReadPackedReferences(string gitDirectory) { // https://git-scm.com/docs/git-pack-refs @@ -84,7 +86,7 @@ private static ImmutableDictionary ReadPackedReferences(string g } // internal for testing - internal static ImmutableDictionary ReadPackedReferences(TextReader reader, string path) + internal ImmutableDictionary ReadPackedReferences(TextReader reader, string path) { var builder = ImmutableDictionary.CreateBuilder(); @@ -248,7 +250,7 @@ private static bool TryGetReferenceName(string reference, [NotNullWhen(true)] ou return false; } - private static (string? objectName, string? referenceName) ParseObjectNameOrReference(string value) + private (string? objectName, string? referenceName) ParseObjectNameOrReference(string value) { if (TryGetReferenceName(value, out var referenceName)) { @@ -297,7 +299,7 @@ private static (string? objectName, string? referenceName) ParseObjectNameOrRefe } private (string? objectName, string? referenceName) FindHeadReference() - => _format switch + => _storageFormat switch { ReferenceStorageFormat.LooseFiles => ParseObjectNameOrReference(ReadReferenceFromFile(Path.Combine(_gitDirectory, GitRepository.GitHeadFileName))), ReferenceStorageFormat.RefTable => FindReferenceInRefTable(GitRepository.GitHeadFileName), @@ -305,7 +307,7 @@ private static (string? objectName, string? referenceName) ParseObjectNameOrRefe }; private (string? objectName, string? referenceName) FindReference(string referenceName) - => _format switch + => _storageFormat switch { ReferenceStorageFormat.LooseFiles => FindReferenceInLooseFile(referenceName), ReferenceStorageFormat.RefTable => FindReferenceInRefTable(referenceName), @@ -383,7 +385,7 @@ internal static string ReadReferenceFromFile(string path) private string? FindPackedReference(string reference) => _lazyPackedReferences.Value.TryGetValue(reference, out var objectId) ? objectId : null; - private static bool IsObjectId(string reference) - => reference.Length == 40 && reference.All(CharUtils.IsHexadecimalDigit); + private bool IsObjectId(string reference) + => reference.Length == _objectNameFormat.HashSize * 2 && reference.All(CharUtils.IsHexadecimalDigit); } } diff --git a/src/Microsoft.Build.Tasks.Git/GitDataReader/GitRepository.cs b/src/Microsoft.Build.Tasks.Git/GitDataReader/GitRepository.cs index 042ed136..1308a16e 100644 --- a/src/Microsoft.Build.Tasks.Git/GitDataReader/GitRepository.cs +++ b/src/Microsoft.Build.Tasks.Git/GitDataReader/GitRepository.cs @@ -61,7 +61,7 @@ internal GitRepository(GitEnvironment environment, GitConfig config, string gitD WorkingDirectory = workingDirectory; Environment = environment; - _referenceResolver = new GitReferenceResolver(gitDirectory, commonDirectory, config.ReferenceStorageFormat); + _referenceResolver = new GitReferenceResolver(gitDirectory, commonDirectory, config.ReferenceStorageFormat, config.ObjectNameFormat); _lazySubmodules = new(ReadSubmodules); _lazyIgnore = new(LoadIgnore); _lazyHeadCommitSha = new(ReadHeadCommitSha); @@ -191,7 +191,7 @@ public static GitRepository OpenRepository(GitRepositoryLocation location, GitEn } var config = GitConfig.ReadRepositoryConfig(gitDirectory, commonDirectory, environment); - return new GitReferenceResolver(gitDirectory, commonDirectory, config.ReferenceStorageFormat); + return new GitReferenceResolver(gitDirectory, commonDirectory, config.ReferenceStorageFormat, config.ObjectNameFormat); } private string GetWorkingDirectory() diff --git a/src/Microsoft.Build.Tasks.Git/GitDataReader/ObjectNameFormat.cs b/src/Microsoft.Build.Tasks.Git/GitDataReader/ObjectNameFormat.cs index 790ebc64..2e338216 100644 --- a/src/Microsoft.Build.Tasks.Git/GitDataReader/ObjectNameFormat.cs +++ b/src/Microsoft.Build.Tasks.Git/GitDataReader/ObjectNameFormat.cs @@ -6,6 +6,10 @@ namespace Microsoft.Build.Tasks.Git; +/// +/// Format of object names. +/// https://git-scm.com/docs/hash-function-transition.html#_object_format +/// internal enum ObjectNameFormat { Sha1,