1package migrate23import (4 "context"5 "embed"6 "fmt"7 "regexp"8 "strings"910 "github.com/charmbracelet/soft-serve/pkg/db"11)1213//go:embed *.sql14var sqls embed.FS1516// Keep this in order of execution, oldest to newest.17var migrations = []Migration{18 createTables,19 webhooks,20 migrateLfsObjects,21}2223func execMigration(ctx context.Context, tx *db.Tx, version int, name string, down bool) error {24 direction := "up"25 if down {26 direction = "down"27 }2829 driverName := tx.DriverName()30 if driverName == "sqlite3" {31 driverName = "sqlite"32 }3334 fn := fmt.Sprintf("%04d_%s_%s.%s.sql", version, toSnakeCase(name), driverName, direction)35 sqlstr, err := sqls.ReadFile(fn)36 if err != nil {37 return err38 }3940 if _, err := tx.ExecContext(ctx, string(sqlstr)); err != nil {41 return err42 }4344 return nil45}4647func migrateUp(ctx context.Context, tx *db.Tx, version int, name string) error {48 return execMigration(ctx, tx, version, name, false)49}5051func migrateDown(ctx context.Context, tx *db.Tx, version int, name string) error {52 return execMigration(ctx, tx, version, name, true)53}5455var (56 matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)")57 matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])")58)5960func toSnakeCase(str string) string {61 str = strings.ReplaceAll(str, "-", "_")62 str = strings.ReplaceAll(str, " ", "_")63 snake := matchFirstCap.ReplaceAllString(str, "${1}_${2}")64 snake = matchAllCap.ReplaceAllString(snake, "${1}_${2}")65 return strings.ToLower(snake)66}