/
run.go
104 lines (87 loc) · 1.93 KB
/
run.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright 2020 The Verbis Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package updater
import (
"database/sql"
"io/ioutil"
)
// runMigrations sorts the migrations and loops over them.
// If there is a migration to run it will be processed
// and committed if the database exists.
func (u *Updater) runMigrations() (Status, error) {
var (
err error
tx *sql.Tx
)
if u.opts.hasDB {
tx, err = u.opts.DB.Begin()
if err != nil {
return DatabaseError, err
}
}
migrations.Sort()
var down []CallBackFn
for _, migration := range migrations {
shouldRun := u.version.LessThan(migration.toSemVer())
if !shouldRun {
continue
}
code, err := u.process(migration, tx)
if err != nil {
rollBackErr := u.rollBack(tx, down)
if rollBackErr != nil {
// In a dirty state
return code, rollBackErr
}
return code, err
}
down = append(down, migration.CallBackDown)
}
if u.opts.hasDB {
err := tx.Commit()
if err != nil {
return DatabaseError, err
}
}
return Updated, nil
}
// rollback reverse the changes from the database (if
// there is one) and the callbacks.
func (u *Updater) rollBack(tx *sql.Tx, down []CallBackFn) error {
if u.opts.hasDB {
err := tx.Rollback()
if err != nil {
return err
}
}
for _, fn := range down {
err := fn()
if err != nil {
return err
}
}
return nil
}
// process reads the migration and executes the migration
// if there is one. Calls the callback function if there
// is one set.
func (u *Updater) process(m *Migration, tx *sql.Tx) (Status, error) {
migration, err := ioutil.ReadAll(m.SQL)
if err != nil {
return Unknown, err
}
if u.opts.hasDB {
_, err = tx.Exec(string(migration))
if err != nil {
return DatabaseError, err
}
}
if m.hasCallBack() {
err := m.CallBackUp()
if err != nil {
return CallBackError, err
}
}
return Updated, nil
}