migrate/main.go

244 lines
5.1 KiB
Go
Raw Normal View History

2014-08-13 01:58:36 +00:00
// Package main is the CLI.
// You can use the CLI via Terminal.
// import "github.com/mattes/migrate/migrate" for usage within Go.
2014-08-11 01:42:57 +00:00
package main
import (
"flag"
"fmt"
2015-10-01 13:41:04 +00:00
"os"
"strconv"
"time"
"github.com/fatih/color"
2015-11-12 10:38:53 +00:00
_ "github.com/mattes/migrate/driver/bash"
_ "github.com/mattes/migrate/driver/cassandra"
_ "github.com/mattes/migrate/driver/mysql"
_ "github.com/mattes/migrate/driver/postgres"
_ "github.com/mattes/migrate/driver/sqlite3"
2015-12-09 00:20:12 +00:00
_ "github.com/mattes/migrate/driver/neo4j"
2014-08-12 20:20:17 +00:00
"github.com/mattes/migrate/file"
2014-08-11 01:42:57 +00:00
"github.com/mattes/migrate/migrate"
2014-08-12 20:20:17 +00:00
"github.com/mattes/migrate/migrate/direction"
2014-08-12 01:36:07 +00:00
pipep "github.com/mattes/migrate/pipe"
2014-08-11 01:42:57 +00:00
)
var url = flag.String("url", os.Getenv("MIGRATE_URL"), "")
2014-08-13 22:22:56 +00:00
var migrationsPath = flag.String("path", "", "")
var version = flag.Bool("version", false, "Show migrate version")
2014-08-11 01:42:57 +00:00
func main() {
2015-10-01 13:41:04 +00:00
flag.Usage = func() {
helpCmd()
}
2014-08-11 01:42:57 +00:00
flag.Parse()
2014-08-11 02:28:00 +00:00
command := flag.Arg(0)
if *version {
2014-10-10 23:39:08 +00:00
fmt.Println(Version)
os.Exit(0)
}
2014-08-13 22:22:56 +00:00
if *migrationsPath == "" {
*migrationsPath, _ = os.Getwd()
}
2014-08-11 01:42:57 +00:00
switch command {
case "create":
2014-08-11 02:59:51 +00:00
verifyMigrationsPath(*migrationsPath)
2014-08-12 20:20:17 +00:00
name := flag.Arg(1)
if name == "" {
fmt.Println("Please specify name.")
os.Exit(1)
}
2014-08-13 22:22:56 +00:00
migrationFile, err := migrate.Create(*url, *migrationsPath, name)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Version %v migration files created in %v:\n", migrationFile.Version, *migrationsPath)
2014-08-13 22:22:56 +00:00
fmt.Println(migrationFile.UpFile.FileName)
fmt.Println(migrationFile.DownFile.FileName)
2014-08-11 02:28:00 +00:00
case "migrate":
2014-08-11 02:59:51 +00:00
verifyMigrationsPath(*migrationsPath)
2014-08-11 02:28:00 +00:00
relativeN := flag.Arg(1)
relativeNInt, err := strconv.Atoi(relativeN)
2014-08-11 01:42:57 +00:00
if err != nil {
2014-09-25 16:43:08 +00:00
fmt.Println("Unable to parse param <n>.")
2014-08-11 01:42:57 +00:00
os.Exit(1)
}
2014-08-13 22:22:56 +00:00
timerStart = time.Now()
pipe := pipep.New()
go migrate.Migrate(pipe, *url, *migrationsPath, relativeNInt)
2014-12-19 10:40:11 +00:00
ok := writePipe(pipe)
2014-08-13 22:22:56 +00:00
printTimer()
2014-12-19 10:40:11 +00:00
if !ok {
os.Exit(1)
}
2014-08-11 02:59:51 +00:00
2014-09-25 16:43:08 +00:00
case "goto":
verifyMigrationsPath(*migrationsPath)
2014-10-04 07:46:29 +00:00
toVersion := flag.Arg(1)
toVersionInt, err := strconv.Atoi(toVersion)
if err != nil || toVersionInt < 0 {
2014-09-25 16:43:08 +00:00
fmt.Println("Unable to parse param <v>.")
os.Exit(1)
}
currentVersion, err := migrate.Version(*url, *migrationsPath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
2014-10-04 07:46:29 +00:00
relativeNInt := toVersionInt - int(currentVersion)
2014-09-25 16:43:08 +00:00
timerStart = time.Now()
pipe := pipep.New()
go migrate.Migrate(pipe, *url, *migrationsPath, relativeNInt)
2014-12-19 10:40:11 +00:00
ok := writePipe(pipe)
2014-09-25 16:43:08 +00:00
printTimer()
2014-12-19 10:40:11 +00:00
if !ok {
os.Exit(1)
}
2014-09-25 16:43:08 +00:00
2014-08-11 02:59:51 +00:00
case "up":
verifyMigrationsPath(*migrationsPath)
2014-08-13 22:22:56 +00:00
timerStart = time.Now()
pipe := pipep.New()
go migrate.Up(pipe, *url, *migrationsPath)
2014-12-19 10:40:11 +00:00
ok := writePipe(pipe)
2014-08-13 22:22:56 +00:00
printTimer()
2014-12-19 10:40:11 +00:00
if !ok {
os.Exit(1)
}
2014-08-11 02:59:51 +00:00
case "down":
verifyMigrationsPath(*migrationsPath)
2014-08-13 22:22:56 +00:00
timerStart = time.Now()
pipe := pipep.New()
go migrate.Down(pipe, *url, *migrationsPath)
2014-12-19 10:40:11 +00:00
ok := writePipe(pipe)
2014-08-13 22:22:56 +00:00
printTimer()
2014-12-19 10:40:11 +00:00
if !ok {
os.Exit(1)
}
2014-08-11 02:59:51 +00:00
case "redo":
verifyMigrationsPath(*migrationsPath)
2014-08-13 22:22:56 +00:00
timerStart = time.Now()
pipe := pipep.New()
go migrate.Redo(pipe, *url, *migrationsPath)
2014-12-19 10:40:11 +00:00
ok := writePipe(pipe)
2014-08-13 22:22:56 +00:00
printTimer()
2014-12-19 10:40:11 +00:00
if !ok {
os.Exit(1)
}
2014-08-11 02:59:51 +00:00
case "reset":
verifyMigrationsPath(*migrationsPath)
2014-08-13 22:22:56 +00:00
timerStart = time.Now()
pipe := pipep.New()
go migrate.Reset(pipe, *url, *migrationsPath)
2014-12-19 10:40:11 +00:00
ok := writePipe(pipe)
2014-08-13 22:22:56 +00:00
printTimer()
2014-12-19 10:40:11 +00:00
if !ok {
os.Exit(1)
}
2014-08-11 02:59:51 +00:00
case "version":
verifyMigrationsPath(*migrationsPath)
2014-08-13 22:22:56 +00:00
version, err := migrate.Version(*url, *migrationsPath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(version)
2014-08-11 02:28:00 +00:00
2014-08-11 02:59:51 +00:00
default:
2014-08-13 22:24:53 +00:00
fallthrough
case "help":
2014-08-11 02:59:51 +00:00
helpCmd()
2014-08-11 01:42:57 +00:00
}
}
func writePipe(pipe chan interface{}) (ok bool) {
okFlag := true
2014-08-11 22:58:30 +00:00
if pipe != nil {
for {
select {
case item, more := <-pipe:
if !more {
return okFlag
2014-08-11 22:58:30 +00:00
} else {
switch item.(type) {
2014-08-11 22:58:30 +00:00
case string:
fmt.Println(item.(string))
2014-08-11 22:58:30 +00:00
case error:
c := color.New(color.FgRed)
2014-08-13 02:22:59 +00:00
c.Println(item.(error).Error(), "\n")
okFlag = false
2014-08-12 20:20:17 +00:00
case file.File:
f := item.(file.File)
2014-08-13 02:22:59 +00:00
c := color.New(color.FgBlue)
2014-08-12 20:20:17 +00:00
if f.Direction == direction.Up {
2014-08-13 02:22:59 +00:00
c.Print(">")
2014-08-12 20:20:17 +00:00
} else if f.Direction == direction.Down {
2014-08-13 02:22:59 +00:00
c.Print("<")
2014-08-12 20:20:17 +00:00
}
fmt.Printf(" %s\n", f.FileName)
2014-08-11 22:58:30 +00:00
default:
text := fmt.Sprint(item)
2014-08-13 21:15:03 +00:00
fmt.Println(text)
2014-08-11 22:58:30 +00:00
}
}
}
}
}
return okFlag
2014-08-11 22:58:30 +00:00
}
2014-08-13 22:22:56 +00:00
func verifyMigrationsPath(path string) {
if path == "" {
fmt.Println("Please specify path")
os.Exit(1)
}
}
2014-08-12 20:20:17 +00:00
var timerStart time.Time
func printTimer() {
diff := time.Now().Sub(timerStart).Seconds()
if diff > 60 {
fmt.Printf("\n%.4f minutes\n", diff/60)
} else {
fmt.Printf("\n%.4f seconds\n", diff)
}
2014-08-12 20:20:17 +00:00
}
2014-08-11 02:59:51 +00:00
func helpCmd() {
os.Stderr.WriteString(
2014-08-13 22:26:44 +00:00
`usage: migrate [-path=<path>] -url=<url> <command> [<args>]
2014-08-11 02:59:51 +00:00
Commands:
create <name> Create a new migration
up Apply all -up- migrations
down Apply all -down- migrations
reset Down followed by Up
redo Roll back most recent migration, then apply it again
version Show current migration version
migrate <n> Apply migrations -n|+n
2014-09-25 16:43:08 +00:00
goto <v> Migrate to version v
2014-08-11 02:59:51 +00:00
help Show this help
2014-08-13 22:22:56 +00:00
'-path' defaults to current working directory.
2014-08-11 02:59:51 +00:00
`)
}