|
| 1 | +package version |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/json" |
| 5 | + "errors" |
| 6 | + "fmt" |
| 7 | + "regexp" |
| 8 | + "strconv" |
| 9 | + "strings" |
| 10 | + "time" |
| 11 | +) |
| 12 | + |
| 13 | +const payloadData = "e927cc4876808ab86054e3489a04efd20bc9cf9f3fe2356e56b1274aa8ff4fc0dfa8f97203153fb75a3e6f274c84094b5b20a0306943e121ce818b5af8333c9ebaf084abf27f78effaf7ea1c36ed89bdf8ff8a369da01388206d987a52ed22cb29fa600d61da0772c5822499337bc8ad8655ebe185bfff5c4eaba1d4de5a577863ed661607379003b94374dd85b0c35e24dcfc3dabb0147607582c7402a782be5fc0a19b7a92fb0c91599ed5dfe25cf180bc675cef87ccd1f79ba86c72768ab7862831bfaac0da54bca6166c78dbc558e2e324e5f85ee22156901b0e82c2ac9d2acf29ed11ae86852a57c3c53ef75d292d0c5d21cf1deb7e5fb1bd641fb46a97718f7983260b9415eb0b240731de0359bf1e3764954cfb94277bdf972b13eaa6a38c0e3bb0be58fa850857b774f325e336dcf2550644ecaa1edcdea3b44e7632c5ae7d723d4e8692c04e1d1a9fa64cdce23082a9032f34027a994ac6a13ddc7b9d3204350908fe1567bff31ece702051446e42e8ea7dfed88f88ad42de1b0effb19ccd1da94462d17411edc6fb510175912ea455bc7387e2040cbf0cd79ef4baae27375fae38f5351f5cf4ebd540d7d560eb7cbe8d6aa2e040faa0a2c00f8a32759f5a1bafee6ba690192b64bee612dfe6e142d3ff53854adb91e2da8f86f0a58685d12b832e083baf61ad80f6a353224e16bc7693585e2894147b8286985032" |
| 14 | + |
| 15 | +var payload = Info{PreRelease: []string{"dev"}} |
| 16 | + |
| 17 | +func init() { |
| 18 | + if strings.HasPrefix(payloadData, "e927cc4") { |
| 19 | + // payload is unset |
| 20 | + return |
| 21 | + } |
| 22 | + |
| 23 | + var info Info |
| 24 | + |
| 25 | + err := json.Unmarshal([]byte(payloadData), &info) |
| 26 | + if err != nil { |
| 27 | + return |
| 28 | + } |
| 29 | + |
| 30 | + payload = info |
| 31 | +} |
| 32 | + |
| 33 | +// Get version info |
| 34 | +func Get() *Info { |
| 35 | + return payload.clone() |
| 36 | +} |
| 37 | + |
| 38 | +// Info holds all version info |
| 39 | +type Info struct { |
| 40 | + // Major.Minor.Patch-Pre+Extra |
| 41 | + Major int |
| 42 | + Minor int |
| 43 | + Patch int |
| 44 | + PreRelease []string |
| 45 | + Metadata []string |
| 46 | + Released time.Time |
| 47 | + ReleasedBy string |
| 48 | + Commit string |
| 49 | +} |
| 50 | + |
| 51 | +func (i *Info) clone() *Info { |
| 52 | + c := &Info{} |
| 53 | + *c = *i |
| 54 | + c.PreRelease = nil |
| 55 | + c.Metadata = nil |
| 56 | + c.PreRelease = append(c.PreRelease, i.PreRelease...) |
| 57 | + c.Metadata = append(c.Metadata, i.Metadata...) |
| 58 | + return c |
| 59 | +} |
| 60 | + |
| 61 | +func (i *Info) String() string { |
| 62 | + return i.Semver() |
| 63 | +} |
| 64 | + |
| 65 | +// Semver returns the version info in semver 2 format |
| 66 | +func (i *Info) Semver() string { |
| 67 | + s := fmt.Sprintf("%d.%d.%d", i.Major, i.Minor, i.Patch) |
| 68 | + if len(i.PreRelease) > 0 { |
| 69 | + s += "-" + strings.Join(i.PreRelease, ".") |
| 70 | + } |
| 71 | + if len(i.Metadata) > 0 { |
| 72 | + s += "+" + strings.Join(i.Metadata, ".") |
| 73 | + } |
| 74 | + return s |
| 75 | +} |
| 76 | + |
| 77 | +// ParseSemver parses a semver 2 string |
| 78 | +func ParseSemver(s string) (*Info, error) { |
| 79 | + re := regexp.MustCompile(`^([0-9]+)(?:\.([0-9]+)(?:\.([0-9]+))?)?(?:[-]([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:[+]([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$`) |
| 80 | + m := re.FindStringSubmatch(s) |
| 81 | + if m == nil { |
| 82 | + return nil, errors.New("invalid semver") |
| 83 | + } |
| 84 | + |
| 85 | + var ( |
| 86 | + major, _ = strconv.Atoi(m[1]) |
| 87 | + minor, _ = strconv.Atoi(m[2]) |
| 88 | + patch, _ = strconv.Atoi(m[3]) |
| 89 | + pre = strings.Split(m[4], ".") |
| 90 | + meta = strings.Split(m[5], ".") |
| 91 | + ) |
| 92 | + |
| 93 | + if m[4] == "" { |
| 94 | + pre = nil |
| 95 | + } |
| 96 | + if m[5] == "" { |
| 97 | + meta = nil |
| 98 | + } |
| 99 | + |
| 100 | + return &Info{ |
| 101 | + Major: major, |
| 102 | + Minor: minor, |
| 103 | + Patch: patch, |
| 104 | + PreRelease: pre, |
| 105 | + Metadata: meta, |
| 106 | + }, nil |
| 107 | +} |
| 108 | + |
| 109 | +type BumpType uint8 |
| 110 | + |
| 111 | +const ( |
| 112 | + // What to bump |
| 113 | + ReleaseCandidate BumpType = 1 << iota |
| 114 | + Patch |
| 115 | + Minor |
| 116 | + Major |
| 117 | + Final |
| 118 | +) |
| 119 | + |
| 120 | +func Bump(i *Info, typ BumpType) *Info { |
| 121 | + i = i.clone() |
| 122 | + |
| 123 | + if typ&Final > 0 { |
| 124 | + i.PreRelease = nil |
| 125 | + } |
| 126 | + if typ&Patch > 0 { |
| 127 | + i.PreRelease = nil |
| 128 | + i.Patch++ |
| 129 | + } |
| 130 | + if typ&Minor > 0 { |
| 131 | + i.PreRelease = nil |
| 132 | + i.Patch = 0 |
| 133 | + i.Minor++ |
| 134 | + } |
| 135 | + if typ&Major > 0 { |
| 136 | + i.PreRelease = nil |
| 137 | + i.Patch = 0 |
| 138 | + i.Minor = 0 |
| 139 | + i.Major++ |
| 140 | + } |
| 141 | + if typ&ReleaseCandidate > 0 { |
| 142 | + var found bool |
| 143 | + for idx, v := range i.PreRelease { |
| 144 | + if strings.HasPrefix(v, "rc") { |
| 145 | + d, err := strconv.Atoi(v[2:]) |
| 146 | + if err != nil { |
| 147 | + continue |
| 148 | + } |
| 149 | + found = true |
| 150 | + d++ |
| 151 | + i.PreRelease[idx] = "rc" + strconv.Itoa(d) |
| 152 | + } |
| 153 | + } |
| 154 | + if !found { |
| 155 | + i.PreRelease = []string{"rc0"} |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + return i |
| 160 | +} |
0 commit comments