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