From 0741616d2ea92fb372f8d5469d9256f3c856ffc1 Mon Sep 17 00:00:00 2001 From: Dave Jeffrey Date: Thu, 11 Jun 2015 11:11:28 +0100 Subject: [PATCH 01/12] Don't load in all drivers by default #40 Requires activating drivers with a _ style import, e.g. import "_ github.com/mattes/migrate/driver/postgres" --- README.md | 3 +++ driver/bash/bash.go | 5 ++++ driver/cassandra/cassandra.go | 5 ++++ driver/driver.go | 50 ++++++++--------------------------- driver/mysql/mysql.go | 5 ++++ driver/postgres/postgres.go | 5 ++++ driver/registry/registry.go | 20 ++++++++++++++ driver/sqlite3/sqlite3.go | 5 ++++ migrate/migrate_test.go | 2 ++ 9 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 driver/registry/registry.go diff --git a/README.md b/README.md index ae09afc7..32873cba 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ See GoDoc here: http://godoc.org/github.com/mattes/migrate/migrate ```go import "github.com/mattes/migrate/migrate" +// Import any required drivers so that they are registered and available +import _ "github.com/mattes/migrate/drivers/mysql" + // use synchronous versions of migration functions ... allErrors, ok := migrate.UpSync("driver://url", "./path") if !ok { diff --git a/driver/bash/bash.go b/driver/bash/bash.go index 156371e3..ed5ffa00 100644 --- a/driver/bash/bash.go +++ b/driver/bash/bash.go @@ -2,6 +2,7 @@ package bash import ( + "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" _ "github.com/mattes/migrate/migrate/direction" ) @@ -30,3 +31,7 @@ func (driver *Driver) Migrate(f file.File, pipe chan interface{}) { func (driver *Driver) Version() (uint64, error) { return uint64(0), nil } + +func init() { + registry.RegisterDriver("bash", Driver{}) +} diff --git a/driver/cassandra/cassandra.go b/driver/cassandra/cassandra.go index 8d72f43e..bb4c75c1 100644 --- a/driver/cassandra/cassandra.go +++ b/driver/cassandra/cassandra.go @@ -4,6 +4,7 @@ package cassandra import ( "fmt" "github.com/gocql/gocql" + "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" "net/url" @@ -153,3 +154,7 @@ func (driver *Driver) Version() (uint64, error) { err := driver.session.Query("SELECT version FROM "+tableName+" WHERE versionRow = ?", versionRow).Scan(&version) return uint64(version) - 1, err } + +func init() { + registry.RegisterDriver("cassandra", Driver{}) +} diff --git a/driver/driver.go b/driver/driver.go index 9c00074b..69f6fe6e 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -5,12 +5,9 @@ import ( "errors" "fmt" neturl "net/url" // alias to allow `url string` func signature in New + "reflect" - "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" + "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" ) @@ -47,51 +44,26 @@ func New(url string) (Driver, error) { return nil, err } - switch u.Scheme { - case "postgres": - d := &postgres.Driver{} - verifyFilenameExtension("postgres", d) - if err := d.Initialize(url); err != nil { - return nil, err - } - return d, nil - - case "mysql": - d := &mysql.Driver{} - verifyFilenameExtension("mysql", d) - if err := d.Initialize(url); err != nil { + driver := registry.GetDriver(u.Scheme) + if driver != nil { + blankDriver := reflect.New(reflect.TypeOf(driver)).Interface() + d, ok := blankDriver.(Driver) + if !ok { + err := errors.New(fmt.Sprintf("Driver '%s' does not implement the Driver interface")) return nil, err } - return d, nil - - case "bash": - d := &bash.Driver{} - verifyFilenameExtension("bash", d) + verifyFilenameExtension(u.Scheme, d) if err := d.Initialize(url); err != nil { return nil, err } - return d, nil - case "cassandra": - d := &cassandra.Driver{} - verifyFilenameExtension("cassanda", d) - if err := d.Initialize(url); err != nil { - return nil, err - } - return d, nil - case "sqlite3": - d := &sqlite3.Driver{} - verifyFilenameExtension("sqlite3", d) - if err := d.Initialize(url); err != nil { - return nil, err - } return d, nil - default: + } else { return nil, errors.New(fmt.Sprintf("Driver '%s' not found.", u.Scheme)) } } -// verifyFilenameExtension panics if the drivers filename extension +// verifyFilenameExtension panics if the driver's filename extension // is not correct or empty. func verifyFilenameExtension(driverName string, d Driver) { f := d.FilenameExtension() diff --git a/driver/mysql/mysql.go b/driver/mysql/mysql.go index ef026ee8..2a3fec64 100644 --- a/driver/mysql/mysql.go +++ b/driver/mysql/mysql.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "github.com/go-sql-driver/mysql" + "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" "regexp" @@ -177,3 +178,7 @@ func (driver *Driver) Version() (uint64, error) { return version, nil } } + +func init() { + registry.RegisterDriver("mysql", Driver{}) +} diff --git a/driver/postgres/postgres.go b/driver/postgres/postgres.go index bacd2ee6..af386950 100644 --- a/driver/postgres/postgres.go +++ b/driver/postgres/postgres.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "github.com/lib/pq" + "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" "strconv" @@ -119,3 +120,7 @@ func (driver *Driver) Version() (uint64, error) { return version, nil } } + +func init() { + registry.RegisterDriver("postgres", Driver{}) +} diff --git a/driver/registry/registry.go b/driver/registry/registry.go new file mode 100644 index 00000000..cbb3bb95 --- /dev/null +++ b/driver/registry/registry.go @@ -0,0 +1,20 @@ +// Package registry maintains a map of imported and available drivers +package registry + +var driverRegistry map[string]interface{} + +// Registers a driver so it can be created from its name. Drivers should +// call this from an init() function so that they registers themselvse on +// import +func RegisterDriver(name string, driver interface{}) { + driverRegistry[name] = driver +} + +// Retrieves a registered driver by name +func GetDriver(name string) interface{} { + return driverRegistry[name] +} + +func init() { + driverRegistry = make(map[string]interface{}) +} diff --git a/driver/sqlite3/sqlite3.go b/driver/sqlite3/sqlite3.go index a33b7e5c..c009b7b1 100644 --- a/driver/sqlite3/sqlite3.go +++ b/driver/sqlite3/sqlite3.go @@ -5,6 +5,7 @@ import ( "database/sql" "errors" "fmt" + "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" "github.com/mattn/go-sqlite3" @@ -123,3 +124,7 @@ func (driver *Driver) Version() (uint64, error) { return version, nil } } + +func init() { + registry.RegisterDriver("sqlite3", Driver{}) +} diff --git a/migrate/migrate_test.go b/migrate/migrate_test.go index e2e0793c..4fe1140d 100644 --- a/migrate/migrate_test.go +++ b/migrate/migrate_test.go @@ -3,6 +3,8 @@ package migrate import ( "io/ioutil" "testing" + // Ensure imports for each driver we wish to test + _ "github.com/mattes/migrate/driver/postgres" ) // Add Driver URLs here to test basic Up, Down, .. functions. From 29574449918c41b9588b9d65c929d980ed76f414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 12:49:43 -0400 Subject: [PATCH 02/12] Fix test with optionated drivers --- .travis.yml | 17 +++++++---------- Dockerfile | 3 +++ Makefile | 24 ++++++++++++++++++++++++ docker-compose.yml | 27 +++++++++++++++++++++++++++ driver/cassandra/cassandra_test.go | 14 +++++++++----- driver/driver.go | 7 +++++-- driver/driver_test.go | 2 ++ driver/mysql/mysql_test.go | 10 +++++++--- driver/postgres/postgres.go | 3 ++- driver/postgres/postgres_test.go | 8 ++++++-- driver/sqlite3/sqlite3_test.go | 3 ++- migrate/migrate_test.go | 5 +++-- 12 files changed, 97 insertions(+), 26 deletions(-) create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 docker-compose.yml diff --git a/.travis.yml b/.travis.yml index 1fd0bd80..d639c535 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: go +sudo :required go: - 1.3 @@ -6,16 +7,12 @@ go: - 1.5 - tip -addons: - postgresql: "9.3" - services: - - cassandra + - docker -before_script: - - > - /usr/local/cassandra/bin/cqlsh -e "CREATE KEYSPACE migratetest WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor' : 1};" - - psql -c 'create database migratetest;' -U postgres - - mysql -e 'create database migratetest;' +before_install: + - curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > docker-compose + - chmod +x docker-compose + - sudo mv docker-compose /usr/local/bin -script: go test -p 1 ./... +script: make test diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..40e09363 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM scratch +ADD migrate /migrate +ENTRYPOINT ["/migrate"] diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..b95eb949 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +IMAGE=mattes/migrate +DCR=docker-compose run --rm +.PHONY: clean test build release docker-build docker-push run + +all: release + +clean: + rm -f migrate + +test: + go get -t -v + $(DCR) go-test + +build: + go get -v -t + $(DCR) go-build + +release: test build docker-build docker-push + +docker-build: + docker build --rm -t $(IMAGE) . + +docker-push: + docker push $(IMAGE) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..6249950f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +go: &go + image: golang + working_dir: /go/src/github.com/mattes/migrate + volumes: + - $GOPATH:/go + - ./migrations:/migrations +go-test: + <<: *go + command: go test -v -cover ./... + links: + - postgres + - mysql + - cassandra +go-build: + <<: *go + command: go build -ldflags '-s' + environment: + CGO_ENABLED: 0 +postgres: + image: postgres +mysql: + image: mysql + environment: + MYSQL_DATABASE: migratetest + MYSQL_ALLOW_EMPTY_PASSWORD: yes +cassandra: + image: cassandra diff --git a/driver/cassandra/cassandra_test.go b/driver/cassandra/cassandra_test.go index bec0aabf..ea737945 100644 --- a/driver/cassandra/cassandra_test.go +++ b/driver/cassandra/cassandra_test.go @@ -2,6 +2,7 @@ package cassandra import ( "net/url" + "os" "testing" "time" @@ -13,7 +14,10 @@ import ( func TestMigrate(t *testing.T) { var session *gocql.Session - driverUrl := "cassandra://localhost/migratetest" + + host := os.Getenv("CASSANDRA_PORT_9042_TCP_ADDR") + port := os.Getenv("CASSANDRA_PORT_9042_TCP_PORT") + driverUrl := "cassandra://" + host + ":" + port + "/system" // prepare a clean test database u, err := url.Parse(driverUrl) @@ -32,12 +36,12 @@ func TestMigrate(t *testing.T) { t.Fatal(err) } - if err := session.Query(`DROP TABLE IF EXISTS yolo`).Exec(); err != nil { - t.Fatal(err) - } - if err := session.Query(`DROP TABLE IF EXISTS ` + tableName).Exec(); err != nil { + if err := session.Query(`CREATE KEYSPACE IF NOT EXISTS migrate WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1};`).Exec(); err != nil { t.Fatal(err) } + cluster.Keyspace = "migrate" + session, err = cluster.CreateSession() + driverUrl = "cassandra://" + host + ":" + port + "/migrate" d := &Driver{} if err := d.Initialize(driverUrl); err != nil { diff --git a/driver/driver.go b/driver/driver.go index d123e2ef..99a4428f 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -52,9 +52,12 @@ func New(url string) (Driver, error) { err := errors.New(fmt.Sprintf("Driver '%s' does not implement the Driver interface")) return nil, err } + verifyFilenameExtension(u.Scheme, d) + if err := d.Initialize(url); err != nil { + return nil, err + } + return d, nil - } else { - return nil, errors.New(fmt.Sprintf("Driver '%s' not found.", u.Scheme)) } return nil, fmt.Errorf("Driver '%s' not found.", u.Scheme) } diff --git a/driver/driver_test.go b/driver/driver_test.go index c400af5f..dce58957 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -1,6 +1,8 @@ package driver import "testing" +import _ "github.com/mattes/migrate/driver/bash" +import _ "github.com/mattes/migrate/driver/sqlite3" func TestNew(t *testing.T) { if _, err := New("unknown://url"); err == nil { diff --git a/driver/mysql/mysql_test.go b/driver/mysql/mysql_test.go index 2393b7b2..51cf552a 100644 --- a/driver/mysql/mysql_test.go +++ b/driver/mysql/mysql_test.go @@ -2,17 +2,21 @@ package mysql import ( "database/sql" + "os" + "strings" + "testing" + "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" pipep "github.com/mattes/migrate/pipe" - "strings" - "testing" ) // TestMigrate runs some additional tests on Migrate(). // Basic testing is already done in migrate/migrate_test.go func TestMigrate(t *testing.T) { - driverUrl := "mysql://root@tcp(127.0.0.1:3306)/migratetest" + host := os.Getenv("MYSQL_PORT_3306_TCP_ADDR") + port := os.Getenv("MYSQL_PORT_3306_TCP_PORT") + driverUrl := "mysql://root@tcp(" + host + ":" + port + ")/migratetest" // prepare clean database connection, err := sql.Open("mysql", strings.SplitN(driverUrl, "mysql://", 2)[1]) diff --git a/driver/postgres/postgres.go b/driver/postgres/postgres.go index af386950..afcb22f6 100644 --- a/driver/postgres/postgres.go +++ b/driver/postgres/postgres.go @@ -5,11 +5,12 @@ import ( "database/sql" "errors" "fmt" + "strconv" + "github.com/lib/pq" "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" - "strconv" ) type Driver struct { diff --git a/driver/postgres/postgres_test.go b/driver/postgres/postgres_test.go index 750f81f6..ec91b350 100644 --- a/driver/postgres/postgres_test.go +++ b/driver/postgres/postgres_test.go @@ -2,16 +2,20 @@ package postgres import ( "database/sql" + "os" + "testing" + "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" pipep "github.com/mattes/migrate/pipe" - "testing" ) // TestMigrate runs some additional tests on Migrate(). // Basic testing is already done in migrate/migrate_test.go func TestMigrate(t *testing.T) { - driverUrl := "postgres://localhost/migratetest?sslmode=disable" + host := os.Getenv("POSTGRES_PORT_5432_TCP_ADDR") + port := os.Getenv("POSTGRES_PORT_5432_TCP_PORT") + driverUrl := "postgres://postgres@" + host + ":" + port + "/template1?sslmode=disable" // prepare clean database connection, err := sql.Open("postgres", driverUrl) diff --git a/driver/sqlite3/sqlite3_test.go b/driver/sqlite3/sqlite3_test.go index 270a25d3..8d51a7de 100644 --- a/driver/sqlite3/sqlite3_test.go +++ b/driver/sqlite3/sqlite3_test.go @@ -2,10 +2,11 @@ package sqlite3 import ( "database/sql" + "testing" + "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" pipep "github.com/mattes/migrate/pipe" - "testing" ) // TestMigrate runs some additional tests on Migrate() diff --git a/migrate/migrate_test.go b/migrate/migrate_test.go index 4fe1140d..c4947de6 100644 --- a/migrate/migrate_test.go +++ b/migrate/migrate_test.go @@ -2,6 +2,7 @@ package migrate import ( "io/ioutil" + "os" "testing" // Ensure imports for each driver we wish to test _ "github.com/mattes/migrate/driver/postgres" @@ -9,7 +10,7 @@ import ( // Add Driver URLs here to test basic Up, Down, .. functions. var driverUrls = []string{ - "postgres://localhost/migratetest?sslmode=disable", + "postgres://postgres@" + os.Getenv("POSTGRES_PORT_5432_TCP_ADDR") + ":" + os.Getenv("POSTGRES_PORT_5432_TCP_PORT") + "/template1?sslmode=disable", } func TestCreate(t *testing.T) { @@ -56,7 +57,7 @@ func TestCreate(t *testing.T) { func TestReset(t *testing.T) { for _, driverUrl := range driverUrls { t.Logf("Test driver: %s", driverUrl) - tmpdir, err := ioutil.TempDir("/tmp", "migrate-test") + tmpdir, err := ioutil.TempDir("/", "migrate-test") if err != nil { t.Fatal(err) } From 5cf4286653d3f46ca0f720237f7f7ed335b24cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 12:53:53 -0400 Subject: [PATCH 03/12] fix yaml in travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d639c535..55cb82aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: go -sudo :required +sudo: required go: - 1.3 From ef698d8132f8ad4aa17ec90456b8269dc3e29fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 12:59:31 -0400 Subject: [PATCH 04/12] go get all deps deeply --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b95eb949..fcc70850 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ clean: rm -f migrate test: - go get -t -v + go get -t -v ./... $(DCR) go-test build: From b4e84ac8f92d908991058e9aed20e916218379fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 13:34:52 -0400 Subject: [PATCH 05/12] Use go version defined in the travis.yml matrix --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 55cb82aa..24677ad2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,5 +14,6 @@ before_install: - curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > docker-compose - chmod +x docker-compose - sudo mv docker-compose /usr/local/bin + - sed -i -e 's/golang/golang:'"$TRAVIS_GO_VERSION"'/' docker-compose.yml script: make test From 8ae2c91ef46cb3330b6584f9324338739d4223c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 13:43:48 -0400 Subject: [PATCH 06/12] Fix travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 24677ad2..e1c49de9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ go: - 1.3 - 1.4 - 1.5 - - tip services: - docker @@ -14,6 +13,7 @@ before_install: - curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > docker-compose - chmod +x docker-compose - sudo mv docker-compose /usr/local/bin + - go get golang.org/x/tools/cmd/cover - sed -i -e 's/golang/golang:'"$TRAVIS_GO_VERSION"'/' docker-compose.yml script: make test From a35e2a3c7ade222b3206c18046139356fb4381e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 13:48:04 -0400 Subject: [PATCH 07/12] Don't use -cover for now, it's not working --- .travis.yml | 1 - docker-compose.yml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e1c49de9..0561d79c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,6 @@ before_install: - curl -L https://github.com/docker/compose/releases/download/1.4.2/docker-compose-`uname -s`-`uname -m` > docker-compose - chmod +x docker-compose - sudo mv docker-compose /usr/local/bin - - go get golang.org/x/tools/cmd/cover - sed -i -e 's/golang/golang:'"$TRAVIS_GO_VERSION"'/' docker-compose.yml script: make test diff --git a/docker-compose.yml b/docker-compose.yml index 6249950f..d435dcf0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ go: &go - ./migrations:/migrations go-test: <<: *go - command: go test -v -cover ./... + command: go test -v ./... links: - postgres - mysql From 46c831b8e9d2dab43d248eb1f1ad824045bccc4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 14:18:23 -0400 Subject: [PATCH 08/12] Don't trust travis go --- Makefile | 2 -- docker-compose.yml | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index fcc70850..9cee255b 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,9 @@ clean: rm -f migrate test: - go get -t -v ./... $(DCR) go-test build: - go get -v -t $(DCR) go-build release: test build docker-build docker-push diff --git a/docker-compose.yml b/docker-compose.yml index d435dcf0..9c6ec892 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,14 +6,14 @@ go: &go - ./migrations:/migrations go-test: <<: *go - command: go test -v ./... + command: sh -c 'go get -t -v ./... && go test -v ./...' links: - postgres - mysql - cassandra go-build: <<: *go - command: go build -ldflags '-s' + command: sh -c 'go get -v && go build -ldflags ''-s'' -o migrater' environment: CGO_ENABLED: 0 postgres: From 3bc76ee0bba0baf464b13365f65ba23ef08cff2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 15 Oct 2015 14:18:58 -0400 Subject: [PATCH 09/12] remove leftover [skipci] --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 9c6ec892..507a8560 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,6 @@ go: &go working_dir: /go/src/github.com/mattes/migrate volumes: - $GOPATH:/go - - ./migrations:/migrations go-test: <<: *go command: sh -c 'go get -t -v ./... && go test -v ./...' From 080f49baf4dccb0d694f558afdaf58abf16762a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Sun, 18 Oct 2015 22:30:51 -0400 Subject: [PATCH 10/12] Fix error message --- driver/driver.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/driver/driver.go b/driver/driver.go index 99a4428f..e6e928fc 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -2,7 +2,6 @@ package driver import ( - "errors" "fmt" neturl "net/url" // alias to allow `url string` func signature in New "reflect" @@ -49,8 +48,7 @@ func New(url string) (Driver, error) { blankDriver := reflect.New(reflect.TypeOf(driver)).Interface() d, ok := blankDriver.(Driver) if !ok { - err := errors.New(fmt.Sprintf("Driver '%s' does not implement the Driver interface")) - return nil, err + return nil, fmt.Errorf("Driver '%s' does not implement the Driver interface", u.Scheme) } verifyFilenameExtension(u.Scheme, d) if err := d.Initialize(url); err != nil { From 9754378aa500481d31d05ce5a3bd09446f30533e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 22 Oct 2015 16:29:26 -0400 Subject: [PATCH 11/12] Move the registry to driver package We can't test driver.New methods because of circular imports. That's probably why the initial code had a map[string]interface{} as registry: it removes a dependency import. I prefer the remove the registry and have a registry returning a real Driver. It will ease the development later. --- driver/bash/bash.go | 5 ++-- driver/bash/bash_test.go | 4 +--- driver/cassandra/cassandra.go | 11 +++++---- driver/driver.go | 25 +++++++------------- driver/driver_test.go | 29 ----------------------- driver/mysql/mysql.go | 11 +++++---- driver/postgres/postgres.go | 4 ++-- driver/registry.go | 44 +++++++++++++++++++++++++++++++++++ driver/registry/registry.go | 20 ---------------- driver/sqlite3/sqlite3.go | 7 +++--- migrate/migrate_test.go | 2 ++ 11 files changed, 76 insertions(+), 86 deletions(-) delete mode 100644 driver/driver_test.go create mode 100644 driver/registry.go delete mode 100644 driver/registry/registry.go diff --git a/driver/bash/bash.go b/driver/bash/bash.go index ed5ffa00..031f9bb4 100644 --- a/driver/bash/bash.go +++ b/driver/bash/bash.go @@ -2,9 +2,8 @@ package bash import ( - "github.com/mattes/migrate/driver/registry" + "github.com/mattes/migrate/driver" "github.com/mattes/migrate/file" - _ "github.com/mattes/migrate/migrate/direction" ) type Driver struct { @@ -33,5 +32,5 @@ func (driver *Driver) Version() (uint64, error) { } func init() { - registry.RegisterDriver("bash", Driver{}) + driver.RegisterDriver("bash", &Driver{}) } diff --git a/driver/bash/bash_test.go b/driver/bash/bash_test.go index ccb39bc1..edc76902 100644 --- a/driver/bash/bash_test.go +++ b/driver/bash/bash_test.go @@ -1,8 +1,6 @@ package bash -import ( - "testing" -) +import "testing" func TestMigrate(t *testing.T) { diff --git a/driver/cassandra/cassandra.go b/driver/cassandra/cassandra.go index bb4c75c1..faea2a27 100644 --- a/driver/cassandra/cassandra.go +++ b/driver/cassandra/cassandra.go @@ -3,13 +3,14 @@ package cassandra import ( "fmt" - "github.com/gocql/gocql" - "github.com/mattes/migrate/driver/registry" - "github.com/mattes/migrate/file" - "github.com/mattes/migrate/migrate/direction" "net/url" "strings" "time" + + "github.com/gocql/gocql" + "github.com/mattes/migrate/driver" + "github.com/mattes/migrate/file" + "github.com/mattes/migrate/migrate/direction" ) type Driver struct { @@ -156,5 +157,5 @@ func (driver *Driver) Version() (uint64, error) { } func init() { - registry.RegisterDriver("cassandra", Driver{}) + driver.RegisterDriver("cassandra", &Driver{}) } diff --git a/driver/driver.go b/driver/driver.go index e6e928fc..e4ecb783 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -4,9 +4,7 @@ package driver import ( "fmt" neturl "net/url" // alias to allow `url string` func signature in New - "reflect" - "github.com/mattes/migrate/driver/registry" "github.com/mattes/migrate/file" ) @@ -43,21 +41,16 @@ func New(url string) (Driver, error) { return nil, err } - driver := registry.GetDriver(u.Scheme) - if driver != nil { - blankDriver := reflect.New(reflect.TypeOf(driver)).Interface() - d, ok := blankDriver.(Driver) - if !ok { - return nil, fmt.Errorf("Driver '%s' does not implement the Driver interface", u.Scheme) - } - verifyFilenameExtension(u.Scheme, d) - if err := d.Initialize(url); err != nil { - return nil, err - } - - return d, nil + d := GetDriver(u.Scheme) + if d == nil { + return nil, fmt.Errorf("Driver '%s' not found.", u.Scheme) + } + verifyFilenameExtension(u.Scheme, d) + if err := d.Initialize(url); err != nil { + return nil, err } - return nil, fmt.Errorf("Driver '%s' not found.", u.Scheme) + + return d, nil } // verifyFilenameExtension panics if the driver's filename extension diff --git a/driver/driver_test.go b/driver/driver_test.go deleted file mode 100644 index dce58957..00000000 --- a/driver/driver_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package driver - -import "testing" -import _ "github.com/mattes/migrate/driver/bash" -import _ "github.com/mattes/migrate/driver/sqlite3" - -func TestNew(t *testing.T) { - if _, err := New("unknown://url"); err == nil { - t.Error("no error although driver unknown") - } -} - -func TestNewBash(t *testing.T) { - driver, err := New("bash://url") - if err != nil { - t.Error("error although bash driver known") - } - version, err := driver.Version() - if version != 0 { - t.Errorf("expected bash driver version to be 0, got %d\n", version) - } -} - -func TestNewSqlite3(t *testing.T) { - _, err := New("sqlite3://test.db") - if err != nil { - t.Error("error although sqlite3 driver known") - } -} diff --git a/driver/mysql/mysql.go b/driver/mysql/mysql.go index 2a3fec64..2bbbc131 100644 --- a/driver/mysql/mysql.go +++ b/driver/mysql/mysql.go @@ -7,13 +7,14 @@ import ( "database/sql" "errors" "fmt" - "github.com/go-sql-driver/mysql" - "github.com/mattes/migrate/driver/registry" - "github.com/mattes/migrate/file" - "github.com/mattes/migrate/migrate/direction" "regexp" "strconv" "strings" + + "github.com/go-sql-driver/mysql" + "github.com/mattes/migrate/driver" + "github.com/mattes/migrate/file" + "github.com/mattes/migrate/migrate/direction" ) type Driver struct { @@ -180,5 +181,5 @@ func (driver *Driver) Version() (uint64, error) { } func init() { - registry.RegisterDriver("mysql", Driver{}) + driver.RegisterDriver("mysql", &Driver{}) } diff --git a/driver/postgres/postgres.go b/driver/postgres/postgres.go index afcb22f6..502c7d1a 100644 --- a/driver/postgres/postgres.go +++ b/driver/postgres/postgres.go @@ -8,7 +8,7 @@ import ( "strconv" "github.com/lib/pq" - "github.com/mattes/migrate/driver/registry" + "github.com/mattes/migrate/driver" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" ) @@ -123,5 +123,5 @@ func (driver *Driver) Version() (uint64, error) { } func init() { - registry.RegisterDriver("postgres", Driver{}) + driver.RegisterDriver("postgres", &Driver{}) } diff --git a/driver/registry.go b/driver/registry.go new file mode 100644 index 00000000..86a3955b --- /dev/null +++ b/driver/registry.go @@ -0,0 +1,44 @@ +package driver + +import ( + "sort" + "sync" +) + +var driversMu sync.Mutex +var drivers = make(map[string]Driver) + +// Registers a driver so it can be created from its name. Drivers should +// call this from an init() function so that they registers themselvse on +// import +func RegisterDriver(name string, driver Driver) { + driversMu.Lock() + defer driversMu.Unlock() + if driver == nil { + panic("driver: Register driver is nil") + } + if _, dup := drivers[name]; dup { + panic("sql: Register called twice for driver " + name) + } + drivers[name] = driver +} + +// Retrieves a registered driver by name +func GetDriver(name string) Driver { + driversMu.Lock() + defer driversMu.Unlock() + driver := drivers[name] + return driver +} + +// Drivers returns a sorted list of the names of the registered drivers. +func Drivers() []string { + driversMu.Lock() + defer driversMu.Unlock() + var list []string + for name := range drivers { + list = append(list, name) + } + sort.Strings(list) + return list +} diff --git a/driver/registry/registry.go b/driver/registry/registry.go deleted file mode 100644 index cbb3bb95..00000000 --- a/driver/registry/registry.go +++ /dev/null @@ -1,20 +0,0 @@ -// Package registry maintains a map of imported and available drivers -package registry - -var driverRegistry map[string]interface{} - -// Registers a driver so it can be created from its name. Drivers should -// call this from an init() function so that they registers themselvse on -// import -func RegisterDriver(name string, driver interface{}) { - driverRegistry[name] = driver -} - -// Retrieves a registered driver by name -func GetDriver(name string) interface{} { - return driverRegistry[name] -} - -func init() { - driverRegistry = make(map[string]interface{}) -} diff --git a/driver/sqlite3/sqlite3.go b/driver/sqlite3/sqlite3.go index c009b7b1..a92b14d8 100644 --- a/driver/sqlite3/sqlite3.go +++ b/driver/sqlite3/sqlite3.go @@ -5,11 +5,12 @@ import ( "database/sql" "errors" "fmt" - "github.com/mattes/migrate/driver/registry" + "strings" + + "github.com/mattes/migrate/driver" "github.com/mattes/migrate/file" "github.com/mattes/migrate/migrate/direction" "github.com/mattn/go-sqlite3" - "strings" ) type Driver struct { @@ -126,5 +127,5 @@ func (driver *Driver) Version() (uint64, error) { } func init() { - registry.RegisterDriver("sqlite3", Driver{}) + driver.RegisterDriver("sqlite3", &Driver{}) } diff --git a/migrate/migrate_test.go b/migrate/migrate_test.go index c4947de6..7d2a622f 100644 --- a/migrate/migrate_test.go +++ b/migrate/migrate_test.go @@ -5,7 +5,9 @@ import ( "os" "testing" // Ensure imports for each driver we wish to test + _ "github.com/mattes/migrate/driver/postgres" + _ "github.com/mattes/migrate/driver/sqlite3" ) // Add Driver URLs here to test basic Up, Down, .. functions. From 65674ac4ccff309944f95d9a18605e7ac764af52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Lafoucrie=CC=80re?= Date: Thu, 22 Oct 2015 19:29:14 -0400 Subject: [PATCH 12/12] Dropping support for go 1.3 --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0561d79c..512b33a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: go sudo: required go: - - 1.3 - 1.4 - 1.5