gci is configured with the sections standard, default and localmodule, and goimports with the module path as its local prefix, so both formatters agree.
96 lines
2.3 KiB
Go
96 lines
2.3 KiB
Go
package migrate
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"log/slog"
|
|
"path/filepath"
|
|
"text/tabwriter"
|
|
|
|
"github.com/pressly/goose/v3"
|
|
"github.com/spf13/cobra"
|
|
|
|
"git.avsdev.uk/Go/job-search/internal/cli"
|
|
"git.avsdev.uk/Go/job-search/internal/store"
|
|
)
|
|
|
|
// printStatus lists every migration as applied (with when) or pending,
|
|
// after a summary line, e.g.
|
|
//
|
|
// Database version 4 of 6 (2 pending)
|
|
// 1 applied 2026-10-07 10:12:01 00001_create_opportunities_table.sql
|
|
// ...
|
|
// 5 pending 00005_create_opportunity_classifications_table.sql
|
|
func printStatus(ctx context.Context, w io.Writer, m *goose.Provider) error {
|
|
statuses, err := m.Status(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
current, err := m.GetDBVersion(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
latest := store.LatestVersion(m)
|
|
|
|
pending := 0
|
|
for _, s := range statuses {
|
|
if s.State == goose.StatePending {
|
|
pending++
|
|
}
|
|
}
|
|
|
|
ew := &errWriter{w: w}
|
|
switch {
|
|
case current > latest:
|
|
ew.printf("Database version %d is newer than this build (latest %d)\n",
|
|
current, latest)
|
|
case pending == 0:
|
|
ew.printf("Database version %d of %d (up-to-date)\n", current, latest)
|
|
default:
|
|
ew.printf("Database version %d of %d (%d pending)\n", current, latest, pending)
|
|
}
|
|
if ew.err != nil {
|
|
return ew.err
|
|
}
|
|
|
|
tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
|
|
ew = &errWriter{w: tw}
|
|
for _, s := range statuses {
|
|
applied := ""
|
|
if s.State == goose.StateApplied {
|
|
applied = s.AppliedAt.Local().Format("2006-01-02 15:04:05")
|
|
}
|
|
ew.printf(" %d\t%s\t%s\t%s\n",
|
|
s.Source.Version, s.State, applied, filepath.Base(s.Source.Path))
|
|
}
|
|
return errors.Join(ew.err, tw.Flush())
|
|
}
|
|
|
|
func commandStatus(opts *cli.Options) *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "status",
|
|
Short: "Show which migrations have been applied to the SQLite database",
|
|
Args: cobra.NoArgs,
|
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
slog.Debug("migrate.status.PersistentPreRun")
|
|
},
|
|
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
|
slog.Debug("migrate.status.PersistentPostRun")
|
|
},
|
|
RunE: func(cmd *cobra.Command, args []string) (err error) {
|
|
slog.Debug("migrate.status.Run")
|
|
|
|
m, db, err := openMigrator(cmd, opts, false, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closeDB(db, &err)
|
|
|
|
return printStatus(cmd.Context(), cmd.OutOrStdout(), m)
|
|
},
|
|
}
|
|
}
|