mirror of https://github.com/status-im/migrate.git
update go-bindata with latest source.Migration helper
This commit is contained in:
parent
3889c93b63
commit
f7699f1dec
|
@ -45,7 +45,7 @@ is easy. Just implement the [source/driver interface](source/driver.go).
|
|||
|
||||
## CLI usage
|
||||
|
||||
```bash
|
||||
```
|
||||
# dowload, build and install the CLI tool
|
||||
# -tags takes database and source drivers and will only build those
|
||||
$ go get -u -tags 'postgres' -o migrate github.com/mattes/migrate/cli
|
||||
|
|
|
@ -33,8 +33,8 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
// Wrap assets into Resource
|
||||
resource := bindata.Resource(migrations.AssetNames(),
|
||||
// wrap assets into Resource
|
||||
s := bindata.Resource(migrations.AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return migrations.Asset(name)
|
||||
})
|
||||
|
|
|
@ -6,9 +6,6 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/mattes/migrate/source"
|
||||
)
|
||||
|
@ -31,15 +28,10 @@ func init() {
|
|||
source.Register("go-bindata", &Bindata{})
|
||||
}
|
||||
|
||||
// filename example: `123_name.up.ext`
|
||||
// filename example: `123_name.down.ext`
|
||||
var filenameRegex = regexp.MustCompile(`^([0-9]+)_(.*)\.(` + string(down) + `|` + string(up) + `)\.(.*)$`)
|
||||
|
||||
type Bindata struct {
|
||||
path string
|
||||
filesIndex uintSlice
|
||||
files map[uint]map[direction]file
|
||||
assetSource *AssetSource
|
||||
migrations *source.Migrations
|
||||
}
|
||||
|
||||
func (b *Bindata) Open(url string) (source.Driver, error) {
|
||||
|
@ -59,35 +51,20 @@ func WithInstance(instance interface{}) (source.Driver, error) {
|
|||
bn := &Bindata{
|
||||
path: "<go-bindata>",
|
||||
assetSource: as,
|
||||
migrations: source.NewMigrations(),
|
||||
}
|
||||
|
||||
// parse file names and create internal data structure
|
||||
bn.files = make(map[uint]map[direction]file)
|
||||
for _, fi := range as.Names {
|
||||
pf, err := parseFilename(fi)
|
||||
m, err := source.DefaultParse(fi)
|
||||
if err != nil {
|
||||
continue // ignore files that we can't parse
|
||||
}
|
||||
|
||||
if bn.files[pf.version] == nil {
|
||||
bn.files[pf.version] = make(map[direction]file)
|
||||
if !bn.migrations.Append(m) {
|
||||
return nil, fmt.Errorf("unable to parse file %v", fi)
|
||||
}
|
||||
|
||||
// reject duplicate versions
|
||||
if dupf, dup := bn.files[pf.version][pf.direction]; dup {
|
||||
return nil, fmt.Errorf("duplicate file: %v and %v", dupf.filename, fi)
|
||||
}
|
||||
|
||||
bn.files[pf.version][pf.direction] = *pf
|
||||
}
|
||||
|
||||
// create index and sort
|
||||
bn.filesIndex = make(uintSlice, 0)
|
||||
for version, _ := range bn.files {
|
||||
bn.filesIndex = append(bn.filesIndex, version)
|
||||
}
|
||||
sort.Sort(bn.filesIndex)
|
||||
|
||||
return bn, nil
|
||||
}
|
||||
|
||||
|
@ -96,113 +73,47 @@ func (b *Bindata) Close() error {
|
|||
}
|
||||
|
||||
func (b *Bindata) First() (version uint, err error) {
|
||||
if len(b.filesIndex) == 0 {
|
||||
if v, ok := b.migrations.First(); !ok {
|
||||
return 0, &os.PathError{"first", b.path, os.ErrNotExist}
|
||||
} else {
|
||||
return v, nil
|
||||
}
|
||||
return b.filesIndex[0], nil
|
||||
}
|
||||
|
||||
func (b *Bindata) Prev(version uint) (prevVersion uint, err error) {
|
||||
pos := b.findPos(version)
|
||||
if pos >= 1 && len(b.filesIndex) > pos-1 {
|
||||
return b.filesIndex[pos-1], nil
|
||||
if v, ok := b.migrations.Prev(version); !ok {
|
||||
return 0, &os.PathError{fmt.Sprintf("prev for version %v", version), b.path, os.ErrNotExist}
|
||||
} else {
|
||||
return v, nil
|
||||
}
|
||||
return 0, &os.PathError{fmt.Sprintf("prev for version %v", version), b.path, os.ErrNotExist}
|
||||
}
|
||||
|
||||
func (b *Bindata) Next(version uint) (nextVersion uint, err error) {
|
||||
pos := b.findPos(version)
|
||||
if pos >= 0 && len(b.filesIndex) > pos+1 {
|
||||
return b.filesIndex[pos+1], nil
|
||||
if v, ok := b.migrations.Next(version); !ok {
|
||||
return 0, &os.PathError{fmt.Sprintf("next for version %v", version), b.path, os.ErrNotExist}
|
||||
} else {
|
||||
return v, nil
|
||||
}
|
||||
return 0, &os.PathError{fmt.Sprintf("next for version %v", version), b.path, os.ErrNotExist}
|
||||
}
|
||||
|
||||
func (b *Bindata) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) {
|
||||
if _, ok := b.files[version]; ok {
|
||||
if upFile, ok := b.files[version][up]; ok {
|
||||
body, err := b.assetSource.AssetFunc(upFile.filename)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return ioutil.NopCloser(bytes.NewReader(body)), upFile.name, nil
|
||||
if m, ok := b.migrations.Up(version); ok {
|
||||
body, err := b.assetSource.AssetFunc(m.Raw)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return ioutil.NopCloser(bytes.NewReader(body)), m.Identifier, nil
|
||||
}
|
||||
return nil, "", &os.PathError{fmt.Sprintf("read version %v", version), b.path, os.ErrNotExist}
|
||||
}
|
||||
|
||||
func (b *Bindata) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) {
|
||||
if _, ok := b.files[version]; ok {
|
||||
if downFile, ok := b.files[version][down]; ok {
|
||||
body, err := b.assetSource.AssetFunc(downFile.filename)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return ioutil.NopCloser(bytes.NewReader(body)), downFile.name, nil
|
||||
if m, ok := b.migrations.Down(version); ok {
|
||||
body, err := b.assetSource.AssetFunc(m.Raw)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return ioutil.NopCloser(bytes.NewReader(body)), m.Identifier, nil
|
||||
}
|
||||
return nil, "", &os.PathError{fmt.Sprintf("read version %v", version), b.path, os.ErrNotExist}
|
||||
}
|
||||
|
||||
// findPos finds the position of a file in the index
|
||||
// returns -1 if the version can't be found
|
||||
func (b *Bindata) findPos(version uint) int {
|
||||
if len(b.filesIndex) > 0 {
|
||||
for i, v := range b.filesIndex {
|
||||
if v == version {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// file contains parsed filename details
|
||||
type file struct {
|
||||
version uint
|
||||
name string
|
||||
direction direction
|
||||
extension string
|
||||
filename string
|
||||
}
|
||||
|
||||
var errParseFilenameNoMatch = fmt.Errorf("no match")
|
||||
|
||||
func parseFilename(filename string) (*file, error) {
|
||||
m := filenameRegex.FindStringSubmatch(filename)
|
||||
if len(m) == 5 {
|
||||
versionUint64, err := strconv.ParseUint(m[1], 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &file{
|
||||
version: uint(versionUint64),
|
||||
name: m[2],
|
||||
direction: direction(m[3]),
|
||||
extension: m[4],
|
||||
filename: filename,
|
||||
}, nil
|
||||
}
|
||||
return nil, errParseFilenameNoMatch
|
||||
}
|
||||
|
||||
type direction string
|
||||
|
||||
const (
|
||||
down direction = "down"
|
||||
up = "up"
|
||||
)
|
||||
|
||||
type uintSlice []uint
|
||||
|
||||
func (s uintSlice) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s uintSlice) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s uintSlice) Less(i, j int) bool {
|
||||
return s[i] < s[j]
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func Test(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWithInstance(t *testing.T) {
|
||||
// wrap assets into Resource first
|
||||
// wrap assets into Resource
|
||||
s := Resource(testdata.AssetNames(),
|
||||
func(name string) ([]byte, error) {
|
||||
return testdata.Asset(name)
|
||||
|
|
Loading…
Reference in New Issue