diff --git a/cmd/migrate.go b/cmd/migrate.go new file mode 100644 index 0000000..de19d60 --- /dev/null +++ b/cmd/migrate.go @@ -0,0 +1,54 @@ +package cmd + +import ( + "database/sql" + "fmt" + "log" + + "github.com/Jaculabilis/intake/core" + _ "github.com/mattn/go-sqlite3" + "github.com/spf13/cobra" +) + +var migrateCmd = &cobra.Command{ + Use: "migrate", + Short: "Migrate an intake database to the latest version", + Long: `Migrate an intake database to the latest version. + +Note that the database will be created if it does not exist, even with --list.`, + Run: func(cmd *cobra.Command, args []string) { + migrate() + }, +} + +var migrateListOnly bool + +func init() { + rootCmd.AddCommand(migrateCmd) + + migrateCmd.Flags().BoolVarP(&migrateListOnly, "list", "l", false, "Show the list of migrations") +} + +func migrate() { + db, err := sql.Open("sqlite3", getDbPath()) + if err != nil { + log.Fatal(err) + } + + core.InitDatabase(db) + if migrateListOnly { + pending, err := core.GetPendingMigrations(db) + if err != nil { + log.Fatal(err) + } + for name, complete := range pending { + if complete { + fmt.Printf("[x] %s\n", name) + } else { + fmt.Printf("[ ] %s\n", name) + } + } + } else { + core.MigrateDatabase(db) + } +} diff --git a/cmd/root.go b/cmd/root.go index 6b20036..e424680 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "os" "github.com/spf13/cobra" @@ -19,7 +20,25 @@ func Execute() { } } +var dbPath string + func init() { // Disable the automatic help command rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) + + // All commands need to operate on a database + rootCmd.PersistentFlags().StringVarP(&dbPath, "db", "d", "", "Path to the intake sqlite database") +} + +func getDbPath() string { + if dbPath != "" { + return dbPath + } + env := os.Getenv("INTAKE_DB") + if env != "" { + return env + } + fmt.Println("error: No database specified. Either --db or INTAKE_DB must be set.") + os.Exit(1) + return "" } diff --git a/core/db.go b/core/db.go index 57490ba..ae767a6 100644 --- a/core/db.go +++ b/core/db.go @@ -51,8 +51,8 @@ func InitDatabase(db *sql.DB) error { return err } -// Get the names of existing migrations that haven't been applied yet. -func GetPendingMigrations(db *sql.DB) ([]string, error) { +// Get a map of migration names to whether the migration has been applied. +func GetPendingMigrations(db *sql.DB) (map[string]bool, error) { allMigrations, err := migrations.ReadDir("sql") if err != nil { return nil, err @@ -73,14 +73,7 @@ func GetPendingMigrations(db *sql.DB) ([]string, error) { complete[name] = true } - var pending []string - for name, isComplete := range complete { - if !isComplete { - pending = append(pending, name) - } - } - - return pending, nil + return complete, nil } // Apply a migration by name. @@ -104,10 +97,12 @@ func MigrateDatabase(db *sql.DB) error { if err != nil { return err } - for _, name := range pending { - err = ApplyMigration(db, name) - if err != nil { - return err + for name, complete := range pending { + if !complete { + err = ApplyMigration(db, name) + if err != nil { + return err + } } } return nil