@@ -15,11 +15,47 @@ import (
15
15
"github.com/golang-migrate/migrate/v4/source"
16
16
)
17
17
18
- const defaultTimeFormat = "20060102150405"
18
+ const (
19
+ defaultTimeFormat = "20060102150405"
20
+ createUsage = `create [-ext E] [-dir D] [-seq] [-digits N] [-format] NAME
21
+ Create a set of timestamped up/down migrations titled NAME, in directory D with extension E.
22
+ Use -seq option to generate sequential up/down migrations with N digits.
23
+ Use -format option to specify a Go time format string. Note: migrations with the same time cause "duplicate migration version" error.
24
+ `
25
+ gotoUsage = `goto V Migrate to version V`
26
+ upUsage = `up [N] Apply all or N up migrations`
27
+ downUsage = `down [N] Apply all or N down migrations`
28
+ dropUsage = `drop [-f] [-all] Drop everything inside database
29
+ Use -f to bypass confirmation
30
+ Use -all to apply all down migrations`
31
+ forceUsage = `force V Set version V but don't run migration (ignores dirty state)`
32
+ )
33
+
34
+ func handleSubCmdHelp (help bool , usage string , flagSet * flag.FlagSet ) {
35
+ if help {
36
+ fmt .Fprintln (os .Stderr , usage )
37
+ flagSet .PrintDefaults ()
38
+ os .Exit (0 )
39
+ }
40
+ }
41
+
42
+ func newFlagSetWithHelp (name string ) (* flag.FlagSet , * bool ) {
43
+ flagSet := flag .NewFlagSet (name , flag .ExitOnError )
44
+ helpPtr := flagSet .Bool ("help" , false , "Print help information" )
45
+ return flagSet , helpPtr
46
+ }
19
47
20
48
// set main log
21
49
var log = & Log {}
22
50
51
+ func printUsageAndExit () {
52
+ flag .Usage ()
53
+
54
+ // If a command is not found we exit with a status 2 to match the behavior
55
+ // of flag.Parse() with flag.ExitOnError when parsing an invalid flag.
56
+ os .Exit (2 )
57
+ }
58
+
23
59
// Main function of a cli application. It is public for backwards compatibility with `cli` package
24
60
func Main (version string ) {
25
61
helpPtr := flag .Bool ("help" , false , "" )
@@ -32,7 +68,7 @@ func Main(version string) {
32
68
sourcePtr := flag .String ("source" , "" , "" )
33
69
34
70
flag .Usage = func () {
35
- fmt .Fprint (os .Stderr ,
71
+ fmt .Fprintf (os .Stderr ,
36
72
`Usage: migrate OPTIONS COMMAND [arg...]
37
73
migrate [ -version | -help ]
38
74
@@ -47,20 +83,16 @@ Options:
47
83
-help Print usage
48
84
49
85
Commands:
50
- create [-ext E] [-dir D] [-seq] [-digits N] [-format] NAME
51
- Create a set of timestamped up/down migrations titled NAME, in directory D with extension E.
52
- Use -seq option to generate sequential up/down migrations with N digits.
53
- Use -format option to specify a Go time format string. Note: migrations with the same time cause "duplicate migration version" error.
54
- goto V Migrate to version V
55
- up [N] Apply all or N up migrations
56
- down [N] Apply all or N down migrations
57
- drop [-f] Drop everything inside database
58
- Use -f to bypass confirmation
59
- force V Set version V but don't run migration (ignores dirty state)
86
+ %s
87
+ %s
88
+ %s
89
+ %s
90
+ %s
91
+ %s
60
92
version Print current migration version
61
93
62
94
Source drivers: ` + strings .Join (source .List (), ", " )+ `
63
- Database drivers: ` + strings .Join (database .List (), ", " )+ "\n " )
95
+ Database drivers: ` + strings .Join (database .List (), ", " )+ "\n " , createUsage , gotoUsage , upUsage , downUsage , dropUsage , forceUsage )
64
96
}
65
97
66
98
flag .Parse ()
@@ -115,22 +147,30 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
115
147
116
148
startTime := time .Now ()
117
149
150
+ if len (flag .Args ()) < 1 {
151
+ printUsageAndExit ()
152
+ }
153
+ args := flag .Args ()[1 :]
154
+
118
155
switch flag .Arg (0 ) {
119
156
case "create" :
120
- args := flag . Args ()[ 1 :]
157
+
121
158
seq := false
122
159
seqDigits := 6
123
160
124
- createFlagSet := flag . NewFlagSet ("create" , flag . ExitOnError )
161
+ createFlagSet , help := newFlagSetWithHelp ("create" )
125
162
extPtr := createFlagSet .String ("ext" , "" , "File extension" )
126
163
dirPtr := createFlagSet .String ("dir" , "" , "Directory to place file in (default: current working directory)" )
127
164
formatPtr := createFlagSet .String ("format" , defaultTimeFormat , `The Go time format string to use. If the string "unix" or "unixNano" is specified, then the seconds or nanoseconds since January 1, 1970 UTC respectively will be used. Caution, due to the behavior of time.Time.Format(), invalid format strings will not error` )
128
165
createFlagSet .BoolVar (& seq , "seq" , seq , "Use sequential numbers instead of timestamps (default: false)" )
129
166
createFlagSet .IntVar (& seqDigits , "digits" , seqDigits , "The number of digits to use in sequences (default: 6)" )
167
+
130
168
if err := createFlagSet .Parse (args ); err != nil {
131
- log .Println (err )
169
+ log .fatalErr (err )
132
170
}
133
171
172
+ handleSubCmdHelp (* help , createUsage , createFlagSet )
173
+
134
174
if createFlagSet .NArg () == 0 {
135
175
log .fatal ("error: please specify name" )
136
176
}
@@ -145,11 +185,20 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
145
185
}
146
186
147
187
case "goto" :
188
+
189
+ gotoSet , helpPtr := newFlagSetWithHelp ("goto" )
190
+
191
+ if err := gotoSet .Parse (args ); err != nil {
192
+ log .fatalErr (err )
193
+ }
194
+
195
+ handleSubCmdHelp (* helpPtr , gotoUsage , gotoSet )
196
+
148
197
if migraterErr != nil {
149
198
log .fatalErr (migraterErr )
150
199
}
151
200
152
- if flag .Arg ( 1 ) == "" {
201
+ if flag .NArg ( ) == 0 {
153
202
log .fatal ("error: please specify version argument V" )
154
203
}
155
204
@@ -167,12 +216,20 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
167
216
}
168
217
169
218
case "up" :
219
+ upSet , helpPtr := newFlagSetWithHelp ("up" )
220
+
221
+ if err := upSet .Parse (args ); err != nil {
222
+ log .fatalErr (err )
223
+ }
224
+
225
+ handleSubCmdHelp (* helpPtr , upUsage , upSet )
226
+
170
227
if migraterErr != nil {
171
228
log .fatalErr (migraterErr )
172
229
}
173
230
174
231
limit := - 1
175
- if flag .Arg ( 1 ) != "" {
232
+ if flag .NArg () > 0 {
176
233
n , err := strconv .ParseUint (flag .Arg (1 ), 10 , 64 )
177
234
if err != nil {
178
235
log .fatal ("error: can't read limit argument N" )
@@ -189,18 +246,19 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
189
246
}
190
247
191
248
case "down" :
192
- if migraterErr != nil {
193
- log .fatalErr (migraterErr )
194
- }
195
-
196
- downFlagSet := flag .NewFlagSet ("down" , flag .ExitOnError )
249
+ downFlagSet , helpPtr := newFlagSetWithHelp ("down" )
197
250
applyAll := downFlagSet .Bool ("all" , false , "Apply all down migrations" )
198
251
199
- args := flag .Args ()[1 :]
200
252
if err := downFlagSet .Parse (args ); err != nil {
201
253
log .fatalErr (err )
202
254
}
203
255
256
+ handleSubCmdHelp (* helpPtr , downUsage , downFlagSet )
257
+
258
+ if migraterErr != nil {
259
+ log .fatalErr (migraterErr )
260
+ }
261
+
204
262
downArgs := downFlagSet .Args ()
205
263
num , needsConfirm , err := numDownMigrationsFromArgs (* applyAll , downArgs )
206
264
if err != nil {
@@ -228,14 +286,15 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
228
286
}
229
287
230
288
case "drop" :
231
- dropFlagSet := flag . NewFlagSet ("drop" , flag . ExitOnError )
289
+ dropFlagSet , help := newFlagSetWithHelp ("drop" )
232
290
forceDrop := dropFlagSet .Bool ("f" , false , "Force the drop command by bypassing the confirmation prompt" )
233
291
234
- args := flag .Args ()[1 :]
235
292
if err := dropFlagSet .Parse (args ); err != nil {
236
293
log .fatalErr (err )
237
294
}
238
295
296
+ handleSubCmdHelp (* help , dropUsage , dropFlagSet )
297
+
239
298
if ! * forceDrop {
240
299
log .Println ("Are you sure you want to drop the entire database schema? [y/N]" )
241
300
var response string
@@ -262,11 +321,19 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
262
321
}
263
322
264
323
case "force" :
324
+ forceSet , helpPtr := newFlagSetWithHelp ("force" )
325
+
326
+ if err := forceSet .Parse (args ); err != nil {
327
+ log .fatalErr (err )
328
+ }
329
+
330
+ handleSubCmdHelp (* helpPtr , forceUsage , forceSet )
331
+
265
332
if migraterErr != nil {
266
333
log .fatalErr (migraterErr )
267
334
}
268
335
269
- if flag .Arg ( 1 ) == "" {
336
+ if flag .NArg ( ) == 0 {
270
337
log .fatal ("error: please specify version argument V" )
271
338
}
272
339
@@ -297,10 +364,6 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n")
297
364
}
298
365
299
366
default :
300
- flag .Usage ()
301
-
302
- // If a command is not found we exit with a status 2 to match the behavior
303
- // of flag.Parse() with flag.ExitOnError when parsing an invalid flag.
304
- os .Exit (2 )
367
+ printUsageAndExit ()
305
368
}
306
369
}
0 commit comments