Skip to content

Commit 5d974f1

Browse files
authored
Minor code updates from missed open comments from #36 to the migratedown feature (#37)
* address comments * address comments + new UTs * address comments * remove build files
1 parent 13318b2 commit 5d974f1

File tree

4 files changed

+106
-46
lines changed

4 files changed

+106
-46
lines changed

cmd/migrate/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ var (
3838

3939
// goto command flags
4040
flagDirty = pflag.Bool("force-dirty-handling", false, "force the handling of dirty database state")
41-
flagMountPath = pflag.String("cache-dir", "", "path to the mounted volume which is used to copy the migration files")
41+
flagMountPath = pflag.String("cache-dir", "", "path to the cache-dir which is used to copy the migration files")
4242
)

internal/cli/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ Database drivers: `+strings.Join(database.List(), ", ")+"\n", createUsage, gotoU
271271
log.fatal("error: cache-dir must be specified when force-dirty-handling is set")
272272
}
273273

274-
if err = migrater.WithDirtyStateHandler(sourcePtr, destPath, handleDirty); err != nil {
274+
if err = migrater.WithDirtyStateConfig(sourcePtr, destPath, handleDirty); err != nil {
275275
log.fatalErr(err)
276276
}
277277
}

migrate.go

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ type Migrate struct {
8888
// but can be set per Migrate instance.
8989
LockTimeout time.Duration
9090

91-
// DirtyStateHandler is used to handle dirty state of the database
92-
dirtyStateConf *dirtyStateHandler
91+
// dirtyStateConfig is used to store the configuration required to handle dirty state of the database
92+
dirtyStateConf *dirtyStateConfig
9393
}
9494

95-
type dirtyStateHandler struct {
95+
type dirtyStateConfig struct {
9696
srcScheme string
9797
srcPath string
9898
destScheme string
@@ -218,33 +218,30 @@ func NewWithInstance(sourceName string, sourceInstance source.Driver, databaseNa
218218
return m, nil
219219
}
220220

221-
func (m *Migrate) WithDirtyStateHandler(srcPath, destPath string, isDirty bool) error {
222-
parser := func(path string) (string, string, error) {
223-
var scheme, p string
221+
func (m *Migrate) WithDirtyStateConfig(srcPath, destPath string, isDirty bool) error {
222+
parsePath := func(path string) (string, string, error) {
224223
uri, err := url.Parse(path)
225224
if err != nil {
226225
return "", "", err
227226
}
228-
scheme = uri.Scheme
229-
p = uri.Path
230-
// if no scheme is provided, assume it's a file path
231-
if scheme == "" {
232-
scheme = "file://"
227+
scheme := "file"
228+
if uri.Scheme != "file" && uri.Scheme != "" {
229+
return "", "", fmt.Errorf("unsupported scheme: %s", scheme)
233230
}
234-
return scheme, p, nil
231+
return scheme + "://", uri.Path, nil
235232
}
236233

237-
sScheme, sPath, err := parser(srcPath)
234+
sScheme, sPath, err := parsePath(srcPath)
238235
if err != nil {
239236
return err
240237
}
241238

242-
dScheme, dPath, err := parser(destPath)
239+
dScheme, dPath, err := parsePath(destPath)
243240
if err != nil {
244241
return err
245242
}
246243

247-
m.dirtyStateConf = &dirtyStateHandler{
244+
m.dirtyStateConf = &dirtyStateConfig{
248245
srcScheme: sScheme,
249246
destScheme: dScheme,
250247
srcPath: sPath,
@@ -839,7 +836,7 @@ func (m *Migrate) runMigrations(ret <-chan interface{}) error {
839836
if migr.Body != nil {
840837
m.logVerbosePrintf("Read and execute %v\n", migr.LogString())
841838
if err := m.databaseDrv.Run(migr.BufferedBody); err != nil {
842-
if m.dirtyStateConf != nil && m.dirtyStateConf.enable {
839+
if m.IsDirtyHandlingEnabled() {
843840
// this condition is required if the first migration fails
844841
if lastCleanMigrationApplied == 0 {
845842
lastCleanMigrationApplied = migr.TargetVersion
@@ -1087,12 +1084,12 @@ func (m *Migrate) logErr(err error) {
10871084
func (m *Migrate) handleDirtyState() error {
10881085
// Perform the following actions when the database state is dirty
10891086
/*
1090-
1. Update the source driver to read the migrations from the mounted volume
1087+
1. Update the source driver to read the migrations from the destination path
10911088
2. Read the last successful migration version from the file
10921089
3. Set the last successful migration version in the schema_migrations table
10931090
4. Delete the last successful migration file
10941091
*/
1095-
// the source driver should read the migrations from the mounted volume
1092+
// the source driver should read the migrations from the destination path
10961093
// as the DB is dirty and last applied migrations to the database are not present in the source path
10971094
if err := m.updateSourceDrv(m.dirtyStateConf.destScheme + m.dirtyStateConf.destPath); err != nil {
10981095
return err

migrate_test.go

Lines changed: 89 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,23 +1418,10 @@ func equalDbSeq(t *testing.T, i int, expected migrationSequence, got *dStub.Stub
14181418
}
14191419
}
14201420

1421-
// Setting up temp directory to be used as the volume mount
1422-
func setupTempDir(t *testing.T) (string, func()) {
1423-
tempDir, err := os.MkdirTemp("", "migrate_test")
1424-
if err != nil {
1425-
t.Fatal(err)
1426-
}
1427-
return tempDir, func() {
1428-
if err = os.RemoveAll(tempDir); err != nil {
1429-
t.Fatal(err)
1430-
}
1431-
}
1432-
}
1433-
14341421
func setupMigrateInstance(tempDir string) (*Migrate, *dStub.Stub) {
14351422
scheme := "stub://"
14361423
m, _ := New(scheme, scheme)
1437-
m.dirtyStateConf = &dirtyStateHandler{
1424+
m.dirtyStateConf = &dirtyStateConfig{
14381425
destScheme: scheme,
14391426
destPath: tempDir,
14401427
enable: true,
@@ -1443,8 +1430,7 @@ func setupMigrateInstance(tempDir string) (*Migrate, *dStub.Stub) {
14431430
}
14441431

14451432
func TestHandleDirtyState(t *testing.T) {
1446-
tempDir, cleanup := setupTempDir(t)
1447-
defer cleanup()
1433+
tempDir := t.TempDir()
14481434

14491435
m, dbDrv := setupMigrateInstance(tempDir)
14501436
m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
@@ -1521,8 +1507,7 @@ func TestHandleDirtyState(t *testing.T) {
15211507
}
15221508

15231509
func TestHandleMigrationFailure(t *testing.T) {
1524-
tempDir, cleanup := setupTempDir(t)
1525-
defer cleanup()
1510+
tempDir := t.TempDir()
15261511

15271512
m, _ := setupMigrateInstance(tempDir)
15281513

@@ -1559,8 +1544,7 @@ func TestHandleMigrationFailure(t *testing.T) {
15591544
}
15601545

15611546
func TestCleanupFiles(t *testing.T) {
1562-
tempDir, cleanup := setupTempDir(t)
1563-
defer cleanup()
1547+
tempDir := t.TempDir()
15641548

15651549
m, _ := setupMigrateInstance(tempDir)
15661550
m.sourceDrv.(*sStub.Stub).Migrations = sourceStubMigrations
@@ -1624,11 +1608,8 @@ func TestCleanupFiles(t *testing.T) {
16241608
}
16251609

16261610
func TestCopyFiles(t *testing.T) {
1627-
srcDir, cleanupSrc := setupTempDir(t)
1628-
defer cleanupSrc()
1629-
1630-
destDir, cleanupDest := setupTempDir(t)
1631-
defer cleanupDest()
1611+
srcDir := t.TempDir()
1612+
destDir := t.TempDir()
16321613

16331614
m, _ := setupMigrateInstance(destDir)
16341615
m.dirtyStateConf.srcPath = srcDir
@@ -1647,7 +1628,7 @@ func TestCopyFiles(t *testing.T) {
16471628
copiedFiles: []string{"1_name.up.sql", "2_name.up.sql", "3_name.up.sql", "4_name.up.sql"},
16481629
},
16491630
{
1650-
emptyDestPath: true,
1631+
emptyDestPath: true, // copyFiles should not do anything
16511632
},
16521633
}
16531634

@@ -1675,6 +1656,88 @@ func TestCopyFiles(t *testing.T) {
16751656
}
16761657
}
16771658

1659+
func TestWithDirtyStateConfig(t *testing.T) {
1660+
tests := []struct {
1661+
name string
1662+
srcPath string
1663+
destPath string
1664+
isDirty bool
1665+
wantErr bool
1666+
wantConf *dirtyStateConfig
1667+
}{
1668+
{
1669+
name: "Valid file paths",
1670+
srcPath: "file:///src/path",
1671+
destPath: "file:///dest/path",
1672+
isDirty: true,
1673+
wantErr: false,
1674+
wantConf: &dirtyStateConfig{
1675+
srcScheme: "file://",
1676+
destScheme: "file://",
1677+
srcPath: "/src/path",
1678+
destPath: "/dest/path",
1679+
enable: true,
1680+
},
1681+
},
1682+
{
1683+
name: "Invalid source scheme",
1684+
srcPath: "s3:///src/path",
1685+
destPath: "file:///dest/path",
1686+
isDirty: true,
1687+
wantErr: true,
1688+
},
1689+
{
1690+
name: "Invalid destination scheme",
1691+
srcPath: "file:///src/path",
1692+
destPath: "s3:///dest/path",
1693+
isDirty: true,
1694+
wantErr: true,
1695+
},
1696+
{
1697+
name: "Empty source scheme",
1698+
srcPath: "/src/path",
1699+
destPath: "file:///dest/path",
1700+
isDirty: true,
1701+
wantErr: false,
1702+
wantConf: &dirtyStateConfig{
1703+
srcScheme: "file://",
1704+
destScheme: "file://",
1705+
srcPath: "/src/path",
1706+
destPath: "/dest/path",
1707+
enable: true,
1708+
},
1709+
},
1710+
{
1711+
name: "Empty destination scheme",
1712+
srcPath: "file:///src/path",
1713+
destPath: "/dest/path",
1714+
isDirty: true,
1715+
wantErr: false,
1716+
wantConf: &dirtyStateConfig{
1717+
srcScheme: "file://",
1718+
destScheme: "file://",
1719+
srcPath: "/src/path",
1720+
destPath: "/dest/path",
1721+
enable: true,
1722+
},
1723+
},
1724+
}
1725+
1726+
for _, tt := range tests {
1727+
t.Run(tt.name, func(t *testing.T) {
1728+
m := &Migrate{}
1729+
err := m.WithDirtyStateConfig(tt.srcPath, tt.destPath, tt.isDirty)
1730+
if (err != nil) != tt.wantErr {
1731+
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
1732+
return
1733+
}
1734+
if !tt.wantErr && m.dirtyStateConf == tt.wantConf {
1735+
t.Errorf("dirtyStateConf = %v, want %v", m.dirtyStateConf, tt.wantConf)
1736+
}
1737+
})
1738+
}
1739+
}
1740+
16781741
/*
16791742
diff returns an array containing the elements in Array A and not in B
16801743
*/

0 commit comments

Comments
 (0)