TastyBites/database/migrator.go
2024-05-07 12:47:44 +01:00

124 lines
2.5 KiB
Go

package database
import (
"bufio"
"embed"
"fmt"
"os"
"strings"
migrate "github.com/rubenv/sql-migrate"
)
//go:embed migrations/*
var dbMigrations embed.FS
var migrations = migrate.EmbedFileSystemMigrationSource{
FileSystem: dbMigrations,
Root: "migrations",
}
func Migrate(confirm bool) error {
var direction = migrate.Up
pending, _, err := migrate.PlanMigration(Conn, "sqlite3", migrations, migrate.Up, 0)
if err != nil {
return err
}
if len(pending) == 0 {
fmt.Println("Nothing to change")
os.Exit(0)
}
if !confirm {
fmt.Printf("Apply %d pending migration(s)? [Y/n] ", len(pending))
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
input = strings.ToLower(input)
if !strings.HasPrefix(input, "y") && input != "" {
fmt.Printf("Canceling %d migration(s)\n", len(pending))
os.Exit(0)
}
}
changes, err := migrate.Exec(Conn, "sqlite3", migrations, direction)
if err != nil {
return err
}
fmt.Printf("Applied %d migration(s)!\n", changes)
return nil
}
func Downgrade(confirm bool) error {
var direction = migrate.Down
pending, err := migrate.GetMigrationRecords(Conn, "sqlite3")
if err != nil {
return err
}
if len(pending) == 0 {
fmt.Println("Nothing to change")
os.Exit(0)
}
if !confirm {
fmt.Printf("Undo %d migration(s)? [Y/n] ", len(pending))
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
input = strings.TrimSpace(input)
input = strings.ToLower(input)
if !strings.HasPrefix(input, "y") && input != "" {
fmt.Printf("Canceling %d downgrade(s)\n", len(pending))
os.Exit(0)
}
}
changes, err := migrate.Exec(Conn, "sqlite3", migrations, direction)
if err != nil {
return err
}
fmt.Printf("Undone %d migration(s)!\n", changes)
return nil
}
func Status() error {
applied, err := migrate.GetMigrationRecords(Conn, "sqlite3")
if err != nil {
return err
}
pending, _, err := migrate.PlanMigration(Conn, "sqlite3", migrations, migrate.Up, 0)
if err != nil {
return err
}
fmt.Println("Available migrations:")
for _, migration := range applied {
fmt.Printf(" [x] %s\n", migration.Id)
}
for _, migration := range pending {
fmt.Printf(" [ ] %s\n", migration.Id)
}
if len(pending) > 0 {
fmt.Printf("\nTo apply %d pending migrations, run `TastyBites migrate`\n", len(pending))
}
return nil
}
func GetPending() (bool, error) {
planned, _, err := migrate.PlanMigration(Conn, "sqlite3", migrations, migrate.Up, 0)
if err != nil {
return false, err
}
return len(planned) > 0, nil
}