这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cli/commands/migrate_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ type migrateCreateOptions struct {

func (o *migrateCreateOptions) run() error {
timestamp := getTime()
err := mig.CreateCmd(o.EC.MigrationDir, timestamp, o.name)
createOptions := mig.New(timestamp, o.name, o.EC.MigrationDir)
createOptions.IsCMD = true
err := createOptions.Create()
if err != nil {
return errors.Wrap(err, "error creating migration files")
}
Expand Down
19 changes: 16 additions & 3 deletions cli/migrate/api/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Response struct {
type Request struct {
Name string `json:"name"`
Up []interface{} `json:"up"`
Down []interface{} `json:"down"`
}

func MigrateAPI(c *gin.Context) {
Expand Down Expand Up @@ -79,7 +80,19 @@ func MigrateAPI(c *gin.Context) {
// Convert to Millisecond
timestamp := startTime.UnixNano() / int64(time.Millisecond)

err = cmd.CreateCmd(sourceURL.Path, timestamp, request.Name, request.Up)
createOptions := cmd.New(timestamp, request.Name, sourceURL.Path)
err = createOptions.SetMetaUp(request.Up)
if err != nil {
c.JSON(http.StatusInternalServerError, &Response{Code: "create_file_error", Message: err.Error()})
return
}
err = createOptions.SetMetaDown(request.Down)
if err != nil {
c.JSON(http.StatusInternalServerError, &Response{Code: "create_file_error", Message: err.Error()})
return
}

err = createOptions.Create()
if err != nil {
c.JSON(http.StatusInternalServerError, &Response{Code: "create_file_error", Message: err.Error()})
return
Expand All @@ -88,7 +101,7 @@ func MigrateAPI(c *gin.Context) {
// Rescan file system
err = t.ReScan()
if err != nil {
deleteErr := cmd.DeleteCmd(sourceURL.Path, timestamp)
deleteErr := createOptions.Delete()
if deleteErr != nil {
c.JSON(http.StatusInternalServerError, &Response{Code: "delete_file_error", Message: deleteErr.Error()})
return
Expand All @@ -98,7 +111,7 @@ func MigrateAPI(c *gin.Context) {
}

if err = t.Migrate(uint64(timestamp), "up"); err != nil {
deleteErr := cmd.DeleteCmd(sourceURL.Path, timestamp)
deleteErr := createOptions.Delete()
if deleteErr != nil {
c.JSON(http.StatusInternalServerError, &Response{Code: "delete_file_error", Message: deleteErr.Error()})
return
Expand Down
152 changes: 86 additions & 66 deletions cli/migrate/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,103 +21,123 @@ const (

var ext = []string{sqlFile, yamlFile}

func DeleteCmd(dir string, timestamp int64) error {
count := 0
type CreateOptions struct {
Version int64
Directory string
Name string
IsCMD bool
MetaUp []byte
MetaDown []byte
SQLUp []byte
SQLDown []byte
}

func New(version int64, name, directory string) *CreateOptions {
if runtime.GOOS == "windows" {
dir = strings.TrimPrefix(dir, "/")
directory = strings.TrimPrefix(directory, "/")
}
fileName := fmt.Sprintf("%v_", timestamp)
// scan directory
files, err := ioutil.ReadDir(dir)
return &CreateOptions{
Version: version,
Directory: directory,
Name: name,
MetaUp: []byte(`[]`),
MetaDown: []byte(`[]`),
SQLUp: []byte{},
SQLDown: []byte{},
}
}

func (c *CreateOptions) SetMetaUp(data interface{}) error {
t, err := json.Marshal(data)
if err != nil {
return err
}
yamlData, err := yaml.JSONToYAML(t)
if err != nil {
return err
}
c.MetaUp = yamlData
return nil
}

for _, fi := range files {
if !fi.IsDir() {
if strings.HasPrefix(fi.Name(), fileName) {
base := filepath.Join(dir, fi.Name())
err = deleteFile(base)
if err != nil {
return err
}
count = count + 1
}
}
func (c *CreateOptions) SetMetaDown(data interface{}) error {
t, err := json.Marshal(data)
if err != nil {
return err
}
if count == 0 {
return errors.New("Cannot find any migration file")
yamlData, err := yaml.JSONToYAML(t)
if err != nil {
return err
}
c.MetaDown = yamlData
return nil
}

func CreateCmd(dir string, timestamp int64, name string, options ...interface{}) error {
if runtime.GOOS == "windows" {
dir = strings.TrimPrefix(dir, "/")
func (c *CreateOptions) SetSQLUp(data string) error {
c.SQLUp = []byte(data)
return nil
}

func (c *CreateOptions) SetSQLDown(data string) error {
c.SQLDown = []byte(data)
return nil
}

func (c *CreateOptions) Create() error {
fileName := fmt.Sprintf("%v_%v.", c.Version, c.Name)
base := filepath.Join(c.Directory, fileName)
err := os.MkdirAll(c.Directory, os.ModePerm)
if err != nil {
return err
}
fileName := fmt.Sprintf("%v_%v.", timestamp, name)
base := filepath.Join(dir, fileName)
err := os.MkdirAll(dir, os.ModePerm)
// Create MetaUp
err = createFile(base+"up.yaml", c.MetaUp)
if err != nil {
return err
}

// If len(options) == 0, cmd else, api
if len(options) == 0 {
return createForCMD(base)
// Create MetaDown
err = createFile(base+"down.yaml", c.MetaDown)
if err != nil {
return err
}
return createForAPI(base, options[0])
}

func createForCMD(base string) error {
var data []byte
var err error
for _, v := range ext {
switch v {
case sqlFile:
data = []byte{}
case yamlFile:
bytes := []byte(`[]`)
data, err = yaml.JSONToYAML(bytes)
if err != nil {
return err
}
}
err = createFile(base+"up"+v, data)
if c.IsCMD {
err = createFile(base+"up.sql", c.SQLUp)
if err != nil {
return err
}
err = createFile(base+"down"+v, data)
err = createFile(base+"down.sql", c.SQLDown)
if err != nil {
return err
}
}
return nil
}

func createForAPI(base string, options interface{}) error {
var data []byte
for _, v := range ext {
switch v {
// Only yaml file for api-console
case yamlFile:
// Up file
t, err := json.Marshal(options)
if err != nil {
return err
}

data, err = yaml.JSONToYAML(t)
if err != nil {
return err
}
func (c *CreateOptions) Delete() error {
count := 0
fileName := fmt.Sprintf("%v_", c.Version)
// scan directory
files, err := ioutil.ReadDir(c.Directory)
if err != nil {
return err
}

err = createFile(base+"up"+v, data)
if err != nil {
return err
for _, fi := range files {
if !fi.IsDir() {
if strings.HasPrefix(fi.Name(), fileName) {
base := filepath.Join(c.Directory, fi.Name())
err = deleteFile(base)
if err != nil {
return err
}
count = count + 1
}
}
}
if count == 0 {
return errors.New("Cannot find any migration file")
}
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion cli/migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ func (m *Migrate) versionUpExists(version uint64) error {
return os.ErrNotExist
}

// versionUpExists checks the source if either the up or down migration for
// versionDownExists checks the source if either the up or down migration for
// the specified migration version exists.
func (m *Migrate) versionDownExists(version uint64) error {
// try up migration first
Expand Down
2 changes: 1 addition & 1 deletion cli/migrate/source/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (f *File) Open(url string, logger *log.Logger) (source.Driver, error) {

for _, fi := range files {
if !fi.IsDir() {
m, err := source.DefaultParse(fi.Name())
m, err := source.DefaultParse(fi.Name(), p)
if err != nil {
continue // ignore files that we can't parse
}
Expand Down
26 changes: 19 additions & 7 deletions cli/migrate/source/file/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,28 @@ func Test(t *testing.T) {
// write files that meet driver test requirements
mustWriteFile(t, tmpDir, "1_foobar.up.sql", "1 up")
mustWriteFile(t, tmpDir, "1_foobar.down.sql", "1 down")
mustWriteFile(t, tmpDir, "1_foobar.up.yaml", "1 metaup")
mustWriteFile(t, tmpDir, "1_foobar.down.yaml", "1 metadown")
mustWriteFile(t, tmpDir, "1_foobar.up.yaml", `- args:
name: test
type: add_existing_table_or_view
`)
mustWriteFile(t, tmpDir, "1_foobar.down.yaml", `- args:
name: test
type: add_existing_table_or_view
`)

mustWriteFile(t, tmpDir, "3_foobar.up.sql", "3 up")

mustWriteFile(t, tmpDir, "4_foobar.up.yaml", "4 metaup")
mustWriteFile(t, tmpDir, "4_foobar.up.yaml", `- args:
name: test
type: add_existing_table_or_view
`)

mustWriteFile(t, tmpDir, "5_foobar.down.sql", "5 down")

mustWriteFile(t, tmpDir, "6_foobar.down.yaml", "6 metadown")
mustWriteFile(t, tmpDir, "6_foobar.down.yaml", `- args:
name: test
type: add_existing_table_or_view
`)

mustWriteFile(t, tmpDir, "8_foobar.up.sql", "7 up")
mustWriteFile(t, tmpDir, "8_foobar.down.sql", "7 down")
Expand Down Expand Up @@ -89,7 +101,7 @@ func TestOpenWithRelativePath(t *testing.T) {
t.Fatal(err)
}

mustWriteFile(t, filepath.Join(tmpDir, "foo"), "1_foobar.up.sql", "")
mustWriteFile(t, filepath.Join(tmpDir, "foo"), "1_foobar.up.sql", "test")

logger, _ := test.NewNullLogger()
f := &File{}
Expand Down Expand Up @@ -140,8 +152,8 @@ func TestOpenWithDuplicateVersion(t *testing.T) {
}
defer os.RemoveAll(tmpDir)

mustWriteFile(t, tmpDir, "1_foo.up.sql", "") // 1 up
mustWriteFile(t, tmpDir, "1_bar.up.sql", "") // 1 up
mustWriteFile(t, tmpDir, "1_foo.up.sql", "test") // 1 up
mustWriteFile(t, tmpDir, "1_bar.up.sql", "test") // 1 up

logger, _ := test.NewNullLogger()
f := &File{}
Expand Down
25 changes: 24 additions & 1 deletion cli/migrate/source/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package source
import (
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"regexp"
"strconv"

yaml "github.com/ghodss/yaml"
)

var (
Expand All @@ -22,7 +26,7 @@ var (
var Regex = regexp.MustCompile(`^([0-9]+)_(.*)\.(` + string(Down) + `|` + string(Up) + `)\.(.*)$`)

// Parse returns Migration for matching Regex pattern.
func Parse(raw string) (*Migration, error) {
func Parse(raw string, directory string) (*Migration, error) {
var direction Direction
m := Regex.FindStringSubmatch(raw)
if len(m) == 5 {
Expand All @@ -40,6 +44,18 @@ func Parse(raw string) (*Migration, error) {
} else {
return nil, errors.New("Invalid Direction type")
}
data, err := ioutil.ReadFile(filepath.Join(directory, raw))
if err != nil {
return nil, err
}
var t []interface{}
err = yaml.Unmarshal(data, &t)
if err != nil {
return nil, err
}
if len(t) == 0 {
return nil, errors.New("Empty metadata file")
}
} else if m[4] == "sql" {
if m[3] == "up" {
direction = Up
Expand All @@ -48,6 +64,13 @@ func Parse(raw string) (*Migration, error) {
} else {
return nil, errors.New("Invalid Direction type")
}
data, err := ioutil.ReadFile(filepath.Join(directory, raw))
if err != nil {
return nil, err
}
if string(data[:]) == "" {
return nil, errors.New("Empty SQL file")
}
}

return &Migration{
Expand Down
Loading