github.com/svrana/migrate@v3.5.4+incompatible/cli/commands.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/golang-migrate/migrate"
     7  	_ "github.com/golang-migrate/migrate/database/stub" // TODO remove again
     8  	_ "github.com/golang-migrate/migrate/source/file"
     9  	"os"
    10  	"path/filepath"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  )
    15  
    16  func nextSeq(matches []string, dir string, seqDigits int) (string, error) {
    17  	if seqDigits <= 0 {
    18  		return "", errors.New("Digits must be positive")
    19  	}
    20  
    21  	nextSeq := 1
    22  	if len(matches) > 0 {
    23  		filename := matches[len(matches)-1]
    24  		matchSeqStr := strings.TrimPrefix(filename, dir)
    25  		idx := strings.Index(matchSeqStr, "_")
    26  		if idx < 1 { // Using 1 instead of 0 since there should be at least 1 digit
    27  			return "", errors.New("Malformed migration filename: " + filename)
    28  		}
    29  		matchSeqStr = matchSeqStr[0:idx]
    30  		var err error
    31  		nextSeq, err = strconv.Atoi(matchSeqStr)
    32  		if err != nil {
    33  			return "", err
    34  		}
    35  		nextSeq++
    36  	}
    37  	if nextSeq <= 0 {
    38  		return "", errors.New("Next sequence number must be positive")
    39  	}
    40  
    41  	nextSeqStr := strconv.Itoa(nextSeq)
    42  	if len(nextSeqStr) > seqDigits {
    43  		return "", fmt.Errorf("Next sequence number %s too large. At most %d digits are allowed", nextSeqStr, seqDigits)
    44  	}
    45  	padding := seqDigits - len(nextSeqStr)
    46  	if padding > 0 {
    47  		nextSeqStr = strings.Repeat("0", padding) + nextSeqStr
    48  	}
    49  	return nextSeqStr, nil
    50  }
    51  
    52  func createCmd(dir string, startTime time.Time, format string, name string, ext string, seq bool, seqDigits int) {
    53  	var base string
    54  	if seq && format != defaultTimeFormat {
    55  		log.fatalErr(errors.New("The seq and format options are mutually exclusive"))
    56  	}
    57  	if seq {
    58  		if seqDigits <= 0 {
    59  			log.fatalErr(errors.New("Digits must be positive"))
    60  		}
    61  		matches, err := filepath.Glob(dir + "*" + ext)
    62  		if err != nil {
    63  			log.fatalErr(err)
    64  		}
    65  		nextSeqStr, err := nextSeq(matches, dir, seqDigits)
    66  		if err != nil {
    67  			log.fatalErr(err)
    68  		}
    69  		base = fmt.Sprintf("%v%v_%v.", dir, nextSeqStr, name)
    70  	} else {
    71  		switch format {
    72  		case "":
    73  			log.fatal("Time format may not be empty")
    74  		case "unix":
    75  			base = fmt.Sprintf("%v%v_%v.", dir, startTime.Unix(), name)
    76  		case "unixNano":
    77  			base = fmt.Sprintf("%v%v_%v.", dir, startTime.UnixNano(), name)
    78  		default:
    79  			base = fmt.Sprintf("%v%v_%v.", dir, startTime.Format(format), name)
    80  		}
    81  	}
    82  
    83  	os.MkdirAll(dir, os.ModePerm)
    84  	createFile(base + "up" + ext)
    85  	createFile(base + "down" + ext)
    86  }
    87  
    88  func createFile(fname string) {
    89  	if _, err := os.Create(fname); err != nil {
    90  		log.fatalErr(err)
    91  	}
    92  }
    93  
    94  func gotoCmd(m *migrate.Migrate, v uint) {
    95  	if err := m.Migrate(v); err != nil {
    96  		if err != migrate.ErrNoChange {
    97  			log.fatalErr(err)
    98  		} else {
    99  			log.Println(err)
   100  		}
   101  	}
   102  }
   103  
   104  func upCmd(m *migrate.Migrate, limit int) {
   105  	if limit >= 0 {
   106  		if err := m.Steps(limit); err != nil {
   107  			if err != migrate.ErrNoChange {
   108  				log.fatalErr(err)
   109  			} else {
   110  				log.Println(err)
   111  			}
   112  		}
   113  	} else {
   114  		if err := m.Up(); err != nil {
   115  			if err != migrate.ErrNoChange {
   116  				log.fatalErr(err)
   117  			} else {
   118  				log.Println(err)
   119  			}
   120  		}
   121  	}
   122  }
   123  
   124  func downCmd(m *migrate.Migrate, limit int) {
   125  	if limit >= 0 {
   126  		if err := m.Steps(-limit); err != nil {
   127  			if err != migrate.ErrNoChange {
   128  				log.fatalErr(err)
   129  			} else {
   130  				log.Println(err)
   131  			}
   132  		}
   133  	} else {
   134  		if err := m.Down(); err != nil {
   135  			if err != migrate.ErrNoChange {
   136  				log.fatalErr(err)
   137  			} else {
   138  				log.Println(err)
   139  			}
   140  		}
   141  	}
   142  }
   143  
   144  func dropCmd(m *migrate.Migrate) {
   145  	if err := m.Drop(); err != nil {
   146  		log.fatalErr(err)
   147  	}
   148  }
   149  
   150  func forceCmd(m *migrate.Migrate, v int) {
   151  	if err := m.Force(v); err != nil {
   152  		log.fatalErr(err)
   153  	}
   154  }
   155  
   156  func versionCmd(m *migrate.Migrate) {
   157  	v, dirty, err := m.Version()
   158  	if err != nil {
   159  		log.fatalErr(err)
   160  	}
   161  	if dirty {
   162  		log.Printf("%v (dirty)\n", v)
   163  	} else {
   164  		log.Println(v)
   165  	}
   166  }