mirror of https://github.com/status-im/migrate.git
167 lines
3.6 KiB
Go
167 lines
3.6 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/golang-migrate/migrate/v4"
|
|
_ "github.com/golang-migrate/migrate/v4/database/stub" // TODO remove again
|
|
_ "github.com/golang-migrate/migrate/v4/source/file"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func nextSeq(matches []string, dir string, seqDigits int) (string, error) {
|
|
if seqDigits <= 0 {
|
|
return "", errors.New("Digits must be positive")
|
|
}
|
|
|
|
nextSeq := 1
|
|
if len(matches) > 0 {
|
|
filename := matches[len(matches)-1]
|
|
matchSeqStr := strings.TrimPrefix(filename, dir)
|
|
idx := strings.Index(matchSeqStr, "_")
|
|
if idx < 1 { // Using 1 instead of 0 since there should be at least 1 digit
|
|
return "", errors.New("Malformed migration filename: " + filename)
|
|
}
|
|
matchSeqStr = matchSeqStr[0:idx]
|
|
var err error
|
|
nextSeq, err = strconv.Atoi(matchSeqStr)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
nextSeq++
|
|
}
|
|
if nextSeq <= 0 {
|
|
return "", errors.New("Next sequence number must be positive")
|
|
}
|
|
|
|
nextSeqStr := strconv.Itoa(nextSeq)
|
|
if len(nextSeqStr) > seqDigits {
|
|
return "", fmt.Errorf("Next sequence number %s too large. At most %d digits are allowed", nextSeqStr, seqDigits)
|
|
}
|
|
padding := seqDigits - len(nextSeqStr)
|
|
if padding > 0 {
|
|
nextSeqStr = strings.Repeat("0", padding) + nextSeqStr
|
|
}
|
|
return nextSeqStr, nil
|
|
}
|
|
|
|
func createCmd(dir string, startTime time.Time, format string, name string, ext string, seq bool, seqDigits int) {
|
|
var base string
|
|
if seq && format != defaultTimeFormat {
|
|
log.fatalErr(errors.New("The seq and format options are mutually exclusive"))
|
|
}
|
|
if seq {
|
|
if seqDigits <= 0 {
|
|
log.fatalErr(errors.New("Digits must be positive"))
|
|
}
|
|
matches, err := filepath.Glob(dir + "*" + ext)
|
|
if err != nil {
|
|
log.fatalErr(err)
|
|
}
|
|
nextSeqStr, err := nextSeq(matches, dir, seqDigits)
|
|
if err != nil {
|
|
log.fatalErr(err)
|
|
}
|
|
base = fmt.Sprintf("%v%v_%v.", dir, nextSeqStr, name)
|
|
} else {
|
|
switch format {
|
|
case "":
|
|
log.fatal("Time format may not be empty")
|
|
case "unix":
|
|
base = fmt.Sprintf("%v%v_%v.", dir, startTime.Unix(), name)
|
|
case "unixNano":
|
|
base = fmt.Sprintf("%v%v_%v.", dir, startTime.UnixNano(), name)
|
|
default:
|
|
base = fmt.Sprintf("%v%v_%v.", dir, startTime.Format(format), name)
|
|
}
|
|
}
|
|
|
|
os.MkdirAll(dir, os.ModePerm)
|
|
createFile(base + "up" + ext)
|
|
createFile(base + "down" + ext)
|
|
}
|
|
|
|
func createFile(fname string) {
|
|
if _, err := os.Create(fname); err != nil {
|
|
log.fatalErr(err)
|
|
}
|
|
}
|
|
|
|
func gotoCmd(m *migrate.Migrate, v uint) {
|
|
if err := m.Migrate(v); err != nil {
|
|
if err != migrate.ErrNoChange {
|
|
log.fatalErr(err)
|
|
} else {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func upCmd(m *migrate.Migrate, limit int) {
|
|
if limit >= 0 {
|
|
if err := m.Steps(limit); err != nil {
|
|
if err != migrate.ErrNoChange {
|
|
log.fatalErr(err)
|
|
} else {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
} else {
|
|
if err := m.Up(); err != nil {
|
|
if err != migrate.ErrNoChange {
|
|
log.fatalErr(err)
|
|
} else {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func downCmd(m *migrate.Migrate, limit int) {
|
|
if limit >= 0 {
|
|
if err := m.Steps(-limit); err != nil {
|
|
if err != migrate.ErrNoChange {
|
|
log.fatalErr(err)
|
|
} else {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
} else {
|
|
if err := m.Down(); err != nil {
|
|
if err != migrate.ErrNoChange {
|
|
log.fatalErr(err)
|
|
} else {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func dropCmd(m *migrate.Migrate) {
|
|
if err := m.Drop(); err != nil {
|
|
log.fatalErr(err)
|
|
}
|
|
}
|
|
|
|
func forceCmd(m *migrate.Migrate, v int) {
|
|
if err := m.Force(v); err != nil {
|
|
log.fatalErr(err)
|
|
}
|
|
}
|
|
|
|
func versionCmd(m *migrate.Migrate) {
|
|
v, dirty, err := m.Version()
|
|
if err != nil {
|
|
log.fatalErr(err)
|
|
}
|
|
if dirty {
|
|
log.Printf("%v (dirty)\n", v)
|
|
} else {
|
|
log.Println(v)
|
|
}
|
|
}
|