diff --git a/README.md b/README.md index c86a48ae..73ba2cbe 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,7 @@ The following options are available with all commands. You must use command line - `--url, -u "protocol://host:port/dbname"` - specify the database url directly. _(env: `DATABASE_URL`)_ - `--env, -e "DATABASE_URL"` - specify an environment variable to read the database connection URL from. +- `--migrations, -m "VERSION"` - operate on only the migrations specified. _(env: `DBMATE_MIGRATIONS`)_ - `--migrations-dir, -d "./db/migrations"` - where to keep the migration files. _(env: `DBMATE_MIGRATIONS_DIR`)_ - `--migrations-table "schema_migrations"` - database table to record migrations in. _(env: `DBMATE_MIGRATIONS_TABLE`)_ - `--schema-file, -s "./db/schema.sql"` - a path to keep the schema.sql file. _(env: `DBMATE_SCHEMA_FILE`)_ diff --git a/main.go b/main.go index 83b85bf8..fa870b70 100644 --- a/main.go +++ b/main.go @@ -49,6 +49,13 @@ func NewApp() *cli.App { Value: "DATABASE_URL", Usage: "specify an environment variable containing the database URL", }, + &cli.StringSliceFlag{ + Name: "migrations", + Aliases: []string{"m"}, + EnvVars: []string{"DBMATE_MIGRATIONS"}, + Value: cli.NewStringSlice(), + Usage: "specify one or more specific migration to use", + }, &cli.StringSliceFlag{ Name: "migrations-dir", Aliases: []string{"d"}, @@ -231,6 +238,7 @@ func action(f func(*dbmate.DB, *cli.Context) error) cli.ActionFunc { } db := dbmate.New(u) db.AutoDumpSchema = !c.Bool("no-dump-schema") + db.Migrations = c.StringSlice("migrations") db.MigrationsDir = c.StringSlice("migrations-dir") db.MigrationsTableName = c.String("migrations-table") db.SchemaFile = c.String("schema-file") diff --git a/pkg/dbmate/db.go b/pkg/dbmate/db.go index ae598ffd..c1a1fcf8 100644 --- a/pkg/dbmate/db.go +++ b/pkg/dbmate/db.go @@ -43,6 +43,8 @@ type DB struct { FS fs.FS // Log is the interface to write stdout Log io.Writer + // Migration specifies one or more specific migrations to look at + Migrations []string // MigrationsDir specifies the directory or directories to find migration files MigrationsDir []string // MigrationsTableName specifies the database table to record migrations in @@ -72,6 +74,7 @@ func New(databaseURL *url.URL) *DB { DatabaseURL: databaseURL, FS: nil, Log: os.Stdout, + Migrations: []string{}, MigrationsDir: []string{"./db/migrations"}, MigrationsTableName: "schema_migrations", SchemaFile: "./db/schema.sql", @@ -412,6 +415,7 @@ func (db *DB) FindMigrations() ([]Migration, error) { } } + givenMigrations := db.Migrations migrations := []Migration{} for _, dir := range db.MigrationsDir { // find filesystem migrations @@ -437,6 +441,21 @@ func (db *DB) FindMigrations() ([]Migration, error) { FS: db.FS, Version: matches[1], } + + if len(db.Migrations) > 0 { + found := false + for i, given := range givenMigrations { + if given == migration.Version || given == migration.FileName { + givenMigrations = append(givenMigrations[:i], givenMigrations[i+1:]...) + found = true + break + } + } + if !found { + continue + } + } + if ok := appliedMigrations[migration.Version]; ok { migration.Applied = true } @@ -445,6 +464,10 @@ func (db *DB) FindMigrations() ([]Migration, error) { } } + if len(givenMigrations) > 0 { + return nil, fmt.Errorf("%w `%v`", ErrMigrationNotFound, givenMigrations) + } + sort.Slice(migrations, func(i, j int) bool { return migrations[i].FileName < migrations[j].FileName })