Skip to content

Commit 311f477

Browse files
committed
Touch-up on perf and add a test
1 parent 4d8ecca commit 311f477

File tree

2 files changed

+39
-19
lines changed

2 files changed

+39
-19
lines changed

src/NerdBank.GitVersioning.Tests/GitContextTests.cs

+9-1
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,12 @@ public void GetVersion_PackedHead()
173173
this.Context.TrySelectCommit("HEAD");
174174
Assert.Equal("1.0.1", oracle.SimpleVersion.ToString());
175175
}
176-
}
176+
177+
[Fact]
178+
public void HeadCanonicalName_PackedHead()
179+
{
180+
using var expandedRepo = TestUtilities.ExtractRepoArchive("PackedHeadRef");
181+
this.Context = this.CreateGitContext(Path.Combine(expandedRepo.RepoPath));
182+
Assert.Equal("refs/heads/main", this.Context.HeadCanonicalName);
183+
}
184+
}

src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs

+30-18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Runtime.InteropServices;
1010
using System.Text;
11+
using Validation;
1112

1213
namespace Nerdbank.GitVersioning.ManagedGit
1314
{
@@ -384,25 +385,29 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false)
384385
objectish += "0";
385386
}
386387

387-
if (TryConvertHexStringToByteArray(objectish, out var hex))
388+
if (objectish.Length <= 40 && objectish.Length % 2 == 0)
388389
{
389-
foreach (var pack in this.packs.Value.Span)
390+
Span<byte> decodedHex = stackalloc byte[objectish.Length / 2];
391+
if (TryConvertHexStringToByteArray(objectish, decodedHex))
390392
{
391-
var objectId = pack.Lookup(hex, endsWithHalfByte);
392-
393-
// It's possible for the same object to be present in both the object database and the pack files,
394-
// or in multiple pack files.
395-
if (objectId != null && !possibleObjectIds.Contains(objectId.Value))
393+
foreach (var pack in this.packs.Value.Span)
396394
{
397-
if (possibleObjectIds.Count > 0)
398-
{
399-
// If objectish already resolved to at least one object which is different from the current
400-
// object id, objectish is not well-defined; so stop resolving and return null instead.
401-
return null;
402-
}
403-
else
395+
var objectId = pack.Lookup(decodedHex, endsWithHalfByte);
396+
397+
// It's possible for the same object to be present in both the object database and the pack files,
398+
// or in multiple pack files.
399+
if (objectId != null && !possibleObjectIds.Contains(objectId.Value))
404400
{
405-
possibleObjectIds.Add(objectId.Value);
401+
if (possibleObjectIds.Count > 0)
402+
{
403+
// If objectish already resolved to at least one object which is different from the current
404+
// object id, objectish is not well-defined; so stop resolving and return null instead.
405+
return null;
406+
}
407+
else
408+
{
409+
possibleObjectIds.Add(objectId.Value);
410+
}
406411
}
407412
}
408413
}
@@ -673,7 +678,7 @@ private static string TrimEndingDirectorySeparator(string path)
673678
#endif
674679
}
675680

676-
private static bool TryConvertHexStringToByteArray(string hexString, out byte[]? data)
681+
private static bool TryConvertHexStringToByteArray(string hexString, Span<byte> data)
677682
{
678683
// https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array
679684
if (hexString.Length % 2 != 0)
@@ -682,15 +687,22 @@ private static bool TryConvertHexStringToByteArray(string hexString, out byte[]?
682687
return false;
683688
}
684689

685-
data = new byte[hexString.Length / 2];
690+
Requires.Argument(data.Length == hexString.Length / 2, nameof(data), "Length must be exactly half that of " + nameof(hexString) + ".");
686691
for (int index = 0; index < data.Length; index++)
687692
{
693+
#if NETCOREAPP3_1_OR_GREATER
694+
ReadOnlySpan<char> byteValue = hexString.AsSpan(index * 2, 2);
695+
if (!byte.TryParse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data[index]))
696+
{
697+
return false;
698+
}
699+
#else
688700
string byteValue = hexString.Substring(index * 2, 2);
689701
if (!byte.TryParse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data[index]))
690702
{
691-
data = null;
692703
return false;
693704
}
705+
#endif
694706
}
695707

696708
return true;

0 commit comments

Comments
 (0)