github.hscsec.cn/amacneil/dbmate@v1.4.1/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "net/url" 7 "os" 8 9 "github.com/amacneil/dbmate/pkg/dbmate" 10 "github.com/joho/godotenv" 11 "github.com/urfave/cli" 12 ) 13 14 func main() { 15 loadDotEnv() 16 17 app := NewApp() 18 err := app.Run(os.Args) 19 if err != nil { 20 _, _ = fmt.Fprintf(os.Stderr, "Error: %s\n", err) 21 os.Exit(1) 22 } 23 } 24 25 // NewApp creates a new command line app 26 func NewApp() *cli.App { 27 app := cli.NewApp() 28 app.Name = "dbmate" 29 app.Usage = "A lightweight, framework-independent database migration tool." 30 app.Version = dbmate.Version 31 32 app.Flags = []cli.Flag{ 33 cli.StringFlag{ 34 Name: "env, e", 35 Value: "DATABASE_URL", 36 Usage: "specify an environment variable containing the database URL", 37 }, 38 cli.StringFlag{ 39 Name: "migrations-dir, d", 40 Value: dbmate.DefaultMigrationsDir, 41 Usage: "specify the directory containing migration files", 42 }, 43 cli.StringFlag{ 44 Name: "schema-file, s", 45 Value: dbmate.DefaultSchemaFile, 46 Usage: "specify the schema file location", 47 }, 48 cli.BoolFlag{ 49 Name: "no-dump-schema", 50 Usage: "don't update the schema file on migrate/rollback", 51 }, 52 } 53 54 app.Commands = []cli.Command{ 55 { 56 Name: "new", 57 Aliases: []string{"n"}, 58 Usage: "Generate a new migration file", 59 Action: action(func(db *dbmate.DB, c *cli.Context) error { 60 name := c.Args().First() 61 return db.NewMigration(name) 62 }), 63 }, 64 { 65 Name: "up", 66 Usage: "Create database (if necessary) and migrate to the latest version", 67 Action: action(func(db *dbmate.DB, c *cli.Context) error { 68 return db.CreateAndMigrate() 69 }), 70 }, 71 { 72 Name: "create", 73 Usage: "Create database", 74 Action: action(func(db *dbmate.DB, c *cli.Context) error { 75 return db.Create() 76 }), 77 }, 78 { 79 Name: "drop", 80 Usage: "Drop database (if it exists)", 81 Action: action(func(db *dbmate.DB, c *cli.Context) error { 82 return db.Drop() 83 }), 84 }, 85 { 86 Name: "migrate", 87 Usage: "Migrate to the latest version", 88 Action: action(func(db *dbmate.DB, c *cli.Context) error { 89 return db.Migrate() 90 }), 91 }, 92 { 93 Name: "rollback", 94 Aliases: []string{"down"}, 95 Usage: "Rollback the most recent migration", 96 Action: action(func(db *dbmate.DB, c *cli.Context) error { 97 return db.Rollback() 98 }), 99 }, 100 { 101 Name: "dump", 102 Usage: "Write the database schema to disk", 103 Action: action(func(db *dbmate.DB, c *cli.Context) error { 104 return db.DumpSchema() 105 }), 106 }, 107 { 108 Name: "wait", 109 Usage: "Wait for the database to become available", 110 Action: action(func(db *dbmate.DB, c *cli.Context) error { 111 return db.Wait() 112 }), 113 }, 114 } 115 116 return app 117 } 118 119 // load environment variables from .env file 120 func loadDotEnv() { 121 if _, err := os.Stat(".env"); err != nil { 122 return 123 } 124 125 if err := godotenv.Load(); err != nil { 126 log.Fatal("Error loading .env file") 127 } 128 } 129 130 // action wraps a cli.ActionFunc with dbmate initialization logic 131 func action(f func(*dbmate.DB, *cli.Context) error) cli.ActionFunc { 132 return func(c *cli.Context) error { 133 u, err := getDatabaseURL(c) 134 if err != nil { 135 return err 136 } 137 db := dbmate.New(u) 138 db.AutoDumpSchema = !c.GlobalBool("no-dump-schema") 139 db.MigrationsDir = c.GlobalString("migrations-dir") 140 db.SchemaFile = c.GlobalString("schema-file") 141 142 return f(db, c) 143 } 144 } 145 146 // getDatabaseURL returns the current environment database url 147 func getDatabaseURL(c *cli.Context) (u *url.URL, err error) { 148 env := c.GlobalString("env") 149 value := os.Getenv(env) 150 151 return url.Parse(value) 152 }