github.com/yuukihogo/migrate@v3.0.0+incompatible/cli/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"os/signal"
     8  	"strconv"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/mattes/migrate"
    13  )
    14  
    15  // set main log
    16  var log = &Log{}
    17  
    18  func main() {
    19  	helpPtr := flag.Bool("help", false, "")
    20  	versionPtr := flag.Bool("version", false, "")
    21  	verbosePtr := flag.Bool("verbose", false, "")
    22  	prefetchPtr := flag.Uint("prefetch", 10, "")
    23  	lockTimeoutPtr := flag.Uint("lock-timeout", 15, "")
    24  	pathPtr := flag.String("path", "", "")
    25  	databasePtr := flag.String("database", "", "")
    26  	sourcePtr := flag.String("source", "", "")
    27  
    28  	flag.Usage = func() {
    29  		fmt.Fprint(os.Stderr,
    30  			`Usage: migrate OPTIONS COMMAND [arg...]
    31         migrate [ -version | -help ]
    32  
    33  Options:
    34    -source          Location of the migrations (driver://url)
    35    -path            Shorthand for -source=file://path 
    36    -database        Run migrations against this database (driver://url)
    37    -prefetch N      Number of migrations to load in advance before executing (default 10)
    38    -lock-timeout N  Allow N seconds to acquire database lock (default 15)
    39    -verbose         Print verbose logging
    40    -version         Print version
    41    -help            Print usage
    42  
    43  Commands:
    44    goto V       Migrate to version V
    45    up [N]       Apply all or N up migrations
    46    down [N]     Apply all or N down migrations
    47    drop         Drop everyting inside database
    48    force V      Set version V but don't run migration (ignores dirty state)
    49    version      Print current migration version
    50  `)
    51  	}
    52  
    53  	flag.Parse()
    54  
    55  	// initialize logger
    56  	log.verbose = *verbosePtr
    57  
    58  	// show cli version
    59  	if *versionPtr {
    60  		fmt.Fprintln(os.Stderr, Version)
    61  		os.Exit(0)
    62  	}
    63  
    64  	// show help
    65  	if *helpPtr {
    66  		flag.Usage()
    67  		os.Exit(0)
    68  	}
    69  
    70  	// translate -path into -source if given
    71  	if *sourcePtr == "" && *pathPtr != "" {
    72  		*sourcePtr = fmt.Sprintf("file://%v", *pathPtr)
    73  	}
    74  
    75  	// initialize migrate
    76  	// don't catch migraterErr here and let each command decide
    77  	// how it wants to handle the error
    78  	migrater, migraterErr := migrate.New(*sourcePtr, *databasePtr)
    79  	defer func() {
    80  		if migraterErr == nil {
    81  			migrater.Close()
    82  		}
    83  	}()
    84  	if migraterErr == nil {
    85  		migrater.Log = log
    86  		migrater.PrefetchMigrations = *prefetchPtr
    87  		migrater.LockTimeout = time.Duration(int64(*lockTimeoutPtr)) * time.Second
    88  
    89  		// handle Ctrl+c
    90  		signals := make(chan os.Signal, 1)
    91  		signal.Notify(signals, syscall.SIGINT)
    92  		go func() {
    93  			for range signals {
    94  				log.Println("Stopping after this running migration ...")
    95  				migrater.GracefulStop <- true
    96  				return
    97  			}
    98  		}()
    99  	}
   100  
   101  	startTime := time.Now()
   102  
   103  	switch flag.Arg(0) {
   104  	case "goto":
   105  		if migraterErr != nil {
   106  			log.fatalErr(migraterErr)
   107  		}
   108  
   109  		if flag.Arg(1) == "" {
   110  			log.fatal("error: please specify version argument V")
   111  		}
   112  
   113  		v, err := strconv.ParseUint(flag.Arg(1), 10, 64)
   114  		if err != nil {
   115  			log.fatal("error: can't read version argument V")
   116  		}
   117  
   118  		gotoCmd(migrater, uint(v))
   119  
   120  		if log.verbose {
   121  			log.Println("Finished after", time.Now().Sub(startTime))
   122  		}
   123  
   124  	case "up":
   125  		if migraterErr != nil {
   126  			log.fatalErr(migraterErr)
   127  		}
   128  
   129  		limit := -1
   130  		if flag.Arg(1) != "" {
   131  			n, err := strconv.ParseUint(flag.Arg(1), 10, 64)
   132  			if err != nil {
   133  				log.fatal("error: can't read limit argument N")
   134  			}
   135  			limit = int(n)
   136  		}
   137  
   138  		upCmd(migrater, limit)
   139  
   140  		if log.verbose {
   141  			log.Println("Finished after", time.Now().Sub(startTime))
   142  		}
   143  
   144  	case "down":
   145  		if migraterErr != nil {
   146  			log.fatalErr(migraterErr)
   147  		}
   148  
   149  		limit := -1
   150  		if flag.Arg(1) != "" {
   151  			n, err := strconv.ParseUint(flag.Arg(1), 10, 64)
   152  			if err != nil {
   153  				log.fatal("error: can't read limit argument N")
   154  			}
   155  			limit = int(n)
   156  		}
   157  
   158  		downCmd(migrater, limit)
   159  
   160  		if log.verbose {
   161  			log.Println("Finished after", time.Now().Sub(startTime))
   162  		}
   163  
   164  	case "drop":
   165  		if migraterErr != nil {
   166  			log.fatalErr(migraterErr)
   167  		}
   168  
   169  		dropCmd(migrater)
   170  
   171  		if log.verbose {
   172  			log.Println("Finished after", time.Now().Sub(startTime))
   173  		}
   174  
   175  	case "force":
   176  		if migraterErr != nil {
   177  			log.fatalErr(migraterErr)
   178  		}
   179  
   180  		if flag.Arg(1) == "" {
   181  			log.fatal("error: please specify version argument V")
   182  		}
   183  
   184  		v, err := strconv.ParseInt(flag.Arg(1), 10, 64)
   185  		if err != nil {
   186  			log.fatal("error: can't read version argument V")
   187  		}
   188  
   189  		if v < -1 {
   190  			log.fatal("error: argument V must be >= -1")
   191  		}
   192  
   193  		forceCmd(migrater, int(v))
   194  
   195  		if log.verbose {
   196  			log.Println("Finished after", time.Now().Sub(startTime))
   197  		}
   198  
   199  	case "version":
   200  		if migraterErr != nil {
   201  			log.fatalErr(migraterErr)
   202  		}
   203  
   204  		versionCmd(migrater)
   205  
   206  	default:
   207  		flag.Usage()
   208  		os.Exit(0)
   209  	}
   210  }