github.com/svrana/migrate@v3.5.4+incompatible/source/file/file.go (about) 1 package file 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 nurl "net/url" 8 "os" 9 "path" 10 "path/filepath" 11 12 "github.com/golang-migrate/migrate/source" 13 ) 14 15 func init() { 16 source.Register("file", &File{}) 17 } 18 19 type File struct { 20 url string 21 path string 22 migrations *source.Migrations 23 } 24 25 func (f *File) Open(url string) (source.Driver, error) { 26 u, err := nurl.Parse(url) 27 if err != nil { 28 return nil, err 29 } 30 31 // concat host and path to restore full path 32 // host might be `.` 33 p := u.Host + u.Path 34 35 if len(p) == 0 { 36 // default to current directory if no path 37 wd, err := os.Getwd() 38 if err != nil { 39 return nil, err 40 } 41 p = wd 42 43 } else if p[0:1] == "." || p[0:1] != "/" { 44 // make path absolute if relative 45 abs, err := filepath.Abs(p) 46 if err != nil { 47 return nil, err 48 } 49 p = abs 50 } 51 52 // scan directory 53 files, err := ioutil.ReadDir(p) 54 if err != nil { 55 return nil, err 56 } 57 58 nf := &File{ 59 url: url, 60 path: p, 61 migrations: source.NewMigrations(), 62 } 63 64 for _, fi := range files { 65 if !fi.IsDir() { 66 m, err := source.DefaultParse(fi.Name()) 67 if err != nil { 68 continue // ignore files that we can't parse 69 } 70 if !nf.migrations.Append(m) { 71 return nil, fmt.Errorf("unable to parse file %v", fi.Name()) 72 } 73 } 74 } 75 return nf, nil 76 } 77 78 func (f *File) Close() error { 79 // nothing do to here 80 return nil 81 } 82 83 func (f *File) First() (version uint, err error) { 84 if v, ok := f.migrations.First(); !ok { 85 return 0, &os.PathError{Op: "first", Path: f.path, Err: os.ErrNotExist} 86 } else { 87 return v, nil 88 } 89 } 90 91 func (f *File) Prev(version uint) (prevVersion uint, err error) { 92 if v, ok := f.migrations.Prev(version); !ok { 93 return 0, &os.PathError{Op: fmt.Sprintf("prev for version %v", version), Path: f.path, Err: os.ErrNotExist} 94 } else { 95 return v, nil 96 } 97 } 98 99 func (f *File) Next(version uint) (nextVersion uint, err error) { 100 if v, ok := f.migrations.Next(version); !ok { 101 return 0, &os.PathError{Op: fmt.Sprintf("next for version %v", version), Path: f.path, Err: os.ErrNotExist} 102 } else { 103 return v, nil 104 } 105 } 106 107 func (f *File) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) { 108 if m, ok := f.migrations.Up(version); ok { 109 r, err := os.Open(path.Join(f.path, m.Raw)) 110 if err != nil { 111 return nil, "", err 112 } 113 return r, m.Identifier, nil 114 } 115 return nil, "", &os.PathError{Op: fmt.Sprintf("read version %v", version), Path: f.path, Err: os.ErrNotExist} 116 } 117 118 func (f *File) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) { 119 if m, ok := f.migrations.Down(version); ok { 120 r, err := os.Open(path.Join(f.path, m.Raw)) 121 if err != nil { 122 return nil, "", err 123 } 124 return r, m.Identifier, nil 125 } 126 return nil, "", &os.PathError{Op: fmt.Sprintf("read version %v", version), Path: f.path, Err: os.ErrNotExist} 127 }