What is the fastest way to find tags pointing to Commits?

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 all tags to be bound to the current commit. What is the best way to do this? Iterate through all the tags and see if tag.Target.Sha == commit.Sha ? This is not good. Is there another way?

+6
source share
2 answers

So, I want all the tags to be bound to the current commit. What is the best way to do this? Iterate through all the tags and see if there is tag.Target.Sha == commit.Sha ? This is not good. Is there another way?

There are two things to consider when it comes to tags.

  • A tag can point to something else besides Commit (for example, Tree or Blob).
  • A tag can point to another tag (anchored annotated tags)

The code below should suit your needs, taking these points into account.

Note. repo.Commits will list only the amounts reachable from the current branch ( HEAD ). The code below extends this to easily view all available targets.

 ... 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 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; } 
+8
source

Here is another version of the nulltoken answer, but using the ILookup class instead of a dictionary. A little better 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 a 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}"); } } } 
0
source

Source: https://habr.com/ru/post/957484/


All Articles