mirror of https://github.com/status-im/migrate.git
prefix migration files with epoch
Using epoch prefixed filenames, multiple developers can commit migrations while minimizing versioning conflicts. This commit remains backwards compatible with all previous migrations and requires no changes to the `schema_migrations` table. This commit also cleans up migrate-test temp directories
This commit is contained in:
parent
6028882529
commit
9694775972
|
@ -10,6 +10,7 @@ import (
|
|||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mattes/migrate/driver"
|
||||
"github.com/mattes/migrate/file"
|
||||
|
@ -212,20 +213,23 @@ func Create(url, migrationsPath, name string) (*file.MigrationFile, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files, err := file.ReadMigrationFiles(migrationsPath, file.FilenameRegex(d.FilenameExtension()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
version := uint64(0)
|
||||
if len(files) > 0 {
|
||||
lastFile := files[len(files)-1]
|
||||
version = lastFile.Version
|
||||
version := uint64(time.Now().Unix())
|
||||
|
||||
for _, f := range files {
|
||||
if f.Version == version {
|
||||
version++
|
||||
}
|
||||
}
|
||||
version += 1
|
||||
|
||||
versionStr := strconv.FormatUint(version, 10)
|
||||
|
||||
length := 4 // TODO(mattes) check existing files and try to guess length
|
||||
length := 10
|
||||
if len(versionStr)%length != 0 {
|
||||
versionStr = strings.Repeat("0", length-len(versionStr)%length) + versionStr
|
||||
}
|
||||
|
|
|
@ -3,7 +3,9 @@ package migrate
|
|||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
// Ensure imports for each driver we wish to test
|
||||
|
||||
_ "github.com/mattes/migrate/driver/postgres"
|
||||
|
@ -15,6 +17,11 @@ var driverUrls = []string{
|
|||
"postgres://postgres@" + os.Getenv("POSTGRES_PORT_5432_TCP_ADDR") + ":" + os.Getenv("POSTGRES_PORT_5432_TCP_PORT") + "/template1?sslmode=disable",
|
||||
}
|
||||
|
||||
func tearDown(driverUrl, tmpdir string) {
|
||||
DownSync(driverUrl, tmpdir)
|
||||
os.RemoveAll(tmpdir)
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
for _, driverUrl := range driverUrls {
|
||||
t.Logf("Test driver: %s", driverUrl)
|
||||
|
@ -22,6 +29,7 @@ func TestCreate(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown(driverUrl, tmpdir)
|
||||
|
||||
if _, err := Create(driverUrl, tmpdir, "test_migration"); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -35,23 +43,33 @@ func TestCreate(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
if len(files) != 4 {
|
||||
t.Fatal("Expected 2 new files, got", len(files))
|
||||
t.Fatal("Expected 4 new files, got", len(files))
|
||||
}
|
||||
fileNameRegexp := regexp.MustCompile(`^\d{10}_(.*.[up|down].sql)`)
|
||||
|
||||
expectFiles := []string{
|
||||
"0001_test_migration.up.sql", "0001_test_migration.down.sql",
|
||||
"0002_another_migration.up.sql", "0002_another_migration.down.sql",
|
||||
"test_migration.up.sql", "test_migration.down.sql",
|
||||
"another_migration.up.sql", "another_migration.down.sql",
|
||||
}
|
||||
foundCounter := 0
|
||||
for _, expectFile := range expectFiles {
|
||||
for _, file := range files {
|
||||
if expectFile == file.Name() {
|
||||
foundCounter += 1
|
||||
break
|
||||
|
||||
var foundCounter int
|
||||
|
||||
for _, file := range files {
|
||||
if x := fileNameRegexp.FindStringSubmatch(file.Name()); len(x) != 2 {
|
||||
t.Errorf("expected %v to match %v", file.Name(), fileNameRegexp)
|
||||
} else {
|
||||
for _, expect := range expectFiles {
|
||||
if expect == x[1] {
|
||||
foundCounter++
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if foundCounter != len(expectFiles) {
|
||||
t.Error("not all expected files have been found")
|
||||
t.Errorf("expected %v files, got %v", len(expectFiles), foundCounter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,24 +77,26 @@ func TestCreate(t *testing.T) {
|
|||
func TestReset(t *testing.T) {
|
||||
for _, driverUrl := range driverUrls {
|
||||
t.Logf("Test driver: %s", driverUrl)
|
||||
tmpdir, err := ioutil.TempDir("/", "migrate-test")
|
||||
tmpdir, err := ioutil.TempDir("/tmp", "migrate-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown(driverUrl, tmpdir)
|
||||
|
||||
Create(driverUrl, tmpdir, "migration1")
|
||||
Create(driverUrl, tmpdir, "migration2")
|
||||
|
||||
errs, ok := ResetSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err := Version(driverUrl, tmpdir)
|
||||
f, err := Create(driverUrl, tmpdir, "migration2")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 2 {
|
||||
t.Fatalf("Expected version 2, got %v", version)
|
||||
|
||||
if err, ok := ResetSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != f.Version {
|
||||
t.Fatalf("Expected version %v, got %v", version, f.Version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,32 +108,33 @@ func TestDown(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown(driverUrl, tmpdir)
|
||||
|
||||
Create(driverUrl, tmpdir, "migration1")
|
||||
Create(driverUrl, tmpdir, "migration2")
|
||||
initVersion, _ := Version(driverUrl, tmpdir)
|
||||
|
||||
errs, ok := ResetSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err := Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
firstMigration, _ := Create(driverUrl, tmpdir, "migration1")
|
||||
secondMigration, _ := Create(driverUrl, tmpdir, "migration2")
|
||||
|
||||
t.Logf("init %v first %v second %v", initVersion, firstMigration.Version, secondMigration.Version)
|
||||
|
||||
if err, ok := ResetSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 2 {
|
||||
t.Fatalf("Expected version 2, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != secondMigration.Version {
|
||||
t.Fatalf("Expected version %v, got %v", version, secondMigration.Version)
|
||||
}
|
||||
|
||||
errs, ok = DownSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err = Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
if err, ok := DownSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 0 {
|
||||
t.Fatalf("Expected version 0, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != 0 {
|
||||
t.Fatalf("Expected 0, got %v", version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,32 +146,33 @@ func TestUp(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown(driverUrl, tmpdir)
|
||||
|
||||
Create(driverUrl, tmpdir, "migration1")
|
||||
Create(driverUrl, tmpdir, "migration2")
|
||||
initVersion, _ := Version(driverUrl, tmpdir)
|
||||
|
||||
errs, ok := DownSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err := Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
firstMigration, _ := Create(driverUrl, tmpdir, "migration1")
|
||||
secondMigration, _ := Create(driverUrl, tmpdir, "migration2")
|
||||
|
||||
t.Logf("init %v first %v second %v", initVersion, firstMigration.Version, secondMigration.Version)
|
||||
|
||||
if err, ok := DownSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 0 {
|
||||
t.Fatalf("Expected version 0, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != initVersion {
|
||||
t.Fatalf("Expected initial version %v, got %v", initVersion, version)
|
||||
}
|
||||
|
||||
errs, ok = UpSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err = Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
if err, ok := UpSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 2 {
|
||||
t.Fatalf("Expected version 2, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != secondMigration.Version {
|
||||
t.Fatalf("Expected migrated version %v, got %v", secondMigration.Version, version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,32 +184,33 @@ func TestRedo(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown(driverUrl, tmpdir)
|
||||
|
||||
Create(driverUrl, tmpdir, "migration1")
|
||||
Create(driverUrl, tmpdir, "migration2")
|
||||
initVersion, _ := Version(driverUrl, tmpdir)
|
||||
|
||||
errs, ok := ResetSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err := Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
firstMigration, _ := Create(driverUrl, tmpdir, "migration1")
|
||||
secondMigration, _ := Create(driverUrl, tmpdir, "migration2")
|
||||
|
||||
t.Logf("init %v first %v second %v", initVersion, firstMigration.Version, secondMigration.Version)
|
||||
|
||||
if err, ok := ResetSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 2 {
|
||||
t.Fatalf("Expected version 2, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != secondMigration.Version {
|
||||
t.Fatalf("Expected migrated version %v, got %v", secondMigration.Version, version)
|
||||
}
|
||||
|
||||
errs, ok = RedoSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err = Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
if err, ok := RedoSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 2 {
|
||||
t.Fatalf("Expected version 2, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != secondMigration.Version {
|
||||
t.Fatalf("Expected migrated version %v, got %v", secondMigration.Version, version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,44 +222,43 @@ func TestMigrate(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer tearDown(driverUrl, tmpdir)
|
||||
|
||||
Create(driverUrl, tmpdir, "migration1")
|
||||
Create(driverUrl, tmpdir, "migration2")
|
||||
initVersion, _ := Version(driverUrl, tmpdir)
|
||||
|
||||
errs, ok := ResetSync(driverUrl, tmpdir)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err := Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
firstMigration, _ := Create(driverUrl, tmpdir, "migration1")
|
||||
secondMigration, _ := Create(driverUrl, tmpdir, "migration2")
|
||||
|
||||
t.Logf("init %v first %v second %v", initVersion, firstMigration.Version, secondMigration.Version)
|
||||
|
||||
if err, ok := ResetSync(driverUrl, tmpdir); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 2 {
|
||||
t.Fatalf("Expected version 2, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != secondMigration.Version {
|
||||
t.Fatalf("Expected migrated version %v, got %v", secondMigration.Version, version)
|
||||
}
|
||||
|
||||
errs, ok = MigrateSync(driverUrl, tmpdir, -2)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
}
|
||||
version, err = Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
if err, ok := MigrateSync(driverUrl, tmpdir, -2); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 0 {
|
||||
t.Fatalf("Expected version 0, got %v", version)
|
||||
}
|
||||
|
||||
errs, ok = MigrateSync(driverUrl, tmpdir, +1)
|
||||
if !ok {
|
||||
t.Fatal(errs)
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != 0 {
|
||||
t.Fatalf("Expected 0, got %v", version)
|
||||
}
|
||||
version, err = Version(driverUrl, tmpdir)
|
||||
if err != nil {
|
||||
|
||||
if err, ok := MigrateSync(driverUrl, tmpdir, +1); !ok {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if version != 1 {
|
||||
t.Fatalf("Expected version 1, got %v", version)
|
||||
|
||||
if version, err := Version(driverUrl, tmpdir); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if version != firstMigration.Version {
|
||||
t.Fatalf("Expected first version %v, got %v", firstMigration.Version, version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue