cobble/MigrationMap.go

70 lines
1.6 KiB
Go

package main
import (
"errors"
"fmt"
)
func NewMigrationGraph() MigrationGraph {
return MigrationGraph{Migrations: map[string]Migration{}, parentage: map[string]*Migration{}}
}
// Adds a migration to the graph.
//
// This also adds the migration to the parentage mappings to link it
// to its parent. If the migration added has no parent, then it's also
// set to be the root of the graph.
func (g *MigrationGraph) AddMigration(m Migration) {
if m.Requires == "" {
g.addRoot(m)
}
g.Migrations[m.Name] = m
g.parentage[m.Requires] = &m
}
// Builds the linear history of migrations.
func (g *MigrationGraph) GetLinearHistory() ([]Migration, error) {
if g.Root == nil {
return []Migration{}, errors.New("Cannot get linear history, the graph has no root.")
}
ordered := []Migration{}
visited := map[string]bool{}
unordered := []Migration{*g.Root}
for len(unordered) > 0 {
migration := unordered[0]
unordered = unordered[1:]
if _, hasVisited := visited[migration.Name]; hasVisited {
return []Migration{}, errors.New("Cycle detected, cannot generate linear history.")
}
child, hasChildren := g.parentage[migration.Name]
ordered = append(ordered, migration)
if hasChildren {
unordered = append(unordered, *child)
}
visited[migration.Name] = true
}
if len(ordered) != len(g.Migrations) {
return ordered, errors.New("Not all migrations in the graph are part of the history.")
}
return ordered, nil
}
func (g *MigrationGraph) addRoot(m Migration) error {
if g.Root != nil {
return errors.New(fmt.Sprintf("Cannot have more than one root, tried to add %#v but already knew about %#v.", m, g.Root))
}
g.Root = &m
return nil
}