github.com/Accefy/pop@v0.0.0-20230428174248-e9f677eab5b9/file_migrator.go (about) 1 package pop 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/gobuffalo/pop/v6/logging" 10 ) 11 12 // FileMigrator is a migrator for SQL and Fizz 13 // files on disk at a specified path. 14 type FileMigrator struct { 15 Migrator 16 Path string 17 } 18 19 // NewFileMigrator for a path and a Connection 20 func NewFileMigrator(path string, c *Connection) (FileMigrator, error) { 21 fm := FileMigrator{ 22 Migrator: NewMigrator(c), 23 Path: path, 24 } 25 fm.SchemaPath = path 26 27 runner := func(mf Migration, tx *Connection) error { 28 f, err := os.Open(mf.Path) 29 if err != nil { 30 return err 31 } 32 defer f.Close() 33 content, err := MigrationContent(mf, tx, f, true) 34 if err != nil { 35 return fmt.Errorf("error processing %s: %w", mf.Path, err) 36 } 37 if content == "" { 38 return nil 39 } 40 err = tx.RawQuery(content).Exec() 41 if err != nil { 42 return fmt.Errorf("error executing %s, sql: %s: %w", mf.Path, content, err) 43 } 44 return nil 45 } 46 47 err := fm.findMigrations(runner) 48 if err != nil { 49 return fm, err 50 } 51 52 return fm, nil 53 } 54 55 func (fm *FileMigrator) findMigrations(runner func(mf Migration, tx *Connection) error) error { 56 dir := fm.Path 57 if fi, err := os.Stat(dir); err != nil || !fi.IsDir() { 58 // directory doesn't exist 59 return nil 60 } 61 return filepath.Walk(dir, func(p string, info os.FileInfo, err error) error { 62 if !info.IsDir() { 63 match, err := ParseMigrationFilename(info.Name()) 64 if err != nil { 65 if strings.HasPrefix(err.Error(), "unsupported dialect") { 66 log(logging.Warn, "ignoring migration file with %s", err.Error()) 67 return nil 68 } 69 return err 70 } 71 if match == nil { 72 log(logging.Warn, "ignoring file %s because it does not match the migration file pattern", info.Name()) 73 return nil 74 } 75 mf := Migration{ 76 Path: p, 77 Version: match.Version, 78 Name: match.Name, 79 DBType: match.DBType, 80 Direction: match.Direction, 81 Type: match.Type, 82 Runner: runner, 83 } 84 switch mf.Direction { 85 case "up": 86 fm.UpMigrations.Migrations = append(fm.UpMigrations.Migrations, mf) 87 case "down": 88 fm.DownMigrations.Migrations = append(fm.DownMigrations.Migrations, mf) 89 default: 90 // the regex only matches `(up|down)` for direction, so a panic here is appropriate 91 panic("got unknown migration direction " + mf.Direction) 92 } 93 } 94 return nil 95 }) 96 }