Skip to content

Commit

Permalink
Touch-up on perf and add a test
Browse files Browse the repository at this point in the history
  • Loading branch information
AArnott committed Jun 12, 2021
1 parent 4d8ecca commit 311f477
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 19 deletions.
10 changes: 9 additions & 1 deletion src/NerdBank.GitVersioning.Tests/GitContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,12 @@ public void GetVersion_PackedHead()
this.Context.TrySelectCommit("HEAD");
Assert.Equal("1.0.1", oracle.SimpleVersion.ToString());
}
}

[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);
}
}
48 changes: 30 additions & 18 deletions src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Validation;

namespace Nerdbank.GitVersioning.ManagedGit
{
Expand Down Expand Up @@ -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<byte> 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);
}
}
}
}
Expand Down Expand Up @@ -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<byte> data)
{
// https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array
if (hexString.Length % 2 != 0)
Expand All @@ -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<char> 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;
Expand Down

0 comments on commit 311f477

Please sign in to comment.