diff --git a/conduitcli/cli.go b/conduitcli/cli.go index f1a90bf..8b11420 100644 --- a/conduitcli/cli.go +++ b/conduitcli/cli.go @@ -7,9 +7,9 @@ import ( "github.com/urfave/cli/v2" "go.inout.gg/conduit" "go.inout.gg/conduit/internal/command/apply" + "go.inout.gg/conduit/internal/command/common" "go.inout.gg/conduit/internal/command/create" "go.inout.gg/conduit/internal/command/initialise" - "go.inout.gg/conduit/internal/command/common" ) // Execute evaluates given os.Args and executes a matched command. diff --git a/conduitregistry/migration.go b/conduitregistry/migration.go index 5a4e230..65eb0b6 100644 --- a/conduitregistry/migration.go +++ b/conduitregistry/migration.go @@ -37,7 +37,7 @@ func (m *Migration) UseTx(dir direction.Direction) (bool, error) { return m.down.inTx, nil } - return false, direction.UnknownDirectionErr + return false, direction.ErrUnknownDirection } // Version returns the version of this migration. @@ -57,7 +57,7 @@ func (m *Migration) Apply(ctx context.Context, dir direction.Direction, conn *pg return m.migrateDown(ctx, conn, tx) } - return direction.UnknownDirectionErr + return direction.ErrUnknownDirection } func (m *Migration) migrateDown(ctx context.Context, conn *pgx.Conn, tx pgx.Tx) error { diff --git a/conduitregistry/registry.go b/conduitregistry/registry.go index 3825c21..2217a94 100644 --- a/conduitregistry/registry.go +++ b/conduitregistry/registry.go @@ -1,22 +1,22 @@ package conduitregistry import ( - "context" - "errors" - "io/fs" - "maps" - "runtime" - - "github.com/jackc/pgx/v5" - "go.inout.gg/conduit/internal/version" - "go.inout.gg/foundations/must" + "context" + "errors" + "io/fs" + "maps" + "runtime" + + "github.com/jackc/pgx/v5" + "go.inout.gg/conduit/internal/version" + "go.inout.gg/foundations/must" ) var ( - UndefinedTxErr = errors.New("conduit: tx must be defined") - EmptyMigrationErr = errors.New("conduit: migration is empty") - UpExistsErr = errors.New("conduit: up migration already registered") - DownExistsErr = errors.New("conduit: down migration already registered") + UndefinedTxErr = errors.New("conduit: tx must be defined") + EmptyMigrationErr = errors.New("conduit: migration is empty") + UpExistsErr = errors.New("conduit: up migration already registered") + DownExistsErr = errors.New("conduit: down migration already registered") ) // MigrateFunc applies an up or down migration. @@ -27,16 +27,16 @@ type MigrateFuncTx func(context.Context, pgx.Tx) error // Registry stores migration files, both SQL and Go-sourced. type Registry struct { - Namespace string - migrations map[int64]*Migration + Namespace string + migrations map[int64]*Migration } // New creates a new Registry with the given namespace. func New(namespace string) *Registry { - return &Registry{ - namespace, - make(map[int64]*Migration), - } + return &Registry{ + namespace, + make(map[int64]*Migration), + } } // FromFS loads SQL migration files from the given filesystem. @@ -46,76 +46,76 @@ func New(namespace string) *Registry { // This comment applies to the current migration section (up or down). // For down migrations, place the comment below the `---- create above / drop below ----` separator. func (r *Registry) FromFS(fsys fs.FS) { - migrations := must.Must(parseSQLMigrationsFromFS(fsys, ".")) - for _, m := range migrations { - r.migrations[m.Version()] = m - } + migrations := must.Must(parseSQLMigrationsFromFS(fsys, ".")) + for _, m := range migrations { + r.migrations[m.Version()] = m + } } // Up registers a Go function for up migration. func (r *Registry) Up(up MigrateFunc) { - m := must.Must(r.goMigration()) - if m.up != nil { - panic(UpExistsErr) - } - m.up = &migrateFunc{fn: up, inTx: false} + m := must.Must(r.goMigration()) + if m.up != nil { + panic(UpExistsErr) + } + m.up = &migrateFunc{fn: up, inTx: false} } // UpTx registers a Go function for up migration within a transaction. func (r *Registry) UpTx(up MigrateFuncTx) { - m := must.Must(r.goMigration()) - if m.up != nil { - panic(UpExistsErr) - } - m.up = &migrateFunc{fnx: up, inTx: true} + m := must.Must(r.goMigration()) + if m.up != nil { + panic(UpExistsErr) + } + m.up = &migrateFunc{fnx: up, inTx: true} } // Down registers a Go function for down migration. func (r *Registry) Down(down MigrateFunc) { - m := must.Must(r.goMigration()) - if m.down != nil { - panic(DownExistsErr) - } - m.down = &migrateFunc{fn: down, inTx: false} + m := must.Must(r.goMigration()) + if m.down != nil { + panic(DownExistsErr) + } + m.down = &migrateFunc{fn: down, inTx: false} } // DownTx registers a Go function for down migration within a transaction. func (r *Registry) DownTx(down MigrateFuncTx) { - m := must.Must(r.goMigration()) - if m.down != nil { - panic(DownExistsErr) - } - m.down = &migrateFunc{fnx: down, inTx: true} + m := must.Must(r.goMigration()) + if m.down != nil { + panic(DownExistsErr) + } + m.down = &migrateFunc{fnx: down, inTx: true} } // goMigration creates a new Migration from a Go registration function. func (r *Registry) goMigration() (*Migration, error) { - _, filename, _, ok := runtime.Caller(2) - if !ok { - return nil, errors.New("conduit: failed to retrieve caller information") - } - - info, err := version.ParseMigrationFilename(filename) - if err != nil { - return nil, err - } - - if val, ok := r.migrations[info.Version]; ok { - return val, nil - } - - migration := &Migration{ - version: info.Version, - name: info.Name, - up: nil, - down: nil, - } - r.migrations[migration.version] = migration - - return migration, nil + _, filename, _, ok := runtime.Caller(2) + if !ok { + return nil, errors.New("conduit: failed to retrieve caller information") + } + + info, err := version.ParseMigrationFilename(filename) + if err != nil { + return nil, err + } + + if val, ok := r.migrations[info.Version]; ok { + return val, nil + } + + migration := &Migration{ + version: info.Version, + name: info.Name, + up: nil, + down: nil, + } + r.migrations[migration.version] = migration + + return migration, nil } -// Migrations returns a copy of the registered migrations map. -func (r *Registry) Migrations() map[int64]*Migration { - return maps.Clone(r.migrations) -} \ No newline at end of file +// CloneMigrations returns a copy of the registered migrations map. +func (r *Registry) CloneMigrations() map[int64]*Migration { + return maps.Clone(r.migrations) +} diff --git a/internal/command/common/common.go b/internal/command/common/common.go index c5c1957..053450b 100644 --- a/internal/command/common/common.go +++ b/internal/command/common/common.go @@ -8,8 +8,8 @@ import ( ) var ( - databaseUrlFlagName = "database-url" - migrationsDirFlagName = "dir" + databaseUrlFlagName = "database-url" + migrationsDirFlagName = "dir" ) var DatabaseURLFlag = &cli.StringFlag{ diff --git a/internal/direction/direction.go b/internal/direction/direction.go index d7d8d22..40784e8 100644 --- a/internal/direction/direction.go +++ b/internal/direction/direction.go @@ -12,7 +12,7 @@ const ( DirectionDown Direction = "down" // rolling back ) -var UnknownDirectionErr = errors.New("conduit: unknown direction") +var ErrUnknownDirection = errors.New("conduit: unknown direction") // FromString converts a string to a Direction. It returns UnknownDirectionErr for invalid inputs. func FromString(s string) (Direction, error) { @@ -23,5 +23,5 @@ func FromString(s string) (Direction, error) { return DirectionDown, nil } - return "", UnknownDirectionErr + return "", ErrUnknownDirection } diff --git a/internal/version/version.go b/internal/version/version.go index 3a9b439..a956104 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -61,4 +61,4 @@ func parseVersionString(version string) (int64, error) { } return numericVersion, nil -} \ No newline at end of file +} diff --git a/migrator.go b/migrator.go index eebcf8b..3d8c27e 100644 --- a/migrator.go +++ b/migrator.go @@ -35,7 +35,7 @@ const ( DirectionDown = direction.DirectionDown ) -var InvalidStepErr = errors.New( +var ErrInvalidStep = errors.New( "conduit: invalid migration step. Expected: -1 (all) or positive integer.", ) @@ -119,7 +119,7 @@ type MigrateOptions struct { func (m *MigrateOptions) validate() error { if !(m.Steps == -1 || m.Steps > 0) { - return InvalidStepErr + return ErrInvalidStep } return nil @@ -205,7 +205,7 @@ func (m *migrator) Migrate( case DirectionDown: result, err = m.migrateDown(ctx, conn, opts) default: - return nil, direction.UnknownDirectionErr + return nil, direction.ErrUnknownDirection } if err != nil { return nil, err @@ -227,7 +227,7 @@ func (m *migrator) migrateUp( return nil, err } - targetMigrations := m.registry.Migrations() + targetMigrations := m.registry.CloneMigrations() for _, existingVersion := range existingMigrationVersions { delete(targetMigrations, existingVersion) } @@ -254,7 +254,7 @@ func (m *migrator) migrateDown( // Filter only applied migrations. existingMigrationsMap := sliceutil.KeyBy(existingMigrations, func(e int64) int64 { return e }) - targetMigrations := m.registry.Migrations() + targetMigrations := m.registry.CloneMigrations() for _, m := range targetMigrations { if _, ok := existingMigrationsMap[m.Version()]; !ok { delete(targetMigrations, m.Version()) diff --git a/migrator_test.go b/migrator_test.go new file mode 100644 index 0000000..5f747d6 --- /dev/null +++ b/migrator_test.go @@ -0,0 +1 @@ +package conduit_test