したがって、現在のコミットに割り当てられているすべてのタグを取得したいと考えています。それを行う最良の方法は何ですか?すべてのタグを反復処理してtag.Target.Sha == commit.Sha
、それはあまり高性能ではありません。別の方法はありますか?
タグに関しては、考慮すべき点が 2 つあります。
- タグは、コミット以外のものを指すことができます (たとえば、ツリーまたはブロブ)
- タグは別のタグを指すことができます (連鎖した注釈付きタグ)
以下のコードは、上記の点を考慮して、ニーズに合うはずです。
注: repo.Commits
現在のブランチ ( ) から到達可能なコミットのみを列挙しHEAD
ます。以下のコードはこれを拡張して、到達可能なすべてのコミットを簡単に参照できるようにします。
...
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;
}