Repository: ariga/atlas
Pull request #1442 (2023-02-03 16:58:10)

sql/migrate: allow overriding migrate.Validate


Patch:
diff --git a/cmd/atlas/internal/cmdapi/cmdapi.go b/cmd/atlas/internal/cmdapi/cmdapi.go
index a88f5d42..ecec0237 100644
--- a/cmd/atlas/internal/cmdapi/cmdapi.go
+++ b/cmd/atlas/internal/cmdapi/cmdapi.go
@@ -541,7 +541,7 @@ func sqlStateReader(ctx context.Context, config *stateReaderConfig, urls []*url.
 		if err != nil {
 			return nil, err
 		}
-		dir = &migrate.MemDir{}
+		dir = &validMemDir{}
 		if err := dir.WriteFile(fi.Name(), b); err != nil {
 			return nil, err
 		}
@@ -583,6 +583,11 @@ func (sr *stateReadCloser) Close() {
 	}
 }
 
+// validMemDir will not throw an error when put into migrate.Validate.
+type validMemDir struct{ migrate.MemDir }
+
+func (d *validMemDir) Validate() error { return nil }
+
 const (
 	extHCL = ".hcl"
 	extSQL = ".sql"
diff --git a/sql/migrate/dir.go b/sql/migrate/dir.go
index cb1d290e..ce3f655a 100644
--- a/sql/migrate/dir.go
+++ b/sql/migrate/dir.go
@@ -217,24 +217,12 @@ type MemDir struct {
 
 // Open implements fs.FS.
 func (d *MemDir) Open(name string) (fs.File, error) {
-	var b []byte
 	f, ok := d.files[name]
-	switch {
-	case !ok && name == HashFileName:
-		h, err := d.Checksum()
-		if err != nil {
-			return nil, err
-		}
-		if b, err = h.MarshalText(); err != nil {
-			return nil, err
-		}
-	case !ok:
+	if !ok {
 		return nil, fs.ErrNotExist
-	default:
-		b = f.Bytes()
 	}
 	return &memFile{
-		ReadCloser: io.NopCloser(bytes.NewReader(b)),
+		ReadCloser: io.NopCloser(bytes.NewReader(f.Bytes())),
 	}, nil
 }
 
@@ -426,6 +414,11 @@ var (
 // Validate checks if the migration dir is in sync with its sum file.
 // If they don't match ErrChecksumMismatch is returned.
 func Validate(dir Dir) error {
+	// If a migration directory implements the Validate() method,
+	// it will be used to determine the validity instead.
+	if v, ok := dir.(interface{ Validate() error }); ok {
+		return v.Validate()
+	}
 	fh, err := readHashFile(dir)
 	if errors.Is(err, fs.ErrNotExist) {
 		// If there are no migration files yet this is okay.


Test patch:
diff --git a/cmd/atlas/internal/cmdapi/schema_test.go b/cmd/atlas/internal/cmdapi/schema_test.go
index 6d3129c8..0c064b45 100644
--- a/cmd/atlas/internal/cmdapi/schema_test.go
+++ b/cmd/atlas/internal/cmdapi/schema_test.go
@@ -412,7 +412,7 @@ func TestSchema_ApplyLog(t *testing.T) {
 	})
 }
 
-func TesSchema_ApplySources(t *testing.T) {
+func TestSchema_ApplySources(t *testing.T) {
 	var (
 		p   = t.TempDir()
 		cfg = filepath.Join(p, "atlas.hcl")
@@ -458,9 +458,9 @@ env "local" {
 	require.Equal(t, []string{
 		"-- Planned Changes:",
 		`-- Create "one" table`,
-		"CREATE TABLE `one` (`id` int NOT NULL)",
+		"CREATE TABLE `one` (`id` int NOT NULL);",
 		`-- Create "two" table`,
-		"CREATE TABLE `two` (`id` int NOT NULL)",
+		"CREATE TABLE `two` (`id` int NOT NULL);",
 	}, lines)
 }
 
diff --git a/sql/migrate/dir_test.go b/sql/migrate/dir_test.go
index dd0fcecc..19654a23 100644
--- a/sql/migrate/dir_test.go
+++ b/sql/migrate/dir_test.go
@@ -215,10 +215,8 @@ func TestMemDir(t *testing.T) {
 	require.NoError(t, err)
 	require.Equal(t, hs1, hs2)
 
-	// If a checksum file is given, it will be used instead of generating the sum on the fly.
-	require.NoError(t, migrate.Validate(&d))
-	require.NoError(t, d.WriteFile(migrate.HashFileName, []byte("")))
-	require.ErrorIs(t, migrate.Validate(&d), migrate.ErrChecksumMismatch)
+	// Will fail without checksum file.
+	require.ErrorIs(t, migrate.Validate(&d), migrate.ErrChecksumNotFound)
 
 	// Will not return the non-sql checksum file.
 	files, err = d.Files()