aboutsummaryrefslogtreecommitdiff
path: root/main.go
blob: 45992f9c4ee6699fe26776865eba4fb898a1ef86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main

import (
	"errors"
	"fmt"
	"log"
	"os"
	"sort"

	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/plumbing"

	"github.com/spf13/cobra"
	flags "github.com/spf13/pflag"

	"github.com/Masterminds/semver/v3"
)

var (
	errNoRemoteFound = errors.New("No remotes found")
	clonedRepo       = &git.Repository{}
	localRepo        = &git.Repository{}
	repoDir          string
	remoteName       string
	rootCmd          = &cobra.Command{
		Use:       "semverbump part [major|minor|patch]",
		Short:     "A tool for bumping semver git tags.",
		ValidArgs: []string{"major", "minor", "patch"},
		Args:      cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
		Long:      `Inspired by the python bumpversion tool.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			part := args[0]
			localRepo, err := git.PlainOpen(repoDir)
			if err != nil {
				return err
			}
			// finding tags and last version
			tags, err := findTags(localRepo)
			if err != nil {
				return err
			}
			lastVersion := latestTag(tags)
			if (lastVersion == &semver.Version{}) {
				return errors.New("No tags found. Not doing anything")
			}

			// actual bump
			nextVersion := semver.Version{}
			switch part {
			case "major":
				nextVersion = lastVersion.IncMajor()
			case "minor":
				nextVersion = lastVersion.IncMinor()
			case "patch":
				nextVersion = lastVersion.IncPatch()
			}
			fmt.Fprint(cmd.OutOrStdout(), nextVersion)
			return err
		},
	}
)

func latestTag(tags []*semver.Version) *semver.Version {
	numTags := len(tags)
	if numTags == 0 {
		return &semver.Version{}
	}
	return tags[numTags-1]
}

func findTags(repo *git.Repository) ([]*semver.Version, error) {
	repoTagsIter, err := repo.Tags()
	if err != nil {
		return []*semver.Version{}, err
	}
	repoTags := []*semver.Version{}
	if err := repoTagsIter.ForEach(func(ref *plumbing.Reference) error {
		rn := plumbing.ReferenceName(ref.Name())
		version, err := semver.NewVersion(rn.Short())
		if err != nil {
			// not a semver
			return nil
		}
		repoTags = append(repoTags, version)
		return nil
	}); err != nil {
		return []*semver.Version{}, err
	}
	sort.Sort(semver.Collection(repoTags))
	return repoTags, nil
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func init() {
	// global flags
	cwd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}
	repoDir = *flags.String("repo-dir", cwd, "repo to examine")
	remoteName = *flags.String("remote-name", "origin", "remote to search and push to")
}