diff --git a/migrate/migrate.go b/migrate/migrate.go index 636d2f04..eda9c4c4 100644 --- a/migrate/migrate.go +++ b/migrate/migrate.go @@ -3,6 +3,9 @@ package migrate import ( "fmt" "github.com/JackC/pgx" + "io/ioutil" + "path/filepath" + "strings" ) type BadVersionError string @@ -19,6 +22,14 @@ func (e IrreversibleMigrationError) Error() string { return fmt.Sprintf("Irreversible migration: %d - %s", e.m.Sequence, e.m.Name) } +type NoMigrationsFoundError struct { + Path string +} + +func (e NoMigrationsFoundError) Error() string { + return fmt.Sprintf("No migrations found at %s", e.Path) +} + type Migration struct { Sequence int32 Name string @@ -40,6 +51,33 @@ func NewMigrator(conn *pgx.Connection, versionTable string) (m *Migrator, err er return } +func (m *Migrator) LoadMigrations(path string) error { + paths, err := filepath.Glob(filepath.Join(path, "*.sql")) + if err != nil { + return err + } + if len(paths) == 0 { + return NoMigrationsFoundError{Path: path} + } + + for _, p := range paths { + body, err := ioutil.ReadFile(p) + if err != nil { + return err + } + + pieces := strings.SplitN(string(body), "---- create above / drop below ----", 2) + var upSQL, downSQL string + upSQL = strings.TrimSpace(pieces[0]) + if len(pieces) == 2 { + downSQL = strings.TrimSpace(pieces[1]) + } + m.AppendMigration(filepath.Base(p), upSQL, downSQL) + } + + return nil +} + func (m *Migrator) AppendMigration(name, upSQL, downSQL string) { m.Migrations = append(m.Migrations, &Migration{Sequence: int32(len(m.Migrations)) + 1, Name: name, UpSQL: upSQL, DownSQL: downSQL}) return diff --git a/migrate/migrate_test.go b/migrate/migrate_test.go index 222e90aa..f58af3b7 100644 --- a/migrate/migrate_test.go +++ b/migrate/migrate_test.go @@ -102,6 +102,41 @@ func (s *MigrateSuite) TestAppendMigration(c *C) { c.Assert(m.Migrations[0].DownSQL, Equals, downSQL) } +func (s *MigrateSuite) TestLoadMigrationsMissingDirectory(c *C) { + m := s.createEmptyMigrator(c) + err := m.LoadMigrations("testdata/missing") + c.Assert(err, ErrorMatches, "No migrations found at testdata/missing") +} + +func (s *MigrateSuite) TestLoadMigrationsEmptyDirectory(c *C) { + m := s.createEmptyMigrator(c) + err := m.LoadMigrations("testdata/empty") + c.Assert(err, ErrorMatches, "No migrations found at testdata/empty") +} + +func (s *MigrateSuite) TestLoadMigrations(c *C) { + m := s.createEmptyMigrator(c) + err := m.LoadMigrations("testdata/sample") + c.Assert(err, IsNil) + c.Assert(m.Migrations, HasLen, 3) + + c.Check(m.Migrations[0].Name, Equals, "001_create_t1.sql") + c.Check(m.Migrations[0].UpSQL, Equals, `create table t1( + id serial primary key +);`) + c.Check(m.Migrations[0].DownSQL, Equals, "drop table t1;") + + c.Check(m.Migrations[1].Name, Equals, "002_create_t2.sql") + c.Check(m.Migrations[1].UpSQL, Equals, `create table t2( + id serial primary key +);`) + c.Check(m.Migrations[1].DownSQL, Equals, "drop table t2;") + + c.Check(m.Migrations[2].Name, Equals, "003_irreversible.sql") + c.Check(m.Migrations[2].UpSQL, Equals, "drop table t2;") + c.Check(m.Migrations[2].DownSQL, Equals, "") +} + func (s *MigrateSuite) TestMigrate(c *C) { m := s.createSampleMigrator(c) diff --git a/migrate/testdata/002_create_t2.sql b/migrate/testdata/002_create_t2.sql new file mode 100644 index 00000000..352e5149 --- /dev/null +++ b/migrate/testdata/002_create_t2.sql @@ -0,0 +1,7 @@ +create table t2( + id serial primary key +); + +---- create above / drop below ---- + +drop table t2; diff --git a/migrate/testdata/sample/001_create_t1.sql b/migrate/testdata/sample/001_create_t1.sql new file mode 100644 index 00000000..87a05c19 --- /dev/null +++ b/migrate/testdata/sample/001_create_t1.sql @@ -0,0 +1,7 @@ +create table t1( + id serial primary key +); + +---- create above / drop below ---- + +drop table t1; diff --git a/migrate/testdata/sample/002_create_t2.sql b/migrate/testdata/sample/002_create_t2.sql new file mode 100644 index 00000000..352e5149 --- /dev/null +++ b/migrate/testdata/sample/002_create_t2.sql @@ -0,0 +1,7 @@ +create table t2( + id serial primary key +); + +---- create above / drop below ---- + +drop table t2; diff --git a/migrate/testdata/sample/003_irreversible.sql b/migrate/testdata/sample/003_irreversible.sql new file mode 100644 index 00000000..fcb15c77 --- /dev/null +++ b/migrate/testdata/sample/003_irreversible.sql @@ -0,0 +1 @@ +drop table t2;