vikunja/pkg/migration/migration.go

125 lines
3.7 KiB
Go
Raw Normal View History

2019-03-24 19:53:06 +00:00
// Vikunja is a todo-list application to facilitate your life.
// Copyright 2019 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package migration
2019-03-25 07:05:06 +00:00
import (
2019-03-25 07:23:56 +00:00
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/log"
2019-03-27 06:55:33 +00:00
"code.vikunja.io/api/pkg/models"
2019-03-25 07:23:56 +00:00
"github.com/go-xorm/xorm"
2019-03-28 18:45:14 +00:00
"github.com/olekukonko/tablewriter"
"github.com/spf13/viper"
2019-03-28 18:45:14 +00:00
"os"
2019-03-25 07:05:06 +00:00
"sort"
"src.techknowlogick.com/xormigrate"
)
2019-03-24 20:45:18 +00:00
// You can get the id string for new migrations by running `date +%Y%m%d%H%M%S` on a unix system.
var migrations []*xormigrate.Migration
// A helper function because we need a migration in various places which we can't really solve with an init() function.
func initMigration(x *xorm.Engine) *xormigrate.Xormigrate {
2019-03-25 07:23:56 +00:00
// Get our own xorm engine if we don't have one
if x == nil {
var err error
x, err = db.CreateDBEngine()
if err != nil {
log.Log.Criticalf("Could not connect to db: %v", err.Error())
return nil
2019-03-25 07:23:56 +00:00
}
}
2019-03-24 20:45:18 +00:00
// Because init() does not guarantee the order in which these are added to the slice,
// we need to sort them to ensure that they are in order
2019-03-25 07:05:06 +00:00
sort.Slice(migrations, func(i, j int) bool {
return migrations[i].ID < migrations[j].ID
})
2019-03-24 19:53:06 +00:00
2019-03-26 07:00:34 +00:00
m := xormigrate.New(x, migrations)
2019-03-25 07:23:56 +00:00
m.NewLogger(log.GetLogWriter("database"))
2019-03-26 07:03:38 +00:00
m.InitSchema(initSchema)
return m
}
2019-03-29 15:37:43 +00:00
// Migrate runs all migrations
func Migrate(x *xorm.Engine) {
m := initMigration(x)
2019-03-27 19:18:21 +00:00
err := m.Migrate()
2019-03-26 07:00:34 +00:00
if err != nil {
2019-03-28 07:13:17 +00:00
log.Log.Fatalf("Migration failed: %v", err)
2019-03-26 07:00:34 +00:00
}
2019-03-28 18:50:41 +00:00
log.Log.Info("Ran all migrations successfully.")
}
2019-03-29 15:37:43 +00:00
// ListMigrations pretty-prints a list with all migrations.
func ListMigrations() {
2019-03-28 18:45:14 +00:00
x, err := db.CreateDBEngine()
if err != nil {
log.Log.Fatalf("Could not connect to db: %v", err.Error())
}
ms := []*xormigrate.Migration{}
err = x.Find(&ms)
if err != nil {
log.Log.Fatalf("Error getting migration table: %v", err.Error())
}
2019-03-25 07:23:56 +00:00
2019-03-28 18:45:14 +00:00
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"ID", "Description"})
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor},
tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor})
for _, m := range ms {
table.Append([]string{m.ID, m.Description})
}
table.Render()
}
2019-03-24 21:00:12 +00:00
2019-03-29 15:37:43 +00:00
// Rollback rolls back all migrations until a certain point.
2019-03-28 18:50:41 +00:00
func Rollback(migrationID string) {
m := initMigration(nil)
err := m.RollbackTo(migrationID)
if err != nil {
log.Log.Fatalf("Could not rollback: %v", err)
}
log.Log.Info("Rolled back successfully.")
2019-03-24 19:53:06 +00:00
}
2019-03-26 07:03:38 +00:00
// Deletes a column from a table. All arguments are strings, to let them be standalone and not depending on any struct.
func dropTableColum(x *xorm.Engine, tableName, col string) error {
switch viper.GetString("database.type") {
case "sqlite":
log.Log.Warning("Unable to drop columns in SQLite")
case "mysql":
2019-03-28 07:13:17 +00:00
_, err := x.Exec("ALTER TABLE " + tableName + " DROP COLUMN " + col)
if err != nil {
return err
}
default:
log.Log.Fatal("Unknown db.")
}
return nil
}
2019-03-26 07:03:38 +00:00
func initSchema(tx *xorm.Engine) error {
return tx.Sync2(
2019-03-28 19:09:07 +00:00
models.GetTables()...,
2019-03-26 07:03:38 +00:00
)
}