func (m *Migrate) Force(version int) error {
	if version < -1 {
		panic("version must be >= -1")
	}
	if err := m.lock(); err != nil {
		return err
	}
	if err := m.databaseDrv.SetVersion(version, false); err != nil {
		return m.unlockErr(err)
	}
	return m.unlock()
}
Force sets a migration version.
It does not check any currently active version in database.
It resets the dirty state to false.
package migrate
import (
	"fmt"
	"os"
	"sync"
	"time"
	"github.com/mattes/migrate/database"
	"github.com/mattes/migrate/source"
)
var DefaultPrefetchMigrations = uint(10)
var DefaultLockTimeout = 15 * time.Second
var (
	ErrNoChange    = fmt.Errorf("no change")
	ErrNilVersion  = fmt.Errorf("no migration")
	ErrLocked      = fmt.Errorf("database locked")
	ErrLockTimeout = fmt.Errorf("timeout: can't acquire database lock")
)
type ErrShortLimit struct {
	Short uint
}
func (e ErrShortLimit) Error() string {
	return fmt.Sprintf("limit %v short", e.Short)
}
type ErrDirty struct {
	Version int
}
func (e ErrDirty) Error() string {
	return fmt.Sprintf("Dirty database version %v. Fix and force version.", e.Version)
}
type Migrate struct {
	sourceName   string
	sourceDrv    source.Driver
	databaseName string
	databaseDrv  database.Driver
	Log Logger
	GracefulStop   chan bool
	isGracefulStop bool
	isLockedMu *sync.Mutex
	isLocked   bool
	PrefetchMigrations uint
	LockTimeout time.Duration
}
func New(sourceUrl, databaseUrl string) (*Migrate, error) {
	m := newCommon()
	sourceName, err := schemeFromUrl(sourceUrl)
	if err != nil {
		return nil, err
	}
	m.sourceName = sourceName
	databaseName, err := schemeFromUrl(databaseUrl)
	if err != nil {
		return nil, err
	}
	m.databaseName = databaseName
	sourceDrv, err := source.Open(sourceUrl)
	if err != nil {
		return nil, err
	}
	m.sourceDrv = sourceDrv
	databaseDrv, err := database.Open(databaseUrl)
	if err != nil {
		return nil, err
	}
	m.databaseDrv = databaseDrv
	return m, nil
}
func NewWithDatabaseInstance(sourceUrl string, databaseName string, databaseInstance database.Driver) (*Migrate, error) {
	m := newCommon()
	sourceName, err := schemeFromUrl(sourceUrl)
	if err != nil {
		return nil, err
	}
	m.sourceName = sourceName
	m.databaseName = databaseName
	sourceDrv, err := source.Open(sourceUrl)
	if err != nil {
		return nil, err
	}
	m.sourceDrv = sourceDrv
	m.databaseDrv = databaseInstance
	return m, nil
}
func NewWithSourceInstance(sourceName string, sourceInstance source.Driver, databaseUrl string) (*Migrate, error) {
	m := newCommon()
	databaseName, err := schemeFromUrl(databaseUrl)
	if err != nil {
		return nil, err
	}
	m.databaseName = databaseName
	m.sourceName = sourceName
	databaseDrv, err := database.Open(databaseUrl)
	if err != nil {
		return nil, err
	}
	m.databaseDrv = databaseDrv
	m.sourceDrv = sourceInstance
	return m, nil
}
func NewWithInstance(sourceName string, sourceInstance source.Driver, databaseName string, databaseInstance database.Driver) (*Migrate, error) {
	m := newCommon()
	m.sourceName = sourceName
	m.databaseName = databaseName
	m.sourceDrv = sourceInstance
	m.databaseDrv = databaseInstance
	return m, nil
}
func newCommon() *Migrate {
	return &Migrate{
		GracefulStop:       make(chan bool, 1),
		PrefetchMigrations: DefaultPrefetchMigrations,
		LockTimeout:        DefaultLockTimeout,
		isLockedMu:         &sync.Mutex{},
	}
}
func (m *Migrate) Close() (source error, database error) {
	databaseSrvClose := make(chan error)
	sourceSrvClose := make(chan error)
	m.logVerbosePrintf("Closing source and database\n")
	go func() {
		databaseSrvClose <- m.databaseDrv.Close()
	}()
	go func() {
		sourceSrvClose <- m.sourceDrv.Close()
	}()
	return <-sourceSrvClose, <-databaseSrvClose
}
func (m *Migrate) Migrate(version uint) error {
	if err := m.lock(); err != nil {
		return err
	}
	curVersion, dirty, err := m.databaseDrv.Version()
	if err != nil {
		return m.unlockErr(err)
	}
	if dirty {
		return m.unlockErr(ErrDirty{curVersion})
	}
	ret := make(chan interface{}, m.PrefetchMigrations)
	go m.read(curVersion, int(version), ret)
	return m.unlockErr(m.runMigrations(ret))
}
func (m *Migrate) Steps(n int) error {
	if n == 0 {
		return ErrNoChange
	}
	if err := m.lock(); err != nil {
		return err
	}
	curVersion, dirty, err := m.databaseDrv.Version()
	if err != nil {
		return m.unlockErr(err)
	}
	if dirty {
		return m.unlockErr(ErrDirty{curVersion})
	}
	ret := make(chan interface{}, m.PrefetchMigrations)
	if n > 0 {
		go m.readUp(curVersion, n, ret)
	} else {
		go m.readDown(curVersion, -n, ret)
	}
	return m.unlockErr(m.runMigrations(ret))
}
func (m *Migrate) Up() error {
	if err := m.lock(); err != nil {
		return err
	}
	curVersion, dirty, err := m.databaseDrv.Version()
	if err != nil {
		return m.unlockErr(err)
	}
	if dirty {
		return m.unlockErr(ErrDirty{curVersion})
	}
	ret := make(chan interface{}, m.PrefetchMigrations)
	go m.readUp(curVersion, -1, ret)
	return m.unlockErr(m.runMigrations(ret))
}
func (m *Migrate) Down() error {
	if err := m.lock(); err != nil {
		return err
	}
	curVersion, dirty, err := m.databaseDrv.Version()
	if err != nil {
		return m.unlockErr(err)
	}
	if dirty {
		return m.unlockErr(ErrDirty{curVersion})
	}
	ret := make(chan interface{}, m.PrefetchMigrations)
	go m.readDown(curVersion, -1, ret)
	return m.unlockErr(m.runMigrations(ret))
}
func (m *Migrate) Drop() error {
	if err := m.lock(); err != nil {
		return err
	}
	if err := m.databaseDrv.Drop(); err != nil {
		return m.unlockErr(err)
	}
	return m.unlock()
}
func (m *Migrate) Run(migration ...*Migration) error {
	if len(migration) == 0 {
		return ErrNoChange
	}
	if err := m.lock(); err != nil {
		return err
	}
	curVersion, dirty, err := m.databaseDrv.Version()
	if err != nil {
		return m.unlockErr(err)
	}
	if dirty {
		return m.unlockErr(ErrDirty{curVersion})
	}
	ret := make(chan interface{}, m.PrefetchMigrations)
	go func() {
		defer close(ret)
		for _, migr := range migration {
			if m.PrefetchMigrations > 0 && migr.Body != nil {
				m.logVerbosePrintf("Start buffering %v\n", migr.LogString())
			} else {
				m.logVerbosePrintf("Scheduled %v\n", migr.LogString())
			}
			ret <- migr
			go migr.Buffer()
		}
	}()
	return m.unlockErr(m.runMigrations(ret))
}