@@ -3,22 +3,260 @@ package release
3
3
import (
4
4
"flag"
5
5
"fmt"
6
+ "log"
7
+ "strconv"
8
+ "strings"
9
+
10
+ survey "github.com/AlecAivazis/survey/v2"
11
+ clog "github.com/barelyhuman/commitlog/log"
12
+ "github.com/go-git/go-git/v5"
13
+ "github.com/go-git/go-git/v5/plumbing"
14
+ "github.com/go-git/go-git/v5/plumbing/object"
6
15
)
7
16
8
17
var releaseCmd * flag.FlagSet
18
+ var major * bool
19
+ var minor * bool
20
+ var patch * bool
21
+ var beta * string
22
+ var tag * string
23
+
24
+ var semverPrompt = & survey.Select {
25
+ Message : "Choose a semver version:" ,
26
+ Options : []string {"major" , "minor" , "patch" , "none" },
27
+ Default : "none" ,
28
+ }
29
+
30
+ var betaPrompt = & survey.Confirm {
31
+ Message : "Is it a beta release?" ,
32
+ }
33
+
34
+ var betaSuffixPrompt = & survey.Input {
35
+ Message : "Enter the exiting beta suffix, will be also used for the any beta suffix?" ,
36
+ Default : "beta" ,
37
+ }
38
+
39
+ // TagVersion - struct holding the broken down tag
40
+ type TagVersion struct {
41
+ major string
42
+ minor string
43
+ patch string
44
+ beta string
45
+ isBeta bool
46
+ }
9
47
10
48
// Install - add flags and other options
11
49
func Install () {
12
50
releaseCmd = flag .NewFlagSet ("release" , flag .ExitOnError )
13
- releaseCmd .Bool ("- major" , false , "If release is a major one, will increment the x.0.0 " )
14
- releaseCmd .Bool ("- minor" , false , "If release is a minor one, will increment the 0.x.0 " )
15
- releaseCmd .Bool ("- patch" , false , "If release is a patch, will increment the 0.0.x " )
16
- releaseCmd .Bool ( "- beta" , false , "If the release is a beta, to add/increment tag by `-beta.x`" )
17
- releaseCmd .String ("- tag" , "" , "The Tag to be taken as base" )
51
+ major = releaseCmd .Bool ("major" , false , "If release is a major one, will increment the x.0.0 " )
52
+ minor = releaseCmd .Bool ("minor" , false , "If release is a minor one, will increment the 0.x.0 " )
53
+ patch = releaseCmd .Bool ("patch" , false , "If release is a patch, will increment the 0.0.x " )
54
+ beta = releaseCmd .String ( " beta" , "beta" , "If the release is a beta, to add/increment tag with `-beta.x` or mentioned string " )
55
+ tag = releaseCmd .String ("tag" , "" , "The Tag to be taken as base" )
18
56
}
19
57
20
58
// Run - execute the command
21
59
func Run (args []string ) {
60
+
61
+ var tagToUse = * tag
62
+
63
+ isBeta := needsQuestionnaire (args )
22
64
releaseCmd .Parse (args )
23
- fmt .Println ("Note: The release command is not yet implemented" )
65
+
66
+ if tagToUse == "" {
67
+ tagToUse = getTagString ()
68
+ }
69
+
70
+ createRelease (tagToUse , * major , * minor , * patch , * beta , isBeta )
71
+ }
72
+
73
+ // needsQuestionnaire - Check semver and beta if no args were supplied
74
+ func needsQuestionnaire (args []string ) bool {
75
+ var semver string
76
+ var isBeta bool
77
+
78
+ if len (args ) < 1 {
79
+ err := survey .AskOne (semverPrompt , & semver )
80
+ if err != nil {
81
+ fmt .Println (err .Error ())
82
+ return false
83
+ }
84
+
85
+ err = survey .AskOne (betaPrompt , & isBeta )
86
+ if err != nil {
87
+ fmt .Println (err .Error ())
88
+ return false
89
+ }
90
+
91
+ err = survey .AskOne (betaSuffixPrompt , beta )
92
+ if err != nil {
93
+ fmt .Println (err .Error ())
94
+ return false
95
+ }
96
+
97
+ switch semver {
98
+ case "major" :
99
+ * major = true
100
+ break
101
+ case "minor" :
102
+ * minor = true
103
+ break
104
+ case "patch" :
105
+ * patch = true
106
+ break
107
+ }
108
+ }
109
+
110
+ return isBeta
111
+ }
112
+
113
+ func createRelease (tagString string , increaseMajor bool , increaseMinor bool , increasePatch bool , betaSuffix string , isBeta bool ) {
114
+ version , hasV := breakTag (tagString )
115
+ releaseTagString := ""
116
+
117
+ majorAsInt , err := strconv .ParseInt (version .major , 10 , 32 )
118
+ if err != nil {
119
+ log .Fatal ("Error converting to number on version.major" , version )
120
+ }
121
+ minorAsInt , err := strconv .ParseInt (version .minor , 10 , 32 )
122
+ if err != nil {
123
+ log .Fatal ("Error converting to number on version.minor" , version )
124
+ }
125
+ patchAsInt , err := strconv .ParseInt (version .patch , 10 , 32 )
126
+ if err != nil {
127
+ log .Fatal ("Error converting to number on version.patch" , version )
128
+ }
129
+ betaAsInt , err := strconv .ParseInt (version .beta , 10 , 32 )
130
+ if err != nil {
131
+ log .Fatal ("Error converting to number on version.beta" , version )
132
+ }
133
+
134
+ if hasV {
135
+ releaseTagString += "v"
136
+ }
137
+
138
+ if increaseMajor {
139
+ majorAsInt ++
140
+ }
141
+
142
+ if increaseMinor {
143
+ minorAsInt ++
144
+ }
145
+
146
+ if increasePatch {
147
+ patchAsInt ++
148
+ }
149
+
150
+ releaseTagString += fmt .Sprintf ("%d.%d.%d" , majorAsInt , minorAsInt , patchAsInt )
151
+
152
+ if isBeta {
153
+ betaAsInt ++
154
+ releaseTagString += fmt .Sprintf ("-%s.%d" , betaSuffix , betaAsInt )
155
+ }
156
+
157
+ fmt .Println (releaseTagString )
158
+
159
+ isConfirmed := confirmRelease (releaseTagString )
160
+
161
+ if ! isConfirmed {
162
+ return
163
+ }
164
+
165
+ repo := clog .OpenRepository ("." )
166
+
167
+ setTag (repo , releaseTagString )
168
+ }
169
+
170
+ func tagExists (tag string , r * git.Repository ) bool {
171
+ tagFoundErr := "tag was found"
172
+ tags , err := r .TagObjects ()
173
+ if err != nil {
174
+ log .Printf ("get tags error: %s" , err )
175
+ return false
176
+ }
177
+ res := false
178
+ err = tags .ForEach (func (t * object.Tag ) error {
179
+ if t .Name == tag {
180
+ res = true
181
+ return fmt .Errorf (tagFoundErr )
182
+ }
183
+ return nil
184
+ })
185
+ if err != nil && err .Error () != tagFoundErr {
186
+ log .Printf ("iterate tags error: %s" , err )
187
+ return false
188
+ }
189
+ return res
190
+ }
191
+
192
+ func setTag (r * git.Repository , tag string ) (bool , error ) {
193
+ if tagExists (tag , r ) {
194
+ log .Printf ("tag %s already exists" , tag )
195
+ return false , nil
196
+ }
197
+ log .Printf ("Set tag %s" , tag )
198
+ h , err := r .Head ()
199
+ if err != nil {
200
+ log .Printf ("get HEAD error: %s" , err )
201
+ return false , err
202
+ }
203
+
204
+ _ , err = r .CreateTag (tag , h .Hash (), & git.CreateTagOptions {
205
+ Message : tag ,
206
+ })
207
+
208
+ if err != nil {
209
+ log .Printf ("create tag error: %s" , err )
210
+ return false , err
211
+ }
212
+
213
+ return true , nil
214
+ }
215
+
216
+ func confirmRelease (tag string ) bool {
217
+ var confirm bool
218
+
219
+ confirmReleasePrompt := & survey.Confirm {
220
+ Message : "Do you want me to create the following tag: " + tag + " ?" ,
221
+ }
222
+
223
+ err := survey .AskOne (confirmReleasePrompt , & confirm )
224
+
225
+ if err != nil {
226
+ log .Fatalln (err )
227
+ }
228
+ return confirm
229
+ }
230
+
231
+ func breakTag (tagString string ) (* TagVersion , bool ) {
232
+ hasV := false
233
+ version := & TagVersion {}
234
+ tagSplits := strings .Split (tagString , "." )
235
+
236
+ version .major = tagSplits [0 ]
237
+ version .minor = tagSplits [1 ]
238
+ version .patch = tagSplits [2 ]
239
+ version .beta = tagSplits [3 ]
240
+
241
+ // Check if the major version has the letter `v` in the tag
242
+ if len (version .major ) > 1 && strings .Contains (version .major , "v" ) {
243
+ version .major = version .major [len ("v" ):]
244
+ hasV = true
245
+ }
246
+
247
+ if len (version .patch ) > 1 && strings .Contains (version .patch , "-" + * beta ) {
248
+ version .patch = strings .Replace (version .patch , "-" + * beta , "" , - 1 )
249
+ }
250
+
251
+ return version , hasV
252
+ }
253
+
254
+ func getTagString () string {
255
+ currentRepository := clog .OpenRepository ("." )
256
+ var tagRef * plumbing.Reference
257
+ if * tag == "" {
258
+ tagRef , _ , _ = clog .GetLatestTagFromRepository (currentRepository )
259
+ }
260
+ onlyTag := tagRef .Name ().Short ()
261
+ return onlyTag
24
262
}
0 commit comments