106 lines
2.9 KiB
Go
106 lines
2.9 KiB
Go
package list
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
|
|
"github.com/charmbracelet/glamour"
|
|
"github.com/go-errors/errors"
|
|
"github.com/jackc/pgconn"
|
|
"github.com/jackc/pgx/v4"
|
|
"github.com/spf13/afero"
|
|
"github.com/supabase/cli/internal/utils"
|
|
"github.com/supabase/cli/pkg/migration"
|
|
)
|
|
|
|
func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
|
|
remoteVersions, err := loadRemoteVersions(ctx, config, options...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
localVersions, err := LoadLocalVersions(fsys)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
table := makeTable(remoteVersions, localVersions)
|
|
return RenderTable(table)
|
|
}
|
|
|
|
func loadRemoteVersions(ctx context.Context, config pgconn.Config, options ...func(*pgx.ConnConfig)) ([]string, error) {
|
|
conn, err := utils.ConnectByConfig(ctx, config, options...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer conn.Close(context.Background())
|
|
return migration.ListRemoteMigrations(ctx, conn)
|
|
}
|
|
|
|
func makeTable(remoteMigrations, localMigrations []string) string {
|
|
var err error
|
|
table := "|Local|Remote|Time (UTC)|\n|-|-|-|\n"
|
|
for i, j := 0, 0; i < len(remoteMigrations) || j < len(localMigrations); {
|
|
remoteTimestamp := math.MaxInt
|
|
if i < len(remoteMigrations) {
|
|
if remoteTimestamp, err = strconv.Atoi(remoteMigrations[i]); err != nil {
|
|
i++
|
|
continue
|
|
}
|
|
}
|
|
localTimestamp := math.MaxInt
|
|
if j < len(localMigrations) {
|
|
if localTimestamp, err = strconv.Atoi(localMigrations[j]); err != nil {
|
|
j++
|
|
continue
|
|
}
|
|
}
|
|
// Top to bottom chronological order
|
|
if localTimestamp < remoteTimestamp {
|
|
table += fmt.Sprintf("|`%s`|` `|`%s`|\n", localMigrations[j], utils.FormatTimestampVersion(localMigrations[j]))
|
|
j++
|
|
} else if remoteTimestamp < localTimestamp {
|
|
table += fmt.Sprintf("|` `|`%s`|`%s`|\n", remoteMigrations[i], utils.FormatTimestampVersion(remoteMigrations[i]))
|
|
i++
|
|
} else {
|
|
table += fmt.Sprintf("|`%s`|`%s`|`%s`|\n", localMigrations[j], remoteMigrations[i], utils.FormatTimestampVersion(remoteMigrations[i]))
|
|
i++
|
|
j++
|
|
}
|
|
}
|
|
return table
|
|
}
|
|
|
|
func RenderTable(markdown string) error {
|
|
r, err := glamour.NewTermRenderer(
|
|
glamour.WithAutoStyle(),
|
|
glamour.WithWordWrap(-1),
|
|
)
|
|
if err != nil {
|
|
return errors.Errorf("failed to initialise terminal renderer: %w", err)
|
|
}
|
|
out, err := r.Render(markdown)
|
|
if err != nil {
|
|
return errors.Errorf("failed to render markdown: %w", err)
|
|
}
|
|
fmt.Print(out)
|
|
return nil
|
|
}
|
|
|
|
func LoadLocalVersions(fsys afero.Fs) ([]string, error) {
|
|
var versions []string
|
|
filter := func(v string) bool {
|
|
versions = append(versions, v)
|
|
return true
|
|
}
|
|
_, err := migration.ListLocalMigrations(utils.MigrationsDir, afero.NewIOFS(fsys), filter)
|
|
return versions, err
|
|
}
|
|
|
|
func LoadPartialMigrations(version string, fsys afero.Fs) ([]string, error) {
|
|
filter := func(v string) bool {
|
|
return version == "" || v <= version
|
|
}
|
|
return migration.ListLocalMigrations(utils.MigrationsDir, afero.NewIOFS(fsys), filter)
|
|
}
|