-
-
Notifications
You must be signed in to change notification settings - Fork 178
Add git-based detection of tags at HEAD to improve PublicRelease detection #876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 14 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
317a142
Add wip tag lookup
georg-jung f0468bc
Add managed git support for annotated tags
georg-jung df58f36
Fix nullable warnings
georg-jung 5f5b002
Fix mistaken comment in GitCommitReader
georg-jung dd9e383
Fix nullability issues and code style
georg-jung 3c93a89
Add workaround for improper GitPack.TryGetValue function
georg-jung c2e3c84
Make HeadTags return null instead of throwing if no HEAD
georg-jung a5c61c4
Fix xml doc
georg-jung 3b05482
Add some minor improvements
georg-jung 9c7d4c5
Fix packed-refs handling
georg-jung 066d82d
Make LibGit2Context behave like ManagedGit
georg-jung a3089b1
Add [Ignore] to exclude BuildingTags from CloudBuildAllVars
georg-jung 46b3681
Cache tags collections
AArnott c321ea2
Reduce allocations for `GitAnnotatedTag` equality checks
AArnott a84ad8b
Skip tag candidate collection, reduce string operations
georg-jung 49b9dc9
Fix handling of peel lines in packed-refs
georg-jung 82c1751
Fix EnumeratePackedRefsWithPeelLines
georg-jung 2198efa
Clarify EnumeratePackedRefsWithPeelLines
georg-jung 41652e2
Speedup: Use packed-refs header, consider records peeled if applicable
georg-jung be0182b
Fix: read from disposed StreamReader
georg-jung 89f29b1
Avoid exploring tags unless version.json needs it
AArnott a39f728
Merge remote-tracking branch 'origin/main' into georg-jung/main
AArnott cc2111b
Add first Tags test
AArnott 3373263
Add annotated tag test
AArnott cd36215
Capture failure drop in its entirety
AArnott 544704a
Add runtime check on ParseHex argument
AArnott fe34eb2
Collect .git directory too
AArnott 9f52d81
Merge remote-tracking branch 'upstream/main'
georg-jung f0008fe
Adapt to changes on main
georg-jung 60462f2
Touch-ups
AArnott File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // Copyright (c) .NET Foundation and Contributors. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
|
||
| #nullable enable | ||
|
|
||
| using System.Collections; | ||
|
|
||
| namespace Nerdbank.GitVersioning.ManagedGit; | ||
|
|
||
| /// <summary> | ||
| /// Represents a Git annotated tag, as stored in the Git object database. | ||
| /// </summary> | ||
| public struct GitAnnotatedTag : IEquatable<GitAnnotatedTag> | ||
| { | ||
| /// <summary> | ||
| /// Gets or sets the <see cref="GitObjectId"/> of object this tag is pointing at. | ||
| /// </summary> | ||
| public GitObjectId Object { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a <see cref="GitObjectId"/> which uniquely identifies the <see cref="GitAnnotatedTag"/>. | ||
| /// </summary> | ||
| public GitObjectId Sha { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the tag name of this annotated tag. | ||
| /// </summary> | ||
| public string Tag { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the type of the object this tag is pointing to, e.g. "commit" or, for nested tags, "tag". | ||
| /// </summary> | ||
| public string Type { get; set; } | ||
|
|
||
| public static bool operator ==(GitAnnotatedTag left, GitAnnotatedTag right) => left.Equals(right); | ||
|
|
||
| public static bool operator !=(GitAnnotatedTag left, GitAnnotatedTag right) => !(left == right); | ||
|
|
||
| /// <inheritdoc/> | ||
| public override bool Equals(object? obj) => obj is GitAnnotatedTag tag ? this.Equals(tag) : false; | ||
|
|
||
| /// <inheritdoc/> | ||
| public bool Equals(GitAnnotatedTag other) => this.Sha.Equals(other.Sha); | ||
|
|
||
| /// <inheritdoc/> | ||
| public override int GetHashCode() => this.Sha.GetHashCode(); | ||
|
|
||
| /// <inheritdoc/> | ||
| public override string ToString() | ||
| { | ||
| return $"Git Tag: {this.Tag} with id {this.Sha}"; | ||
| } | ||
| } |
133 changes: 133 additions & 0 deletions
133
src/NerdBank.GitVersioning/ManagedGit/GitAnnotatedTagReader.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| // Copyright (c) .NET Foundation and Contributors. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
|
||
| #nullable enable | ||
|
|
||
| using System.Buffers; | ||
| using System.Diagnostics; | ||
| using System.Xml.Linq; | ||
| using LibGit2Sharp; | ||
| using Validation; | ||
|
|
||
| namespace Nerdbank.GitVersioning.ManagedGit; | ||
|
|
||
| /// <summary> | ||
| /// Reads a <see cref="GitAnnotatedTag"/> object. | ||
| /// </summary> | ||
| public static class GitAnnotatedTagReader | ||
| { | ||
| private const int ObjectLineLength = 48; | ||
|
|
||
| private static readonly byte[] ObjectStart = GitRepository.Encoding.GetBytes("object "); | ||
| private static readonly byte[] TypeStart = GitRepository.Encoding.GetBytes("type "); | ||
| private static readonly byte[] TagStart = GitRepository.Encoding.GetBytes("tag "); | ||
|
|
||
| /// <summary> | ||
| /// Reads a <see cref="GitAnnotatedTag"/> object from a <see cref="Stream"/>. | ||
| /// </summary> | ||
| /// <param name="stream"> | ||
| /// A <see cref="Stream"/> which contains the <see cref="GitAnnotatedTag"/> in its text representation. | ||
| /// </param> | ||
| /// <param name="sha"> | ||
| /// The <see cref="GitObjectId"/> of the commit. | ||
| /// </param> | ||
| /// <returns> | ||
| /// The <see cref="GitAnnotatedTag"/>. | ||
| /// </returns> | ||
| public static GitAnnotatedTag Read(Stream stream, GitObjectId sha) | ||
| { | ||
| Requires.NotNull(stream, nameof(stream)); | ||
|
|
||
| byte[] buffer = ArrayPool<byte>.Shared.Rent(checked((int)stream.Length)); | ||
|
|
||
| try | ||
| { | ||
| Span<byte> span = buffer.AsSpan(0, (int)stream.Length); | ||
| stream.ReadAll(span); | ||
|
|
||
| return Read(span, sha); | ||
| } | ||
| finally | ||
| { | ||
| ArrayPool<byte>.Shared.Return(buffer); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Reads a <see cref="GitAnnotatedTag"/> object from a <see cref="ReadOnlySpan{T}"/>. | ||
| /// </summary> | ||
| /// <param name="tag"> | ||
| /// A <see cref="ReadOnlySpan{T}"/> which contains the <see cref="GitAnnotatedTag"/> in its text representation. | ||
| /// </param> | ||
| /// <param name="sha"> | ||
| /// The <see cref="GitObjectId"/> of the annotated tag. | ||
| /// </param> | ||
| /// <returns> | ||
| /// The <see cref="GitAnnotatedTag"/>. | ||
| /// </returns> | ||
| public static GitAnnotatedTag Read(ReadOnlySpan<byte> tag, GitObjectId sha) | ||
| { | ||
| ReadOnlySpan<byte> buffer = tag; | ||
|
|
||
| GitObjectId obj = ReadObject(buffer.Slice(0, ObjectLineLength)); | ||
| buffer = buffer.Slice(ObjectLineLength); | ||
|
|
||
| (string type, int typeLen) = ReadType(buffer); | ||
| buffer = buffer.Slice(typeLen); | ||
|
|
||
| (string tagName, _) = ReadTag(buffer); | ||
|
|
||
| return new GitAnnotatedTag | ||
| { | ||
| Sha = sha, | ||
| Object = obj, | ||
| Type = type, | ||
| Tag = tagName, | ||
| }; | ||
| } | ||
|
|
||
| private static GitObjectId ReadObject(ReadOnlySpan<byte> line) | ||
| { | ||
| // Format: object d8329fc1cc938780ffdd9f94e0d364e0ea74f579\n | ||
| // 48 bytes: | ||
| // object: 6 bytes | ||
| // space: 1 byte | ||
| // hash: 40 bytes | ||
| // \n: 1 byte | ||
| Debug.Assert(line.Slice(0, ObjectStart.Length).SequenceEqual(ObjectStart)); | ||
| Debug.Assert(line[ObjectLineLength - 1] == (byte)'\n'); | ||
|
|
||
| return GitObjectId.ParseHex(line.Slice(ObjectStart.Length, 40)); | ||
| } | ||
|
|
||
| private static (string Content, int BytesRead) ReadPrefixedString(ReadOnlySpan<byte> remaining, byte[] prefix) | ||
| { | ||
| Debug.Assert(remaining.Slice(0, prefix.Length).SequenceEqual(prefix)); | ||
|
|
||
| int lineEnd = remaining.IndexOf((byte)'\n'); | ||
| ReadOnlySpan<byte> type = remaining.Slice(prefix.Length, lineEnd - prefix.Length); | ||
| return (GitRepository.GetString(type), lineEnd + 1); | ||
| } | ||
|
|
||
| private static (string Content, int BytesRead) ReadType(ReadOnlySpan<byte> remaining) | ||
| { | ||
| // Format: type commit\n | ||
| // <variable> bytes: | ||
| // type: 4 bytes | ||
| // space: 1 byte | ||
| // <type e.g. commit>: <variable> bytes | ||
| // \n: 1 byte | ||
| return ReadPrefixedString(remaining, TypeStart); | ||
| } | ||
|
|
||
| private static (string Content, int BytesRead) ReadTag(ReadOnlySpan<byte> remaining) | ||
| { | ||
| // Format: tag someAnnotatedTag\n | ||
| // <variable> bytes: | ||
| // tag: 3 bytes | ||
| // space: 1 byte | ||
| // <tag name e.g. someAnnotatedTag>: <variable> bytes | ||
| // \n: 1 byte | ||
| return ReadPrefixedString(remaining, TagStart); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.