-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexec_start.go
70 lines (59 loc) · 1.98 KB
/
exec_start.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
package adapt
import (
"log/slog"
)
func (e *exec) stageStart() error {
e.log.Debug("start")
// compare local against store
unknown, err := unknownAppliedMigrations(e.applied, e.available, !e.optDisableHashIntegrityChecks, e.log)
if err != nil {
return err
}
e.unknownApplied = unknown
// branch between rollback and migrate
if len(e.unknownApplied) > 0 {
e.log.Debug("found unknown migrations. Starting with rollback protocol", "unknown_migrations", len(e.unknownApplied))
err = e.stageRollback()
if err != nil {
e.log.Error("rollback procedure failed", "error", err)
return err
}
} else {
e.log.Debug("all stored migrations are known. Continuing with migration")
}
return e.stageMigrate()
}
func unknownAppliedMigrations(applied []*Migration, available []*AvailableMigration, performHashIntegrityChecks bool, log *slog.Logger) ([]*Migration, error) {
searchLocal := func(id string) *AvailableMigration {
for _, local := range available {
if local.ID == id {
return local
}
}
return nil
}
hashEqual := func(h1 *string, h2 *string) bool {
return h1 == nil || h2 == nil || *h1 == *h2
}
var unknown []*Migration
for _, a := range applied {
local := searchLocal(a.ID)
if local == nil {
unknown = append(unknown, a)
continue
}
if performHashIntegrityChecks && !hashEqual(a.Hash, local.Hash) {
log.Error("hash of local migration changed. Aborting to protect integrity, as changes to already applied scripts aren't allowed",
"migration_id", a.ID, "local_hash", *local.Hash, "storage_hash", *a.Hash)
return nil, ErrIntegrityProtection
}
if len(unknown) > 0 {
log.Error("found known migration AFTER an unknown one. Aborting to " +
"protect integrity, because unknown migrations (and their eventual rollbacks) must be at the " +
"end of applied migrations. This ensures rollbacks are clean and don't interfere with migrations " +
"that depend on these changes.")
return nil, ErrIntegrityProtection
}
}
return unknown, nil
}