mirror of
https://github.com/bluenviron/mediamtx.git
synced 2025-12-20 02:00:05 -08:00
143 lines
3.4 KiB
Go
143 lines
3.4 KiB
Go
// Package main contains an utility to get the server version
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/go-git/go-billy/v5/osfs"
|
|
"github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
"github.com/go-git/go-git/v5/plumbing/cache"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
"github.com/go-git/go-git/v5/storage/filesystem"
|
|
)
|
|
|
|
// Golang version of git describe --tags
|
|
func gitDescribeTags(repo *git.Repository) (string, error) {
|
|
head, err := repo.Head()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get HEAD: %w", err)
|
|
}
|
|
|
|
tagIterator, err := repo.Tags()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get tags: %w", err)
|
|
}
|
|
defer tagIterator.Close()
|
|
|
|
tags := make(map[plumbing.Hash]*plumbing.Reference)
|
|
|
|
err = tagIterator.ForEach(func(t *plumbing.Reference) error {
|
|
if to, err2 := repo.TagObject(t.Hash()); err2 == nil {
|
|
tags[to.Target] = t
|
|
} else {
|
|
tags[t.Hash()] = t
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to iterate tags: %w", err)
|
|
}
|
|
|
|
cIter, err := repo.Log(&git.LogOptions{From: head.Hash()})
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get log: %w", err)
|
|
}
|
|
|
|
i := 0
|
|
|
|
for {
|
|
var commit *object.Commit
|
|
commit, err = cIter.Next()
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to get next commit: %w", err)
|
|
}
|
|
|
|
if str, ok := tags[commit.Hash]; ok {
|
|
label := strings.TrimPrefix(string(str.Name()), "refs/tags/")
|
|
|
|
if i != 0 {
|
|
label += "-" + strconv.FormatInt(int64(i), 10) + "-" + head.Hash().String()[:8]
|
|
}
|
|
|
|
return label, nil
|
|
}
|
|
|
|
i++
|
|
}
|
|
}
|
|
|
|
func tagFromGit() error {
|
|
// [git.PlainOpen] uses a ChrootOS that limits filesystem access to the .git directory only.
|
|
//
|
|
// Unfortunately, this can cause issues with package build environments such as Arch Linux's,
|
|
// where .git/objects/info/alternates points to a directory outside of the .git directory.
|
|
//
|
|
// To work around this, specify an AlternatesFS that allows access to the entire filesystem.
|
|
dotGitAbs, _ := filepath.Abs("../../.git")
|
|
storerFs := osfs.New(dotGitAbs, osfs.WithBoundOS())
|
|
storer := filesystem.NewStorageWithOptions(storerFs, cache.NewObjectLRUDefault(), filesystem.Options{
|
|
AlternatesFS: osfs.New("/", osfs.WithBoundOS()),
|
|
})
|
|
workTreeAbs, _ := filepath.Abs("../../")
|
|
worktreeFs := osfs.New(workTreeAbs, osfs.WithBoundOS())
|
|
repo, err := git.Open(storer, worktreeFs)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to open repository: %w", err)
|
|
}
|
|
|
|
version, err := gitDescribeTags(repo)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get version: %w", err)
|
|
}
|
|
|
|
wt, err := repo.Worktree()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get worktree: %w", err)
|
|
}
|
|
|
|
status, err := wt.Status()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get status: %w", err)
|
|
}
|
|
|
|
if !status.IsClean() {
|
|
version += "-dirty"
|
|
}
|
|
|
|
err = os.WriteFile("VERSION", []byte(version), 0o644)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to write version file: %w", err)
|
|
}
|
|
|
|
log.Printf("ok (%s)", version)
|
|
return nil
|
|
}
|
|
|
|
func do() error {
|
|
log.Println("getting mediamtx version...")
|
|
|
|
err := tagFromGit()
|
|
if err != nil {
|
|
log.Println("WARN: cannot get tag from .git folder, using v0.0.0 as version")
|
|
err = os.WriteFile("VERSION", []byte("v0.0.0"), 0o644)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to write version file: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
err := do()
|
|
if err != nil {
|
|
log.Printf("ERR: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|