Skip to content

Commit

Permalink
Tweak GitRepository.Lookup error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
filipnavara authored and AArnott committed Jun 12, 2021
1 parent 47d7f46 commit ea9517b
Showing 1 changed file with 43 additions and 54 deletions.
97 changes: 43 additions & 54 deletions src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,7 @@ public object GetHeadAsReferenceOrSha()
/// </returns>
public GitObjectId GetHeadCommitSha()
{
var reference = this.GetHeadAsReferenceOrSha();
var objectId = this.ResolveReference(reference);
return objectId;
return this.Lookup("HEAD") ?? GitObjectId.Empty;
}

/// <summary>
Expand Down Expand Up @@ -280,16 +278,25 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false)
/// <returns>The object ID referenced by <paramref name="objectish"/> if found; otherwise <see langword="null"/>.</returns>
public GitObjectId? Lookup(string objectish)
{
bool skipObjectIdLookup = false;

if (objectish == "HEAD")
{
return this.GetHeadCommitSha();
var reference = this.GetHeadAsReferenceOrSha();
if (reference is GitObjectId headObjectId)
{
return headObjectId;
}

objectish = (string)reference;
}

var possibleLooseFileMatches = new List<string>();
if (objectish.StartsWith("refs/", StringComparison.Ordinal))
{
// Match on loose ref files by their canonical name.
possibleLooseFileMatches.Add(Path.Combine(this.GitDirectory, objectish));
skipObjectIdLookup = true;
}
else
{
Expand Down Expand Up @@ -341,6 +348,11 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false)
}
}

if (skipObjectIdLookup)
{
return null;
}

if (objectish.Length == 40)
{
return GitObjectId.Parse(objectish);
Expand Down Expand Up @@ -372,25 +384,26 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false)
objectish += "0";
}

var hex = ConvertHexStringToByteArray(objectish);

foreach (var pack in this.packs.Value.Span)
if (TryConvertHexStringToByteArray(objectish, out var hex))
{
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(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))
{
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 @@ -610,35 +623,6 @@ private bool TryGetObjectByPath(GitObjectId sha, string objectType, [NotNullWhen
return true;
}

private GitObjectId ResolveReference(object reference)
{
if (reference is string)
{
if (!FileHelpers.TryOpen(Path.Combine(this.CommonDirectory, (string)reference), out FileStream? stream))
{
// HEAD can point to a reference that's in the packed references and needs
// a full resolution.
return Lookup((string)reference) ?? GitObjectId.Empty;
}

using (stream)
{
Span<byte> objectId = stackalloc byte[40];
stream!.Read(objectId);

return GitObjectId.ParseHex(objectId);
}
}
else if (reference is GitObjectId)
{
return (GitObjectId)reference;
}
else
{
throw new GitException();
}
}

private ReadOnlyMemory<GitPack> LoadPacks()
{
var packDirectory = Path.Combine(this.ObjectDirectory, "pack/");
Expand Down Expand Up @@ -689,22 +673,27 @@ private static string TrimEndingDirectorySeparator(string path)
#endif
}

private static byte[] ConvertHexStringToByteArray(string hexString)
private static bool TryConvertHexStringToByteArray(string hexString, out byte[]? data)
{
// https://stackoverflow.com/questions/321370/how-can-i-convert-a-hex-string-to-a-byte-array
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
data = null;
return false;
}

byte[] data = new byte[hexString.Length / 2];
data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
if (byte.TryParse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out data[index]))
{
data = null;
return false;
}
}

return data;
return true;
}

/// <summary>
Expand Down

0 comments on commit ea9517b

Please sign in to comment.