diff --git a/migration.go b/migration.go new file mode 100644 index 0000000..f3e4c04 --- /dev/null +++ b/migration.go @@ -0,0 +1,66 @@ +package version + +import ( + "sort" +) + +// Migration maps provide a simple way to run functions wrapped in version constraints. +type Migration map[string]func() error + +// AllVersions returns a List of all versions in the migration map. +func (m Migration) AllVersions() (List, error) { + l := List{} + for str := range m { + v, err := Parse(str) + if err != nil { + return nil, err + } + + l = append(l, v) + } + + sort.Stable(l) + + return l, nil +} + +// RequiredVersions returns a List of all versions in the migration map that are newer than a given (presumed current) version. +// If currentVersion is nil, this is identical to AllVersions. +func (m Migration) RequiredVersions(currentVersion *Version) (List, 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 +}