How to get the git tags for a particular hash in go using go-git package to get an output similar to git describe –tags –always

huangapple go评论85阅读模式
英文:

How to get the git tags for a particular hash in go using go-git package to get an output similar to git describe --tags --always

问题

我正在使用go-git包来获取标签,在使用"TagObject"函数时,它返回null。你应该如何编写它?

实际文件:

hashCommit, _ := r.Head()
tagObj, _ := r.TagObject(hashCommit.Hash())

测试文件:

tags, err := testAppDir.Tags()
h.AssertNil(t, err)
tags.ForEach(func(t *plumbing.Reference) error {
    fmt.Println("the tag inside test", t)
    return nil
})

我该如何在我的实际文件中获取标签?
错误:

- "describe": string(""),
+ "describe": (*object.Tag)(nil)
英文:

I am using the go-git package to get the tags, on using the function "TagObject", it is returning null.
How should I write it?

Actual file:

hashCommit, _ := r.Head()
tagObj, _ := r.TagObject(hashCommit.Hash())

Test file:

tags, err := testAppDir.Tags()
					h.AssertNil(t, err)
					tags.ForEach(func(t *plumbing.Reference) error {
						fmt.Println("the tag inside test", t)
						return nil
					})

How do I get the tags in my actual file?
Error:

  - "describe": string(""),
 + "describe": (*object.Tag)(nil)

答案1

得分: 1

我认为这对于这个特定情况会起作用。

由于标签与它们标记的提交有一个引用,但没有反向引用,getTags函数返回一个反转该关系的map,允许我们找到附加到提交的tag(注意,假设一个提交只有一个标签,这可能不是真实情况)。

然后,我们将该映射与头部进行比较,如果有标签,则打印它。否则,我们将从头部开始遍历日志,寻找第一个带有标签的提交。如果找到任何标签,我们将打印标签和提交的简短版本(似乎没有一种可靠获取简短哈希的方法,所以我取了前8个字符)。

最后,如果找不到任何内容,则使用前面描述的方法打印简短哈希。

这是一个天真的实现,可能在具有大量标签的存储库中存在问题。

请注意,我使用了更新的go-git版本。

package main

import (
	"errors"
	"fmt"
	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/plumbing"
	"io"
	"log"
)

func getTags(r *git.Repository) (map[plumbing.Hash]string, error) {
	tags := make(map[plumbing.Hash]string)

	iter, err := r.Tags()
	if err != nil {
		return nil, err
	}

	for {
		ref, err := iter.Next()
		if errors.Is(err, io.EOF) {
			break
		}
		if err != nil{
			return nil, err
		}
		tags[ref.Hash()] = ref.Name().Short()

	}
	return tags, nil
}

func main() {
    appPath := ""
	r, err := git.PlainOpen(appPath)

	if err != nil {
		log.Fatal(err)
	}
	hashCommit, err := r.Head()
	if err != nil {
		log.Fatal("head", err)
	}
	fmt.Println("hash", hashCommit)

	tags, err := getTags(r)

	// check if last commit is tagged
	if str, ok := tags[hashCommit.Hash()]; ok {
		fmt.Println(str)
		return
	}

	// check if any commit is tagged
	cIter, err := r.Log(&git.LogOptions{From: hashCommit.Hash()})
	for {
		commit, err := cIter.Next()
		if errors.Is(err, io.EOF) {
			break
		}
		if err != nil{
			log.Fatal(err)
		}

		if str, ok := tags[commit.Hash]; ok {
			fmt.Printf("%s-%s\n", str, hashCommit.Hash().String()[:8])
			return
		}
	}

	fmt.Println(hashCommit.Hash().String()[:8])
}
英文:

I think this will work for that particular case.

Since tags have a reference to the commit they tagged but there is no reference back, the getTags function returns a map that inverts that relation and allows us to find the tag that is attached to a commit (note that it is assumed that there is only one tag for a commit which may not be true).

We then take that map and see if the head has a tag and if so print it. Otherwise we'll go through the log starting on the head and searching for the first tagged commit. If we find any we'll print the tag and a short version of the commit (there doesn't seem to be a method to get a reliable short hash so I took the first 8 chars)

Finally if nothing is found the short hash is printed using the method described before.

This is a naive implementation that may have problems with repositories with a large amount of tags.

Please note that I used an updated version of go-git.

package main

import (
	"errors"
	"fmt"
	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/plumbing"
	"io"
	"log"
)

func getTags(r *git.Repository) (map[plumbing.Hash]string, error) {
	tags := make(map[plumbing.Hash]string)

	iter, err := r.Tags()
	if err != nil {
		return nil, err
	}

	for {
		ref, err := iter.Next()
		if errors.Is(err, io.EOF) {
			break
		}
		if err != nil{
			return nil, err
		}
		tags[ref.Hash()] = ref.Name().Short()

	}
	return tags, nil
}

func main() {
    appPath := "" 
	r, err := git.PlainOpen(appPath)

	if err != nil {
		log.Fatal(err)
	}
	hashCommit, err := r.Head()
	if err != nil {
		log.Fatal("head", err)
	}
	fmt.Println("hash", hashCommit)

	tags, err := getTags(r)

	// check if last commit is tagged
	if str, ok := tags[hashCommit.Hash()]; ok {
		fmt.Println(str)
		return
	}

	// check if any commit is tagged
	cIter, err := r.Log(&git.LogOptions{From: hashCommit.Hash()})
	for {
		commit, err := cIter.Next()
		if errors.Is(err, io.EOF) {
			break
		}
		if err != nil{
			log.Fatal(err)
		}

		if str, ok := tags[commit.Hash]; ok {
			fmt.Printf("%s-%s\n", str, hashCommit.Hash().String()[:8])
			return
		}
	}

	fmt.Println(hashCommit.Hash().String()[:8])
}

huangapple
  • 本文由 发表于 2021年9月15日 15:39:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/69188914.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定