Skip to content
Open
Show file tree
Hide file tree
Changes from 17 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
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,15 @@ dbmate up # create the database (if it does not already exist) and run an
dbmate create # create the database
dbmate drop # drop the database
dbmate migrate # run any pending migrations
dbmate rollback # roll back the most recent migration
--only <version> # apply only the specified migration version
--to <version> # apply migrations up to the specified version (inclusive)
--one # apply exactly one pending migration
--all # apply all pending migrations (default)
dbmate rollback # rollback migrations
--only <version> # rollback only the specified migration version
--to <version> # rollback migrations down to the specified version (exclusive)
--one # rollback exactly one migration (default)
--all # rollback all migrations
dbmate down # alias for rollback
dbmate status # show the status of all migrations (supports --exit-code and --quiet)
dbmate dump # write the database schema.sql file
Expand Down Expand Up @@ -632,3 +640,4 @@ To start a development shell:
```sh
$ make docker-sh
```

85 changes: 83 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,22 @@ func NewApp() *cli.App {
Name: "migrate",
Usage: "Migrate to the latest version",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "only",
Usage: "apply only the specified migration version",
},
&cli.StringFlag{
Name: "to",
Usage: "apply migrations up to specified version (inclusive)",
},
&cli.BoolFlag{
Name: "one",
Usage: "apply exactly one pending migration",
},
&cli.BoolFlag{
Name: "all",
Usage: "apply all pending migrations (default)",
},
&cli.BoolFlag{
Name: "strict",
EnvVars: []string{"DBMATE_STRICT"},
Expand All @@ -163,14 +179,44 @@ func NewApp() *cli.App {
Action: action(func(db *dbmate.DB, c *cli.Context) error {
db.Strict = c.Bool("strict")
db.Verbose = c.Bool("verbose")
return db.Migrate()
if err := validateMigrationFlags(c); err != nil {
return err
}
if version := c.String("only"); version != "" {
migrations, err := db.FindMigrations()
if err != nil {
return err
}
return db.MigrateOnly(migrations, version)
} else if version := c.String("to"); version != "" {
return db.MigrateTo(version)
} else if c.Bool("one") {
return db.MigrateNext()
}
return db.Migrate() // default: apply all
}),
},
{
Name: "rollback",
Aliases: []string{"down"},
Usage: "Rollback the most recent migration",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "only",
Usage: "rollback only the specified migration version",
},
&cli.StringFlag{
Name: "to",
Usage: "rollback migrations down to specified version (exclusive)",
},
&cli.BoolFlag{
Name: "one",
Usage: "rollback exactly one migration (default)",
},
&cli.BoolFlag{
Name: "all",
Usage: "rollback all migrations",
},
&cli.BoolFlag{
Name: "verbose",
Aliases: []string{"v"},
Expand All @@ -180,7 +226,21 @@ func NewApp() *cli.App {
},
Action: action(func(db *dbmate.DB, c *cli.Context) error {
db.Verbose = c.Bool("verbose")
return db.Rollback()
if err := validateMigrationFlags(c); err != nil {
return err
}
if version := c.String("only"); version != "" {
migrations, err := db.FindMigrations()
if err != nil {
return err
}
return db.RollbackOnly(migrations, version)
} else if version := c.String("to"); version != "" {
return db.RollbackTo(version)
} else if c.Bool("all") {
return db.RollbackAll()
}
return db.Rollback() // default: rollback one migration
}),
},
{
Expand Down Expand Up @@ -242,6 +302,27 @@ func NewApp() *cli.App {
return app
}

// validateMigrationFlags checks that only one of the migration flags is set
func validateMigrationFlags(c *cli.Context) error {
flagsSet := 0
if c.String("only") != "" {
flagsSet++
}
if c.String("to") != "" {
flagsSet++
}
if c.Bool("one") {
flagsSet++
}
if c.Bool("all") {
flagsSet++
}
if flagsSet > 1 {
return errors.New("only one of --only, --to, --one, or --all can be specified at a time")
}
return nil
}

// load environment variables from file(s)
func loadEnvFiles(args []string) error {
var envFiles []string
Expand Down
Loading
Loading