With libgit2sharp I would like to do the following:
foreach( Commit commit in repo.Commits )
{
// How to implement assignedTags?
foreach( Tag tag in commit.assignedTags ) {}
}
I want to get all tags assigned to the current commit. Whats the best way to do that? Iterate through all Tags and see if tag.Target.Sha == commit.Sha
? Thats not very performant. Is there another way?
So I want to get all tags assigned to the current commit. Whats the best way to do that? Iterate through all Tags and see if
tag.Target.Sha == commit.Sha
? Thats not very performant. Is there another way?
There are two things to take into account when it comes to Tags.
The code below should fit your need by taking these points above into account.
Note: repo.Commits
will only enumerate the commits reachable from the current branch (HEAD
). The code below
extends this to easily browse all the reachable commits.
...
using (var repo = new Repository("Path/to/your/repo"))
{
// Build up a cached dictionary of all the tags that point to a commit
var dic = TagsPerPeeledCommitId(repo);
// Let's enumerate all the reachable commits (similarly to `git log --all`)
foreach (Commit commit in repo.Commits.QueryBy(new CommitFilter {Since = repo.Refs}))
{
foreach (var tags in AssignedTags(commit, dic))
{
Console.WriteLine("Tag {0} points at {1}", tags.Name, commit.Id);
}
}
}
....
private static IEnumerable<Tag> AssignedTags(Commit commit, Dictionary<ObjectId, List<Tag>> tags)
{
if (!tags.ContainsKey(commit.Id))
{
return Enumerable.Empty<Tag>();
}
return tags[commit.Id];
}
private static Dictionary<ObjectId, List<Tag>> TagsPerPeeledCommitId(Repository repo)
{
var tagsPerPeeledCommitId = new Dictionary<ObjectId, List<Tag>>();
foreach (Tag tag in repo.Tags)
{
GitObject peeledTarget = tag.PeeledTarget;
if (!(peeledTarget is Commit))
{
// We're not interested by Tags pointing at Blobs or Trees
continue;
}
ObjectId commitId = peeledTarget.Id;
if (!tagsPerPeeledCommitId.ContainsKey(commitId))
{
// A Commit may be pointed at by more than one Tag
tagsPerPeeledCommitId.Add(commitId, new List<Tag>());
}
tagsPerPeeledCommitId[commitId].Add(tag);
}
return tagsPerPeeledCommitId;
}
Here is another version of nulltoken's answer but with using ILookup
class instead of dictionary. A bit nicer IMO:
private static ILookup<ObjectId, Tag> CreateCommitIdToTagLookup(Repository repo)
{
var commitIdToTagLookup =
repo.Tags
.Select(tag => new { Commit = tag.PeeledTarget as Commit, Tag = tag })
.Where(x => x.Commit != null)
.ToLookup(x => x.Commit.Id, x => x.Tag);
return commitIdToTagLookup;
}
and simple usage example:
using (var repo = new Repository("Path/to/your/repo"))
{
var commitIdToTagLookup = CreateCommitIdToTagLookup(repo);
foreach (var commit in repo.Commits)
{
foreach (var tag in commitIdToTagLookup[commit.Id])
{
Console.WriteLine($"Tag {tag.FriendlyName} points at {commit.Id}");
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With