initial commit. Cloned timetracker repository
This commit is contained in:
136
app/utils/version/version.go
Normal file
136
app/utils/version/version.go
Normal file
@@ -0,0 +1,136 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
// Version info populated at build time
|
||||
var (
|
||||
Version string // Git tag or commit hash
|
||||
Commit string // Short commit hash
|
||||
BuildDate string // Build timestamp
|
||||
)
|
||||
|
||||
// Info returns version information
|
||||
type Info struct {
|
||||
Version string `json:"version"`
|
||||
Commit string `json:"commit"`
|
||||
BuildDate string `json:"build_date"`
|
||||
}
|
||||
|
||||
// GetInfo returns version information
|
||||
func GetInfo() Info {
|
||||
v := Info{
|
||||
Version: Version,
|
||||
Commit: Commit,
|
||||
BuildDate: BuildDate,
|
||||
}
|
||||
|
||||
// If not set during build, try to get from git
|
||||
if v.Version == "" || v.Version == "unknown" || v.Version == "(devel)" {
|
||||
if gitVersion, gitCommit := getGitInfo(); gitVersion != "" {
|
||||
v.Version = gitVersion
|
||||
v.Commit = gitCommit
|
||||
}
|
||||
}
|
||||
|
||||
// If build date not set, use current time
|
||||
if v.BuildDate == "" {
|
||||
v.BuildDate = time.Now().Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// getGitInfo returns the latest tag or short commit hash and the commit hash
|
||||
func getGitInfo() (string, string) {
|
||||
// Get the current working directory
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// Open the git repository
|
||||
repo, err := git.PlainOpen(dir)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// Get the HEAD reference
|
||||
head, err := repo.Head()
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
commitHash := head.Hash().String()[:7]
|
||||
|
||||
// Get all tags
|
||||
tagIter, err := repo.Tags()
|
||||
if err != nil {
|
||||
return commitHash, commitHash
|
||||
}
|
||||
|
||||
// Get the commit for HEAD
|
||||
commit, err := repo.CommitObject(head.Hash())
|
||||
if err != nil {
|
||||
return commitHash, commitHash
|
||||
}
|
||||
|
||||
// Build ancestry map
|
||||
ancestry := make(map[string]bool)
|
||||
c := commit
|
||||
for c != nil {
|
||||
ancestry[c.Hash.String()] = true
|
||||
c, _ = c.Parent(0)
|
||||
}
|
||||
|
||||
// Find the most recent tag that's an ancestor of HEAD
|
||||
var latestTag string
|
||||
err = tagIter.ForEach(func(ref *plumbing.Reference) error {
|
||||
// Get the target commit
|
||||
targetHash := ref.Hash()
|
||||
|
||||
// Get the target commit
|
||||
targetCommit, err := repo.CommitObject(targetHash)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if this tag is an ancestor of HEAD
|
||||
checkCommit := targetCommit
|
||||
for checkCommit != nil {
|
||||
if ancestry[checkCommit.Hash.String()] {
|
||||
// Extract tag name (remove refs/tags/ prefix)
|
||||
tagName := strings.TrimPrefix(ref.Name().String(), "refs/tags/")
|
||||
if latestTag == "" || tagName > latestTag {
|
||||
latestTag = tagName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
checkCommit, _ = checkCommit.Parent(0)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return commitHash, commitHash
|
||||
}
|
||||
|
||||
if latestTag != "" {
|
||||
return latestTag, commitHash
|
||||
}
|
||||
|
||||
return commitHash, commitHash
|
||||
}
|
||||
|
||||
// String returns a formatted version string
|
||||
func String() string {
|
||||
info := GetInfo()
|
||||
return fmt.Sprintf("Version: %s\nCommit: %s\nBuild Date: %s\n", info.Version, info.Commit, info.BuildDate)
|
||||
}
|
||||
Reference in New Issue
Block a user