improve constraint matching, migration structure
This commit is contained in:
@@ -4,11 +4,19 @@ package version
|
|||||||
type List []*Version
|
type List []*Version
|
||||||
|
|
||||||
// Match tests versions against a constraint and returns a new List of matching versions only.
|
// Match tests versions against a constraint and returns a new List of matching versions only.
|
||||||
func (list List) Match(c *Constraint) List {
|
func (list List) Match(constraints ...*Constraint) List {
|
||||||
filtered := List{}
|
filtered := List{}
|
||||||
|
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
if v.Match(c) {
|
ok := true
|
||||||
|
for _, c := range constraints {
|
||||||
|
if !v.Match(c) {
|
||||||
|
ok = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
filtered = append(filtered, v)
|
filtered = append(filtered, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-43
@@ -4,11 +4,71 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Migration maps provide a simple way to run functions wrapped in version constraints.
|
// Migration maps provide a simple way to store and run versioned 'patch' functions.
|
||||||
type Migration map[string]func() error
|
type Migration map[string]Patch
|
||||||
|
|
||||||
// AllVersions returns a List of all versions in the migration map.
|
// Down reverts all patches in reverse version order.
|
||||||
func (m Migration) AllVersions() (List, error) {
|
func (m Migration) Down(after func(*Version)) error {
|
||||||
|
versions, err := m.Versions()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := len(versions); i > 0; i-- {
|
||||||
|
v := versions[i-1]
|
||||||
|
patch := m[v.Text]
|
||||||
|
if err := patch.Down(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if after != nil {
|
||||||
|
after(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match tests versions against a constraint and returns a new migration map of matching versions only.
|
||||||
|
func (m Migration) Match(constraints ...*Constraint) (Migration, error) {
|
||||||
|
l, err := m.Versions()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
l = l.Match(constraints...)
|
||||||
|
|
||||||
|
m2 := Migration{}
|
||||||
|
for _, v := range l {
|
||||||
|
m2[v.Text] = m[v.Text]
|
||||||
|
}
|
||||||
|
|
||||||
|
return m2, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up executes all patches in version order.
|
||||||
|
func (m Migration) Up(after func(*Version)) error {
|
||||||
|
versions, err := m.Versions()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range versions {
|
||||||
|
patch := m[v.Text]
|
||||||
|
if err := patch.Up(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if after != nil {
|
||||||
|
after(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Versions returns a List of all versions in the migration map.
|
||||||
|
func (m Migration) Versions() (List, error) {
|
||||||
l := List{}
|
l := List{}
|
||||||
for str := range m {
|
for str := range m {
|
||||||
v, err := Parse(str)
|
v, err := Parse(str)
|
||||||
@@ -24,43 +84,7 @@ func (m Migration) AllVersions() (List, error) {
|
|||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequiredVersions returns a List of all versions in the migration map that are newer than a given (presumed current) version.
|
type Patch struct {
|
||||||
// If currentVersion is nil, this is identical to AllVersions.
|
Down func() error
|
||||||
func (m Migration) RequiredVersions(currentVersion *Version) (List, error) {
|
Up func() error
|
||||||
l, err := m.AllVersions()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if currentVersion != nil {
|
|
||||||
c := &Constraint{
|
|
||||||
Gt: currentVersion,
|
|
||||||
}
|
|
||||||
l = l.Match(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return l, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run all required migration functions in the migration map.
|
|
||||||
// If currentVersion is nil, all migrations will be run.
|
|
||||||
// If afterEachCallback is not nil, it will be called after each successful migration.
|
|
||||||
func (m Migration) Run(currentVersion *Version, afterEachCallback func(*Version)) error {
|
|
||||||
versions, err := m.RequiredVersions(currentVersion)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range versions {
|
|
||||||
f := m[v.Text]
|
|
||||||
if err := f(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if afterEachCallback != nil {
|
|
||||||
afterEachCallback(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user