diff --git a/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs b/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs index 1d3b78b2..52c8b5ea 100644 --- a/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs +++ b/src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs @@ -222,9 +222,7 @@ public object GetHeadAsReferenceOrSha() /// public GitObjectId GetHeadCommitSha() { - var reference = this.GetHeadAsReferenceOrSha(); - var objectId = this.ResolveReference(reference); - return objectId; + return this.Lookup("HEAD") ?? GitObjectId.Empty; } /// @@ -280,9 +278,17 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false) /// The object ID referenced by if found; otherwise . 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(); @@ -290,6 +296,7 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false) { // Match on loose ref files by their canonical name. possibleLooseFileMatches.Add(Path.Combine(this.GitDirectory, objectish)); + skipObjectIdLookup = true; } else { @@ -341,6 +348,11 @@ public GitCommit GetCommit(GitObjectId sha, bool readAuthor = false) } } + if (skipObjectIdLookup) + { + return null; + } + if (objectish.Length == 40) { return GitObjectId.Parse(objectish); @@ -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); + } } } } @@ -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 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 LoadPacks() { var packDirectory = Path.Combine(this.ObjectDirectory, "pack/"); @@ -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; } ///