@@ -3,22 +3,260 @@ package release
33import (
44 "flag"
55 "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"
615)
716
817var 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+ }
947
1048// Install - add flags and other options
1149func Install () {
1250 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" )
1856}
1957
2058// Run - execute the command
2159func Run (args []string ) {
60+
61+ var tagToUse = * tag
62+
63+ isBeta := needsQuestionnaire (args )
2264 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
24262}
0 commit comments