github.com/bdollma-te/migrate/v4@v4.17.0-clickv2/source/pkger/pkger.go (about) 1 package pkger 2 3 import ( 4 "fmt" 5 "net/http" 6 stdurl "net/url" 7 8 "github.com/bdollma-te/migrate/v4/source" 9 "github.com/bdollma-te/migrate/v4/source/httpfs" 10 "github.com/markbates/pkger" 11 "github.com/markbates/pkger/pkging" 12 ) 13 14 func init() { 15 source.Register("pkger", &Pkger{}) 16 } 17 18 // Pkger is a source.Driver that reads migrations from instances of 19 // pkging.Pkger. 20 type Pkger struct { 21 httpfs.PartialDriver 22 } 23 24 // Open implements source.Driver. The path component of url will be used as the 25 // relative location of migrations. The returned driver will use the package 26 // scoped pkger.Open to access migrations. The relative root and any 27 // migrations must be added to the global pkger.Pkger instance by calling 28 // pkger.Apply. Refer to Pkger documentation for more information. 29 func (p *Pkger) Open(url string) (source.Driver, error) { 30 u, err := stdurl.Parse(url) 31 if err != nil { 32 return nil, err 33 } 34 35 // wrap pkger to implement http.FileSystem. 36 fs := fsFunc(func(name string) (http.File, error) { 37 f, err := pkger.Open(name) 38 if err != nil { 39 return nil, err 40 } 41 return f.(http.File), nil 42 }) 43 44 if err := p.Init(fs, u.Path); err != nil { 45 return nil, fmt.Errorf("failed to init driver with relative path %q: %w", u.Path, err) 46 } 47 48 return p, nil 49 } 50 51 // WithInstance returns a source.Driver that is backed by an instance of 52 // pkging.Pkger. The relative location of migrations is indicated by path. The 53 // path must exist on the pkging.Pkger instance for the driver to initialize 54 // successfully. 55 func WithInstance(instance pkging.Pkger, path string) (source.Driver, error) { 56 if instance == nil { 57 return nil, fmt.Errorf("expected instance of pkging.Pkger") 58 } 59 60 // wrap pkger to implement http.FileSystem. 61 fs := fsFunc(func(name string) (http.File, error) { 62 f, err := instance.Open(name) 63 if err != nil { 64 return nil, err 65 } 66 return f.(http.File), nil 67 }) 68 69 var p Pkger 70 71 if err := p.Init(fs, path); err != nil { 72 return nil, fmt.Errorf("failed to init driver with relative path %q: %w", path, err) 73 } 74 75 return &p, nil 76 } 77 78 type fsFunc func(name string) (http.File, error) 79 80 // Open implements http.FileSystem. 81 func (f fsFunc) Open(name string) (http.File, error) { 82 return f(name) 83 }