github.com/dynastymasra/migrate/v4@v4.11.0/source/httpfs/partial_driver.go (about) 1 package httpfs 2 3 import ( 4 "io" 5 "net/http" 6 "os" 7 "path" 8 "strconv" 9 10 "github.com/golang-migrate/migrate/v4/source" 11 ) 12 13 // PartialDriver is a helper service for creating new source drivers working with 14 // http.FileSystem instances. It implements all source.Driver interface methods 15 // except for Open(). New driver could embed this struct and add missing Open() 16 // method. 17 // 18 // To prepare PartialDriver for use Init() function. 19 type PartialDriver struct { 20 migrations *source.Migrations 21 fs http.FileSystem 22 path string 23 } 24 25 // Init prepares not initialized PartialDriver instance to read migrations from a 26 // http.FileSystem instance and a relative path. 27 func (p *PartialDriver) Init(fs http.FileSystem, path string) error { 28 root, err := fs.Open(path) 29 if err != nil { 30 return err 31 } 32 33 files, err := root.Readdir(0) 34 if err != nil { 35 _ = root.Close() 36 return err 37 } 38 if err = root.Close(); err != nil { 39 return err 40 } 41 42 ms := source.NewMigrations() 43 for _, file := range files { 44 if file.IsDir() { 45 continue 46 } 47 48 m, err := source.DefaultParse(file.Name()) 49 if err != nil { 50 continue // ignore files that we can't parse 51 } 52 53 if !ms.Append(m) { 54 return source.ErrDuplicateMigration{ 55 Migration: *m, 56 FileInfo: file, 57 } 58 } 59 } 60 61 p.fs = fs 62 p.path = path 63 p.migrations = ms 64 return nil 65 } 66 67 // Close is part of source.Driver interface implementation. This is a no-op. 68 func (p *PartialDriver) Close() error { 69 return nil 70 } 71 72 // First is part of source.Driver interface implementation. 73 func (p *PartialDriver) First() (version uint, err error) { 74 if version, ok := p.migrations.First(); ok { 75 return version, nil 76 } 77 return 0, &os.PathError{ 78 Op: "first", 79 Path: p.path, 80 Err: os.ErrNotExist, 81 } 82 } 83 84 // Prev is part of source.Driver interface implementation. 85 func (p *PartialDriver) Prev(version uint) (prevVersion uint, err error) { 86 if version, ok := p.migrations.Prev(version); ok { 87 return version, nil 88 } 89 return 0, &os.PathError{ 90 Op: "prev for version " + strconv.FormatUint(uint64(version), 10), 91 Path: p.path, 92 Err: os.ErrNotExist, 93 } 94 } 95 96 // Next is part of source.Driver interface implementation. 97 func (p *PartialDriver) Next(version uint) (nextVersion uint, err error) { 98 if version, ok := p.migrations.Next(version); ok { 99 return version, nil 100 } 101 return 0, &os.PathError{ 102 Op: "next for version " + strconv.FormatUint(uint64(version), 10), 103 Path: p.path, 104 Err: os.ErrNotExist, 105 } 106 } 107 108 // ReadUp is part of source.Driver interface implementation. 109 func (p *PartialDriver) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) { 110 if m, ok := p.migrations.Up(version); ok { 111 body, err := p.fs.Open(path.Join(p.path, m.Raw)) 112 if err != nil { 113 return nil, "", err 114 } 115 return body, m.Identifier, nil 116 } 117 return nil, "", &os.PathError{ 118 Op: "read up for version " + strconv.FormatUint(uint64(version), 10), 119 Path: p.path, 120 Err: os.ErrNotExist, 121 } 122 } 123 124 // ReadDown is part of source.Driver interface implementation. 125 func (p *PartialDriver) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) { 126 if m, ok := p.migrations.Down(version); ok { 127 body, err := p.fs.Open(path.Join(p.path, m.Raw)) 128 if err != nil { 129 return nil, "", err 130 } 131 return body, m.Identifier, nil 132 } 133 return nil, "", &os.PathError{ 134 Op: "read down for version " + strconv.FormatUint(uint64(version), 10), 135 Path: p.path, 136 Err: os.ErrNotExist, 137 } 138 }