Files
butterfliu/cmd/migrate/main.go
2026-01-08 20:48:55 +08:00

144 lines
3.6 KiB
Go

package main
import (
"butterfliu/migrations"
"database/sql"
"fmt"
"log"
"os"
_ "github.com/mattn/go-sqlite3"
)
func main() {
if len(os.Args) < 2 {
printUsage()
os.Exit(1)
}
command := os.Args[1]
// Database file path
dbPath := "./butterfliu.db"
if len(os.Args) > 3 && os.Args[1] == "db" {
dbPath = os.Args[3]
}
log.Printf("Using database: %s", dbPath)
// Open database connection
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
log.Fatalf("Error opening database %s: %v", dbPath, err)
}
defer db.Close()
// Test connection
if err = db.Ping(); err != nil {
log.Fatalf("Error connecting to database %s: %v", dbPath, err)
}
// Initialize migration table
if err = migrations.InitMigrationTable(db); err != nil {
log.Fatalf("Error initializing migration table: %v", err)
}
switch command {
case "up":
// Run all pending migrations
if err := migrations.MigrateUp(db); err != nil {
log.Fatalf("Error applying migrations: %v", err)
}
log.Println("All migrations applied successfully")
case "down":
if len(os.Args) < 3 {
log.Println("Error: Missing target version")
printUsage()
os.Exit(1)
}
targetVersion, err := parseVersion(os.Args[2])
if err != nil {
log.Fatalf("Error parsing target version: %v", err)
}
// Roll back migrations to target version
if err := migrations.MigrateDown(db, targetVersion); err != nil {
log.Fatalf("Error rolling back migrations: %v", err)
}
log.Printf("Migrations rolled back to version %d successfully\n", targetVersion)
case "reset":
// Roll back all migrations
if err := migrations.MigrateDown(db, 0); err != nil {
log.Fatalf("Error rolling back migrations: %v", err)
}
log.Println("All migrations rolled back successfully")
case "refresh":
// Roll back all migrations and then apply them again
if err := migrations.MigrateDown(db, 0); err != nil {
log.Fatalf("Error rolling back migrations: %v", err)
}
if err := migrations.MigrateUp(db); err != nil {
log.Fatalf("Error applying migrations: %v", err)
}
log.Println("All migrations refreshed successfully")
case "status":
// Show migration status
migrationList, err := migrations.ListMigrations(db)
if err != nil {
log.Fatalf("Error listing migrations: %v", err)
}
log.Println("Migration Status:")
log.Println("=================")
for _, migration := range migrationList {
status := "Pending"
appliedAt := ""
if applied, ok := migration["applied"].(bool); ok && applied {
status = "Applied"
appliedAt = migration["applied_at"].(string)
}
log.Printf("%d: %s - %s %s\n", migration["version"], migration["description"], status, appliedAt)
}
case "create":
if len(os.Args) < 3 {
log.Println("Error: Missing migration name")
printUsage()
os.Exit(1)
}
name := os.Args[2]
if err := migrations.CreateMigration(name); err != nil {
log.Fatalf("Error creating migration: %v", err)
}
default:
log.Printf("Error: Unknown command '%s'\n", command)
printUsage()
os.Exit(1)
}
}
func printUsage() {
log.Println("Usage: go run cmd/migrate/main.go <command> [args]")
log.Println("")
log.Println("Commands:")
log.Println(" up Apply all pending migrations")
log.Println(" down <version> Roll back migrations to specified version")
log.Println(" reset Roll back all migrations")
log.Println(" refresh Roll back all migrations and apply them again")
log.Println(" status Show migration status")
log.Println(" create <name> Create a new migration")
}
func parseVersion(s string) (int, error) {
var v int
_, err := fmt.Sscanf(s, "%d", &v)
return v, err
}