Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
118 lines
2.1 KiB
Go
118 lines
2.1 KiB
Go
package repoversion
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
)
|
|
|
|
type Version struct {
|
|
Tag string
|
|
Hash string
|
|
}
|
|
|
|
func Determine(path string) (v Version, err error) {
|
|
repo, err := git.PlainOpenWithOptions(path, &git.PlainOpenOptions{DetectDotGit: true})
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
tags, err := repo.Tags()
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
head, err := repo.Head()
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
cIter, err := repo.Log(&git.LogOptions{Order: git.LogOrderCommitterTime})
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
var (
|
|
tag string
|
|
tagHash string
|
|
commitIndex int
|
|
taggerTimestamp int64
|
|
)
|
|
|
|
idMap := make(map[string]int)
|
|
|
|
err = cIter.ForEach(func(c *object.Commit) error {
|
|
idMap[c.Hash.String()] = commitIndex
|
|
commitIndex++
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
err = tags.ForEach(func(t *plumbing.Reference) error {
|
|
obj, err := repo.TagObject(t.Hash())
|
|
|
|
if err == nil {
|
|
|
|
_, exists := idMap[obj.Target.String()]
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
if taggerTimestamp < obj.Tagger.When.Unix() {
|
|
taggerTimestamp = obj.Tagger.When.Unix()
|
|
|
|
tag = strings.TrimPrefix(obj.Name, "v")
|
|
tagHash = obj.Target.String()
|
|
}
|
|
} else {
|
|
_, exists := idMap[t.Hash().String()]
|
|
|
|
if !exists {
|
|
return nil
|
|
}
|
|
|
|
commit, err := repo.CommitObject(t.Hash())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if taggerTimestamp < commit.Committer.When.Unix() {
|
|
taggerTimestamp = commit.Committer.When.Unix()
|
|
|
|
tag = strings.TrimPrefix(t.Name().Short(), "v")
|
|
tagHash = t.Hash().String()
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return Version{}, err
|
|
}
|
|
|
|
const subHashLen int = 8
|
|
|
|
tagHashIndex := idMap[tagHash]
|
|
headHashText := head.Hash().String()
|
|
subHeadHash := headHashText
|
|
|
|
if len(headHashText) > subHashLen {
|
|
subHeadHash = subHeadHash[:subHashLen]
|
|
}
|
|
|
|
v.Tag = tag
|
|
v.Hash = headHashText
|
|
|
|
if tagHashIndex > 0 {
|
|
v.Tag = fmt.Sprintf("%s-%s", tag, subHeadHash)
|
|
}
|
|
|
|
return v, nil
|
|
}
|