From 54b74adb8415cd970cf5484cff6a7191400b1362 Mon Sep 17 00:00:00 2001 From: Greg Weber <1183+gregwebs@users.noreply.github.com> Date: Thu, 20 Apr 2023 06:47:34 -0500 Subject: [PATCH 1/2] specify just a single migration to use --- README.md | 1 + main.go | 7 +++++++ pkg/dbmate/db.go | 16 ++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/README.md b/README.md index c86a48ae..5d29b155 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 single migration specified _(env: `DBMATE_MIGRATION`)_ - `--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 6576384f..95268e82 100644 --- a/main.go +++ b/main.go @@ -49,6 +49,12 @@ func NewApp() *cli.App { Value: "DATABASE_URL", Usage: "specify an environment variable containing the database URL", }, + &cli.StringFlag{ + Name: "migration", + Aliases: []string{"m"}, + EnvVars: []string{"DBMATE_MIGRATION"}, + Usage: "specify one specific migration to use", + }, &cli.StringFlag{ Name: "migrations-dir", Aliases: []string{"d"}, @@ -231,6 +237,7 @@ func action(f func(*dbmate.DB, *cli.Context) error) cli.ActionFunc { } db := dbmate.New(u) db.AutoDumpSchema = !c.Bool("no-dump-schema") + db.Migration = c.String("migration") db.MigrationsDir = c.String("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 fc404d6b..29d92f02 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 a specific migration to look at + Migration string // MigrationsDir specifies the directory 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, + Migration: "", MigrationsDir: "./db/migrations", MigrationsTableName: "schema_migrations", SchemaFile: "./db/schema.sql", @@ -418,6 +421,7 @@ func (db *DB) FindMigrations() ([]Migration, error) { return nil, fmt.Errorf("%w `%s`", ErrMigrationDirNotFound, db.MigrationsDir) } + found := false migrations := []Migration{} for _, file := range files { if file.IsDir() { @@ -436,6 +440,14 @@ func (db *DB) FindMigrations() ([]Migration, error) { FS: db.FS, Version: matches[1], } + + if db.Migration != "" { + if db.Migration != migration.Version && db.Migration != migration.FileName { + continue + } + found = true + } + if ok := appliedMigrations[migration.Version]; ok { migration.Applied = true } @@ -443,6 +455,10 @@ func (db *DB) FindMigrations() ([]Migration, error) { migrations = append(migrations, migration) } + if !found && db.Migration != "" { + return nil, fmt.Errorf("%w `%s`", ErrMigrationNotFound, db.Migration) + } + sort.Slice(migrations, func(i, j int) bool { return migrations[i].FileName < migrations[j].FileName }) From dad7559465c7cbe8f8bfc70fa0a8200ca606b4b1 Mon Sep 17 00:00:00 2001 From: Greg Weber Date: Fri, 21 Apr 2023 16:35:12 -0500 Subject: [PATCH 2/2] specify multiple migrations at once --- README.md | 2 +- main.go | 11 ++++++----- pkg/dbmate/db.go | 25 ++++++++++++++++--------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 5d29b155..73ba2cbe 100644 --- a/README.md +++ b/README.md @@ -138,7 +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 single migration specified _(env: `DBMATE_MIGRATION`)_ +- `--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 f54cd679..fa870b70 100644 --- a/main.go +++ b/main.go @@ -49,11 +49,12 @@ func NewApp() *cli.App { Value: "DATABASE_URL", Usage: "specify an environment variable containing the database URL", }, - &cli.StringFlag{ - Name: "migration", + &cli.StringSliceFlag{ + Name: "migrations", Aliases: []string{"m"}, - EnvVars: []string{"DBMATE_MIGRATION"}, - Usage: "specify one specific migration to use", + EnvVars: []string{"DBMATE_MIGRATIONS"}, + Value: cli.NewStringSlice(), + Usage: "specify one or more specific migration to use", }, &cli.StringSliceFlag{ Name: "migrations-dir", @@ -237,7 +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.Migration = c.String("migration") + 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 bafad197..c1a1fcf8 100644 --- a/pkg/dbmate/db.go +++ b/pkg/dbmate/db.go @@ -43,8 +43,8 @@ type DB struct { FS fs.FS // Log is the interface to write stdout Log io.Writer - // Migration specifies a specific migration to look at - Migration string + // 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 @@ -74,7 +74,7 @@ func New(databaseURL *url.URL) *DB { DatabaseURL: databaseURL, FS: nil, Log: os.Stdout, - Migration: "", + Migrations: []string{}, MigrationsDir: []string{"./db/migrations"}, MigrationsTableName: "schema_migrations", SchemaFile: "./db/schema.sql", @@ -415,7 +415,7 @@ func (db *DB) FindMigrations() ([]Migration, error) { } } - found := false + givenMigrations := db.Migrations migrations := []Migration{} for _, dir := range db.MigrationsDir { // find filesystem migrations @@ -442,11 +442,18 @@ func (db *DB) FindMigrations() ([]Migration, error) { Version: matches[1], } - if db.Migration != "" { - if db.Migration != migration.Version && db.Migration != migration.FileName { + 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 } - found = true } if ok := appliedMigrations[migration.Version]; ok { @@ -457,8 +464,8 @@ func (db *DB) FindMigrations() ([]Migration, error) { } } - if !found && db.Migration != "" { - return nil, fmt.Errorf("%w `%s`", ErrMigrationNotFound, db.Migration) + if len(givenMigrations) > 0 { + return nil, fmt.Errorf("%w `%v`", ErrMigrationNotFound, givenMigrations) } sort.Slice(migrations, func(i, j int) bool {