为了账号安全,请及时绑定邮箱和手机立即绑定

获取特定分支的标签

获取特定分支的标签

Go
温温酱 2023-07-26 13:23:23
使用go-git:有没有办法只获取特定分支的(轻量级和带注释的)标签?由于我主要对主分支的标签感兴趣,所以类似的东西git tag --merged也足够了。使用基本的 go-git 方法似乎不可能,例如Tags()......
查看完整描述

1 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

不完全是一个简短的解决方案,但以下代码通过以下方式实现了目标:

  1. 读取整个分支的提交哈希值。

  2. 读取存储库的所有标签。

  3. 检查并仅打印散列位于分支中的标签。

注意:尚未尝试使用带注释的标签。但应该很接近。

package main


import (

    "log"


    "github.com/src-d/go-billy/memfs"

    "gopkg.in/src-d/go-git.v4"

    "gopkg.in/src-d/go-git.v4/plumbing"

    "gopkg.in/src-d/go-git.v4/plumbing/object"

    "gopkg.in/src-d/go-git.v4/storage/memory"

)


func getBranchHashes(repo *git.Repository, branchName string) (hashes map[plumbing.Hash]bool, err error) {


    // get branch reference name

    branch, err := repo.Branch("master")

    if err != nil {

        return

    }


    // get reference of the reference name

    ref, err := repo.Reference(branch.Merge, true)

    if err != nil {

        return

    }


    // retrieve logs from the branch reference commit

    // (default order is depth first)

    logs, err := repo.Log(&git.LogOptions{

        From: ref.Hash(),

    })

    if err != nil {

        return

    }

    defer logs.Close()


    // a channel to collect all hashes

    chHash := make(chan plumbing.Hash)

    chErr := make(chan error)

    go func() {

        err = logs.ForEach(func(commit *object.Commit) (err error) {

            chHash <- commit.Hash

            return

        })

        if err != nil {

            chErr <- err

        }

        close(chErr)

        close(chHash)

    }()


    // make all hashes into a map

    hashes = make(map[plumbing.Hash]bool)

hashLoop:

    for {

        select {

        case err = <-chErr:

            if err != nil {

                return

            }

            break hashLoop

        case h := <-chHash:

            hashes[h] = true

        }

    }

    return

}


type TagRef struct {

    Hash plumbing.Hash

    Name string

}


func main() {

    // Filesystem abstraction based on memory

    fs := memfs.New()


    // Git objects storer based on memory

    storer := memory.NewStorage()


    // Clones the repository into the worktree (fs) and storer all the .git

    // content into the storer

    repo, err := git.Clone(storer, fs, &git.CloneOptions{

        URL: "https://github.com/yookoala/gofast.git",

    })

    if err != nil {

        log.Fatal(err)

    }


    hashes, err := getBranchHashes(repo, "master")

    if err != nil {

        log.Fatal(err)

    }


    // get all tags in the repo

    tags, err := repo.Tags()

    if err != nil {

        log.Fatal(err)

    }


    tagRefs := make(chan TagRef)

    go func() {

        err = tags.ForEach(func(ref *plumbing.Reference) (err error) {

            if annotedTag, err := repo.TagObject(ref.Hash()); err != plumbing.ErrObjectNotFound {

                if annotedTag.TargetType == plumbing.CommitObject {

                    tagRefs <- TagRef{

                        Hash: annotedTag.Target,

                        Name: ref.Name().Short(),

                    }

                }

                return nil

            }

            tagRefs <- TagRef{

                Hash: ref.Hash(),

                Name: ref.Name().Short(),

            }

            return

        })

        if err != nil {

            log.Fatal(err)

        }


        close(tagRefs)

    }()


    for tagRef := range tagRefs {

        if _, ok := hashes[tagRef.Hash]; ok {

            log.Printf("tag: %s, hash: %s", tagRef.Name, tagRef.Hash)

        }

    }

}


查看完整回答
反对 回复 2023-07-26
  • 1 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信