package cmd import ( "context" "os" "os/exec" "regexp" "strings" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/rs/zerolog/log" ) func run(ctx context.Context, cmd string, args ...string) error { c := exec.CommandContext(ctx, cmd, args...) c.Stdout = os.Stdout c.Stderr = os.Stderr c.Stdin = os.Stdin return c.Run() } func fetch(ctx context.Context) { if err := run(ctx, "git", "fetch", "upstream"); err != nil { log.Err(err).Msg("") } } func isClean() bool { c := exec.Command("git", "status", "--porcelain") o, err := c.Output() if err != nil { log.Fatal().Err(err).Msg("could not get git status") } return len(o) == 0 } func repo() *git.Repository { repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{ DetectDotGit: true, }) if err != nil { log.Fatal().Err(err).Msg("cannot open git repository") } return repo } func worktree() *git.Worktree { tree, err := repo().Worktree() if err != nil { log.Fatal().Err(err).Msg("cannot get git worktree") } return tree } func head(name string) plumbing.Hash { ref, err := repo().Reference(plumbing.NewRemoteReferenceName("upstream", name), false) if err != nil { log.Fatal().Err(err).Msgf("cannot get remote upstream %s HEAD", name) } return ref.Hash() } var releaseRe = regexp.MustCompile(`release/v1\.(\d+)`) func latestRelease() string { cmd := exec.Command("git", "ls-remote", "upstream", "release/*") out, err := cmd.Output() if err != nil { log.Fatal().Err(err).Msg("could not get latest release") } matches := releaseRe.FindAllStringSubmatch(string(out), -1) var latest string for _, match := range matches { m := match[1] if len(m) < 3 { m = strings.Repeat("0", 3-len(m)) + m } if m > latest { latest = m } } return strings.TrimLeft(latest, "0") }