mirror of https://github.com/pressly/goose.git
Merge pull request #157 from pressly/remove_goose_pkg_deps
Remove goose pkg depspull/161/head v2.7.0-rc3
commit
f6dca2b18a
|
@ -32,7 +32,7 @@ This will install the `goose` binary to your `$GOPATH/bin` directory.
|
|||
|
||||
For a lite version of the binary without DB connection dependent commands, use the exclusive build tags:
|
||||
|
||||
$ go build -tags='no_mysql no_sqlite no_psql' -i -o goose ./cmd/goose
|
||||
$ go build -tags='no_postgres no_mysql no_sqlite3' -i -o goose ./cmd/goose
|
||||
|
||||
|
||||
# Usage
|
||||
|
|
|
@ -3,6 +3,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/ziutek/mymysql/godrv"
|
||||
)
|
||||
|
||||
// normalizeMySQLDSN parses the dsn used with the mysql driver to always have
|
||||
// the parameter `parseTime` set to true. This allows internal goose logic
|
||||
// to assume that DATETIME/DATE/TIMESTAMP can be scanned into the time.Time
|
||||
// type.
|
||||
func normalizeDBString(driver string, str string) string {
|
||||
if driver == "mysql" {
|
||||
var err error
|
||||
str, err = normalizeMySQLDSN(str)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to normalize MySQL connection string: %v", err)
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func normalizeMySQLDSN(dsn string) (string, error) {
|
||||
config, err := mysql.ParseDSN(dsn)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
config.ParseTime = true
|
||||
return config.FormatDSN(), nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// +build no_mysql
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/ziutek/mymysql/godrv"
|
||||
)
|
||||
|
||||
func normalizeDBString(driver string, str string) string {
|
||||
return str
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// +build !no_pq
|
||||
// +build !no_postgres
|
||||
|
||||
package main
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// +build !no_sqlite
|
||||
// +build !no_sqlite3
|
||||
|
||||
package main
|
||||
|
|
@ -55,13 +55,7 @@ func main() {
|
|||
|
||||
driver, dbstring, command := args[0], args[1], args[2]
|
||||
|
||||
switch dbstring {
|
||||
case "":
|
||||
log.Fatalf("-dbstring=%q not supported\n", dbstring)
|
||||
default:
|
||||
}
|
||||
|
||||
db, err := goose.OpenDBWithDriver(driver, dbstring)
|
||||
db, err := goose.OpenDBWithDriver(driver, normalizeDBString(driver, dbstring))
|
||||
if err != nil {
|
||||
log.Fatalf("-dbstring=%q: %v\n", dbstring, err)
|
||||
}
|
||||
|
|
23
db.go
23
db.go
|
@ -3,8 +3,6 @@ package goose
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
// OpenDBWithDriver creates a connection a database, and modifies goose
|
||||
|
@ -22,28 +20,9 @@ func OpenDBWithDriver(driver string, dbstring string) (*sql.DB, error) {
|
|||
}
|
||||
|
||||
switch driver {
|
||||
case "postgres", "sqlite3":
|
||||
case "postgres", "sqlite3", "mysql":
|
||||
return sql.Open(driver, dbstring)
|
||||
case "mysql":
|
||||
dsn, err := normalizeMySQLDSN(dbstring)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sql.Open(driver, dsn)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported driver %s", driver)
|
||||
}
|
||||
}
|
||||
|
||||
// normalizeMySQLDSN parses the dsn used with the mysql driver to always have
|
||||
// the parameter `parseTime` set to true. This allows internal goose logic
|
||||
// to assume that DATETIME/DATE/TIMESTAMP can be scanned into the time.Time
|
||||
// type.
|
||||
func normalizeMySQLDSN(dsn string) (string, error) {
|
||||
config, err := mysql.ParseDSN(dsn)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
config.ParseTime = true
|
||||
return config.FormatDSN(), nil
|
||||
}
|
||||
|
|
54
db_test.go
54
db_test.go
|
@ -1,54 +0,0 @@
|
|||
package goose
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNormalizeMySQLDSN(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
in string
|
||||
out string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
desc: "errors if dsn is invalid",
|
||||
in: "root:password@tcp(mysql:3306)", // forgot the database name
|
||||
expectedErr: "invalid DSN: missing the slash separating the database name",
|
||||
},
|
||||
{
|
||||
desc: "works when there are no query parameters supplied with the dsn",
|
||||
in: "root:password@tcp(mysql:3306)/db",
|
||||
out: "root:password@tcp(mysql:3306)/db?parseTime=true",
|
||||
},
|
||||
{
|
||||
desc: "works when parseTime is already set to true supplied with the dsn",
|
||||
in: "root:password@tcp(mysql:3306)/db?parseTime=true",
|
||||
out: "root:password@tcp(mysql:3306)/db?parseTime=true",
|
||||
},
|
||||
{
|
||||
desc: "persists other parameters if they are present",
|
||||
in: "root:password@tcp(mysql:3306)/db?allowCleartextPasswords=true&interpolateParams=true",
|
||||
out: "root:password@tcp(mysql:3306)/db?allowCleartextPasswords=true&interpolateParams=true&parseTime=true",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
out, err := normalizeMySQLDSN(tc.in)
|
||||
if tc.expectedErr != "" {
|
||||
if err == nil {
|
||||
t.Errorf("expected an error, but did not have one, had (%#v, %#v)", out, err)
|
||||
} else if err.Error() != tc.expectedErr {
|
||||
t.Errorf("expected error %s but had %s", tc.expectedErr, err.Error())
|
||||
}
|
||||
} else if err != nil {
|
||||
t.Errorf("had unexpected error %s", err.Error())
|
||||
} else if out != tc.out {
|
||||
t.Errorf("had output mismatch, wanted %s but had %s", tc.out, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
// This is custom goose binary with sqlite3 support only.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -7,11 +9,7 @@ import (
|
|||
|
||||
"github.com/pressly/goose"
|
||||
|
||||
// Init DB drivers.
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
_ "github.com/ziutek/mymysql/godrv"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -20,49 +18,19 @@ var (
|
|||
)
|
||||
|
||||
func main() {
|
||||
flags.Usage = usage
|
||||
flags.Parse(os.Args[1:])
|
||||
|
||||
args := flags.Args()
|
||||
if len(args) == 0 || args[0] == "-h" || args[0] == "--help" {
|
||||
|
||||
if len(args) < 2 {
|
||||
flags.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
switch args[0] {
|
||||
case "create":
|
||||
if err := goose.Run("create", nil, *dir, args[1:]...); err != nil {
|
||||
log.Fatalf("goose run: %v", err)
|
||||
}
|
||||
return
|
||||
case "fix":
|
||||
if err := goose.Run("fix", nil, *dir); err != nil {
|
||||
log.Fatalf("goose run: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
dbstring, command := args[1], args[2]
|
||||
|
||||
if len(args) < 3 {
|
||||
flags.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
if args[0] == "-h" || args[0] == "--help" {
|
||||
flags.Usage()
|
||||
return
|
||||
}
|
||||
|
||||
driver, dbstring, command := args[0], args[1], args[2]
|
||||
|
||||
switch dbstring {
|
||||
case "":
|
||||
log.Fatalf("-dbstring=%q not supported\n", dbstring)
|
||||
default:
|
||||
}
|
||||
|
||||
db, err := goose.OpenDBWithDriver(driver, dbstring)
|
||||
db, err := goose.OpenDBWithDriver("sqlite3", dbstring)
|
||||
if err != nil {
|
||||
log.Fatalf("goose run: %v\n", err)
|
||||
log.Fatalf("goose: failed to open DB: %v\n", err)
|
||||
}
|
||||
|
||||
arguments := []string{}
|
||||
|
@ -71,49 +39,6 @@ func main() {
|
|||
}
|
||||
|
||||
if err := goose.Run(command, db, *dir, arguments...); err != nil {
|
||||
log.Fatalf("goose run: %v", err)
|
||||
log.Fatalf("goose %v: %v", command, err)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
log.Print(usagePrefix)
|
||||
flags.PrintDefaults()
|
||||
log.Print(usageCommands)
|
||||
}
|
||||
|
||||
var (
|
||||
usagePrefix = `Usage: goose [OPTIONS] DRIVER DBSTRING COMMAND
|
||||
|
||||
Drivers:
|
||||
postgres
|
||||
mysql
|
||||
sqlite3
|
||||
redshift
|
||||
|
||||
Examples:
|
||||
goose sqlite3 ./foo.db status
|
||||
goose sqlite3 ./foo.db create init sql
|
||||
goose sqlite3 ./foo.db create add_some_column sql
|
||||
goose sqlite3 ./foo.db create fetch_user_data go
|
||||
goose sqlite3 ./foo.db up
|
||||
|
||||
goose postgres "user=postgres dbname=postgres sslmode=disable" status
|
||||
goose mysql "user:password@/dbname?parseTime=true" status
|
||||
goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" status
|
||||
|
||||
Options:
|
||||
`
|
||||
|
||||
usageCommands = `
|
||||
Commands:
|
||||
up Migrate the DB to the most recent version available
|
||||
up-to VERSION Migrate the DB to a specific VERSION
|
||||
down Roll back the version by 1
|
||||
down-to VERSION Roll back to a specific VERSION
|
||||
redo Re-run the latest migration
|
||||
status Dump the migration status for the current DB
|
||||
version Print the current version of the database
|
||||
create NAME [sql|go] Creates new migration file with the current timestamp
|
||||
fix Apply sequential ordering to migrations
|
||||
`
|
||||
)
|
||||
|
|
|
@ -47,20 +47,20 @@ func TestLiteBinary(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer os.RemoveAll(dir) // clean up
|
||||
defer os.Remove("./bin/light-goose") // clean up
|
||||
defer os.RemoveAll(dir) // clean up
|
||||
defer os.Remove("./bin/lite-goose") // clean up
|
||||
|
||||
// this has to be done outside of the loop
|
||||
// since go only supports space separated tags list.
|
||||
cmd := exec.Command("go", "build", "-tags='no_mysql no_sqlite no_psql'", "-o", "./bin/light-goose", "./cmd/goose")
|
||||
cmd := exec.Command("go", "build", "-tags='no_postgres no_mysql no_sqlite3'", "-o", "./bin/lite-goose", "./cmd/goose")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%s:\n%v\n\n%s", err, cmd, out)
|
||||
}
|
||||
|
||||
commands := []string{
|
||||
fmt.Sprintf("./bin/light-goose -dir=%s create user_indices sql", dir),
|
||||
fmt.Sprintf("./bin/light-goose -dir=%s fix", dir),
|
||||
fmt.Sprintf("./bin/lite-goose -dir=%s create user_indices sql", dir),
|
||||
fmt.Sprintf("./bin/lite-goose -dir=%s fix", dir),
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
|
|
Loading…
Reference in New Issue