-
-
Notifications
You must be signed in to change notification settings - Fork 106
/
migrate.go
126 lines (103 loc) · 3.57 KB
/
migrate.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
package dbal
import (
"fmt"
"path/filepath"
"sort"
"strings"
"github.com/gobuffalo/packr"
"github.com/pkg/errors"
migrate "github.com/rubenv/sql-migrate"
"github.com/sirupsen/logrus"
)
type migrationFile struct {
Filename string
Filepath string
Content []byte
}
const migrationBasePath = "/migrations/sql"
type migrationFiles []migrationFile
func (s migrationFiles) Len() int { return len(s) }
func (s migrationFiles) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s migrationFiles) Less(i, j int) bool { return s[i].Filename < s[j].Filename }
// PackrMigrationSource is a wrapper around *migrate.PackrMigrationSource that allows to modify IDs.
type PackrMigrationSource struct {
*migrate.PackrMigrationSource
omitExtension bool
}
// FindMigrations finds migrations in this source.
func (p PackrMigrationSource) FindMigrations() ([]*migrate.Migration, error) {
migrations, err := p.PackrMigrationSource.FindMigrations()
if err != nil {
return nil, err
}
if p.omitExtension {
for k, m := range migrations {
m.Id = strings.TrimSuffix(m.Id, filepath.Ext(m.Id))
migrations[k] = m
}
}
return migrations, err
}
// FindMatchingTestMigrations finds the matching test migrations from a migration map
func FindMatchingTestMigrations(folder string, migrations map[string]*PackrMigrationSource, assetNames []string, asset func(string) ([]byte, error)) map[string]*PackrMigrationSource {
var testMigrations = map[string]*PackrMigrationSource{}
for name, migration := range migrations {
var filter []string
for _, file := range migration.PackrMigrationSource.Box.List() {
f := folder + strings.Replace(filepath.Base(file), ".sql", "_test.sql", 1)
filter = append(filter, f)
}
testMigrations[name] = NewMustPackerMigrationSource(logrus.New(), assetNames, asset, filter, true)
}
return testMigrations
}
// NewMustPackerMigrationSource create a new packr-based migration source or fatals.
func NewMustPackerMigrationSource(l logrus.FieldLogger, folder []string, loader func(string) ([]byte, error), filters []string, omitExtension bool) *PackrMigrationSource {
m, err := NewPackerMigrationSource(l, folder, loader, filters, omitExtension)
if err != nil {
l.WithError(err).WithField("stack", fmt.Sprintf("%+v", err)).Fatal("Unable to set up migration source")
}
return m
}
// NewPackerMigrationSource create a new packr-based migration source or returns an error
func NewPackerMigrationSource(l logrus.FieldLogger, sources []string, loader func(string) ([]byte, error), filters []string, omitExtension bool) (*PackrMigrationSource, error) {
b := packr.NewBox(migrationBasePath)
var files migrationFiles
for _, source := range sources {
if filepath.Ext(source) != ".sql" {
continue
}
var found bool
for _, f := range filters {
if strings.Contains(source, f) {
found = true
}
}
if !found {
l.WithField("file", source).WithField("filters", fmt.Sprintf("%v", filters)).Debug("Ignoring file because path does not match filters")
continue
}
l.WithField("file", source).Debug("Processing sql migration file")
body, err := loader(source)
if err != nil {
return nil, errors.WithStack(err)
}
files = append(files, migrationFile{
Filename: filepath.Base(source),
Filepath: source,
Content: body,
})
}
sort.Sort(files)
for _, f := range files {
/* #nosec G104 */
b.AddBytes(filepath.ToSlash(filepath.Join(migrationBasePath, f.Filename)), f.Content)
}
return &PackrMigrationSource{
PackrMigrationSource: &migrate.PackrMigrationSource{
Box: b,
Dir: migrationBasePath,
},
omitExtension: omitExtension,
}, nil
}