From 311f4775683cf7bd6cb802be995afa795ea2f653 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Sat, 12 Jun 2021 14:16:55 -0600 Subject: [PATCH] Touch-up on perf and add a test --- .../GitContextTests.cs | 10 +++- .../ManagedGit/GitRepository.cs | 48 ++++++++++++------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/NerdBank.GitVersioning.Tests/GitContextTests.cs b/src/NerdBank.GitVersioning.Tests/GitContextTests.cs index 81cf1a83..ccb93142 100644 --- a/src/NerdBank.GitVersioning.Tests/GitContextTests.cs +++ b/src/NerdBank.GitVersioning.Tests/GitContextTests.cs @@ -173,4 +173,12 @@ public void GetVersion_PackedHead() this.Context.TrySelectCommit("HEAD"); Assert.Equal("1.0.1", oracle.SimpleVersion.ToString()); } -} \ No newline at end of file + + [Fact] + public void HeadCanonicalName_PackedHead() + { + using var expandedRepo = TestUtilities.ExtractRepoArchive("PackedHeadRef"); + this.Context = this.CreateGitContext(Path.Combine(expandedRepo.RepoPath)); + Assert.Equal("refs/heads/main", this.Context.HeadCanonicalName); + } +} diff --git a/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs b/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs index e7a6d851..459f23c6 100644 --- a/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs +++ b/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; +using Validation; namespace Nerdbank.GitVersioning.ManagedGit { @@ -384,25 +385,29 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false) objectish += "0"; } - if (TryConvertHexStringToByteArray(objectish, out var hex)) + if (objectish.Length <= 40 && objectish.Length % 2 == 0) { - foreach (var pack in this.packs.Value.Span) + Span decodedHex = stackalloc byte[objectish.Length / 2]; + if (TryConvertHexStringToByteArray(objectish, decodedHex)) { - var objectId = pack.Lookup(hex, endsWithHalfByte); - - // It's possible for the same object to be present in both the object database and the pack files, - // or in multiple pack files. - if (objectId != null && !possibleObjectIds.Contains(objectId.Value)) + foreach (var pack in this.packs.Value.Span) { - if (possibleObjectIds.Count > 0) - { - // If objectish already resolved to at least one object which is different from the current - // object id, objectish is not well-defined; so stop resolving and return null instead. - return null; - } - else + var objectId = pack.Lookup(decodedHex, endsWithHalfByte); + + // It's possible for the same object to be present in both the object database and the pack files, + // or in multiple pack files. + if (objectId != null && !possibleObjectIds.Contains(objectId.Value)) { - possibleObjectIds.Add(objectId.Value); + if (possibleObjectIds.Count > 0) + { + // If objectish already resolved to at least one object which is different from the current + // object id, objectish is not well-defined; so stop resolving and return null instead. + return null; + } + else + { + possibleObjectIds.Add(objectId.Value); + } } } } @@ -673,7 +678,7 @@ private static string TrimEndingDirectorySeparator(string path) #endif } - private static bool TryConvertHexStringToByteArray(string hexString, out byte[]? data) + private static bool TryConvertHexStringToByteArray(string hexString, Span data) { // https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array if (hexString.Length % 2 != 0) @@ -682,15 +687,22 @@ private static bool TryConvertHexStringToByteArray(string hexString, out byte[]? return false; } - data = new byte[hexString.Length / 2]; + Requires.Argument(data.Length == hexString.Length / 2, nameof(data), "Length must be exactly half that of " + nameof(hexString) + "."); for (int index = 0; index < data.Length; index++) { +#if NETCOREAPP3_1_OR_GREATER + ReadOnlySpan byteValue = hexString.AsSpan(index * 2, 2); + if (!byte.TryParse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data[index])) + { + return false; + } +#else string byteValue = hexString.Substring(index * 2, 2); if (!byte.TryParse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data[index])) { - data = null; return false; } +#endif } return true;