github.com/yuukihogo/migrate@v3.0.0+incompatible/cli/main.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "os" 7 "os/signal" 8 "strconv" 9 "syscall" 10 "time" 11 12 "github.com/mattes/migrate" 13 ) 14 15 // set main log 16 var log = &Log{} 17 18 func main() { 19 helpPtr := flag.Bool("help", false, "") 20 versionPtr := flag.Bool("version", false, "") 21 verbosePtr := flag.Bool("verbose", false, "") 22 prefetchPtr := flag.Uint("prefetch", 10, "") 23 lockTimeoutPtr := flag.Uint("lock-timeout", 15, "") 24 pathPtr := flag.String("path", "", "") 25 databasePtr := flag.String("database", "", "") 26 sourcePtr := flag.String("source", "", "") 27 28 flag.Usage = func() { 29 fmt.Fprint(os.Stderr, 30 `Usage: migrate OPTIONS COMMAND [arg...] 31 migrate [ -version | -help ] 32 33 Options: 34 -source Location of the migrations (driver://url) 35 -path Shorthand for -source=file://path 36 -database Run migrations against this database (driver://url) 37 -prefetch N Number of migrations to load in advance before executing (default 10) 38 -lock-timeout N Allow N seconds to acquire database lock (default 15) 39 -verbose Print verbose logging 40 -version Print version 41 -help Print usage 42 43 Commands: 44 goto V Migrate to version V 45 up [N] Apply all or N up migrations 46 down [N] Apply all or N down migrations 47 drop Drop everyting inside database 48 force V Set version V but don't run migration (ignores dirty state) 49 version Print current migration version 50 `) 51 } 52 53 flag.Parse() 54 55 // initialize logger 56 log.verbose = *verbosePtr 57 58 // show cli version 59 if *versionPtr { 60 fmt.Fprintln(os.Stderr, Version) 61 os.Exit(0) 62 } 63 64 // show help 65 if *helpPtr { 66 flag.Usage() 67 os.Exit(0) 68 } 69 70 // translate -path into -source if given 71 if *sourcePtr == "" && *pathPtr != "" { 72 *sourcePtr = fmt.Sprintf("file://%v", *pathPtr) 73 } 74 75 // initialize migrate 76 // don't catch migraterErr here and let each command decide 77 // how it wants to handle the error 78 migrater, migraterErr := migrate.New(*sourcePtr, *databasePtr) 79 defer func() { 80 if migraterErr == nil { 81 migrater.Close() 82 } 83 }() 84 if migraterErr == nil { 85 migrater.Log = log 86 migrater.PrefetchMigrations = *prefetchPtr 87 migrater.LockTimeout = time.Duration(int64(*lockTimeoutPtr)) * time.Second 88 89 // handle Ctrl+c 90 signals := make(chan os.Signal, 1) 91 signal.Notify(signals, syscall.SIGINT) 92 go func() { 93 for range signals { 94 log.Println("Stopping after this running migration ...") 95 migrater.GracefulStop <- true 96 return 97 } 98 }() 99 } 100 101 startTime := time.Now() 102 103 switch flag.Arg(0) { 104 case "goto": 105 if migraterErr != nil { 106 log.fatalErr(migraterErr) 107 } 108 109 if flag.Arg(1) == "" { 110 log.fatal("error: please specify version argument V") 111 } 112 113 v, err := strconv.ParseUint(flag.Arg(1), 10, 64) 114 if err != nil { 115 log.fatal("error: can't read version argument V") 116 } 117 118 gotoCmd(migrater, uint(v)) 119 120 if log.verbose { 121 log.Println("Finished after", time.Now().Sub(startTime)) 122 } 123 124 case "up": 125 if migraterErr != nil { 126 log.fatalErr(migraterErr) 127 } 128 129 limit := -1 130 if flag.Arg(1) != "" { 131 n, err := strconv.ParseUint(flag.Arg(1), 10, 64) 132 if err != nil { 133 log.fatal("error: can't read limit argument N") 134 } 135 limit = int(n) 136 } 137 138 upCmd(migrater, limit) 139 140 if log.verbose { 141 log.Println("Finished after", time.Now().Sub(startTime)) 142 } 143 144 case "down": 145 if migraterErr != nil { 146 log.fatalErr(migraterErr) 147 } 148 149 limit := -1 150 if flag.Arg(1) != "" { 151 n, err := strconv.ParseUint(flag.Arg(1), 10, 64) 152 if err != nil { 153 log.fatal("error: can't read limit argument N") 154 } 155 limit = int(n) 156 } 157 158 downCmd(migrater, limit) 159 160 if log.verbose { 161 log.Println("Finished after", time.Now().Sub(startTime)) 162 } 163 164 case "drop": 165 if migraterErr != nil { 166 log.fatalErr(migraterErr) 167 } 168 169 dropCmd(migrater) 170 171 if log.verbose { 172 log.Println("Finished after", time.Now().Sub(startTime)) 173 } 174 175 case "force": 176 if migraterErr != nil { 177 log.fatalErr(migraterErr) 178 } 179 180 if flag.Arg(1) == "" { 181 log.fatal("error: please specify version argument V") 182 } 183 184 v, err := strconv.ParseInt(flag.Arg(1), 10, 64) 185 if err != nil { 186 log.fatal("error: can't read version argument V") 187 } 188 189 if v < -1 { 190 log.fatal("error: argument V must be >= -1") 191 } 192 193 forceCmd(migrater, int(v)) 194 195 if log.verbose { 196 log.Println("Finished after", time.Now().Sub(startTime)) 197 } 198 199 case "version": 200 if migraterErr != nil { 201 log.fatalErr(migraterErr) 202 } 203 204 versionCmd(migrater) 205 206 default: 207 flag.Usage() 208 os.Exit(0) 209 } 210 }