-
Notifications
You must be signed in to change notification settings - Fork 0
/
diff.go
175 lines (146 loc) · 4.63 KB
/
diff.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package cmd
import (
"fmt"
"github.com/freneticmonkey/migrate/go/config"
"github.com/freneticmonkey/migrate/go/configsetup"
"github.com/freneticmonkey/migrate/go/git"
"github.com/freneticmonkey/migrate/go/id"
"github.com/freneticmonkey/migrate/go/metadata"
"github.com/freneticmonkey/migrate/go/mysql"
"github.com/freneticmonkey/migrate/go/table"
"github.com/freneticmonkey/migrate/go/util"
"github.com/freneticmonkey/migrate/go/yaml"
"github.com/urfave/cli"
)
// GetDiffCommand Configure the validate command
func GetDiffCommand() (setup cli.Command) {
setup = cli.Command{
Name: "diff",
Usage: "Diff the MySQL target database and the YAML schema.",
Flags: []cli.Flag{
cli.StringFlag{
Name: "project",
Value: "",
Usage: "The target project",
},
cli.StringFlag{
Name: "version",
Value: "",
Usage: "The target git version",
},
cli.StringFlag{
Name: "table",
Value: "",
Usage: "Name of the target table to diff",
},
},
Action: func(ctx *cli.Context) error {
var version string
var project string
var table string
// Parse global flags
parseGlobalFlags(ctx)
// Setup the management database and configuration settings
conf, err := configsetup.ConfigureManagement()
if err != nil {
return cli.NewExitError(fmt.Sprintf("Configuration Load failed. Error: %v", err), 1)
}
// Override the project settings with the command line flags
if ctx.IsSet("version") {
version = ctx.String("version")
}
if ctx.IsSet("project") {
project = ctx.String("project")
}
if ctx.IsSet("table") {
table = ctx.String("table")
}
return diff(version, project, table, conf)
},
}
return setup
}
func diff(project, version, tableName string, conf config.Config) *cli.ExitError {
var forwardDiff table.Differences
var problems id.ValidationErrors
var err error
targetTableFound := false
// Enable Metadata cache as we're not going to be making changes to it
metadata.UseCache(true)
// Override the project settings with the command line flags
if version != "" {
conf.Project.Git.Version = version
}
if project != "" {
conf.Project.Name = project
git.Clone(conf.Project)
} else {
util.LogInfo("No project specified. Comparing the current state of the YAML schema in working path.")
}
// Read the YAML files cloned from the repo
err = yaml.ReadTables(conf)
if util.ErrorCheck(err) {
return cli.NewExitError("Diff failed. Unable to read YAML Tables", 1)
}
problems, err = id.ValidateSchema(yaml.Schema, "YAML Schema", true)
if util.ErrorCheck(err) {
return cli.NewExitError("Validation failed. YAML Errors found", problems.Count())
}
// Filter by tableName in the YAML Schema
if tableName != "" {
tgtTbl := []table.Table{}
for _, tbl := range yaml.Schema {
if tbl.Name == tableName {
tgtTbl = append(tgtTbl, tbl)
targetTableFound = true
break
}
}
// Reduce the YAML schema to the single target table
yaml.Schema = tgtTbl
}
// Read the MySQL tables from the target database
err = mysql.ReadTables(conf)
if util.ErrorCheck(err) {
return cli.NewExitError("Diff failed. Unable to read MySQL Tables", 1)
}
problems, err = id.ValidateSchema(mysql.Schema, "Target Database Schema", true)
if util.ErrorCheck(err) {
return cli.NewExitError("Validation failed. Problems with Target Database Detected", problems.Count())
}
// Filter by tableName in the MySQL Schema
if tableName != "" {
tgtTbl := []table.Table{}
for _, tbl := range mysql.Schema {
if tbl.Name == tableName {
tgtTbl = append(tgtTbl, tbl)
targetTableFound = true
break
}
}
// Reduce the YAML schema to the single target table
mysql.Schema = tgtTbl
}
problems, err = id.ValidatePropertyIDs(yaml.Schema, mysql.Schema, true)
if util.ErrorCheck(err) {
return cli.NewExitError("Validation failed. Detected YAML PropertyID problems", problems.Count())
}
// If a Table Name was specified, and a table wasn't found
if !targetTableFound && tableName != "" {
return cli.NewExitError(fmt.Sprintf("Diff failed for Table: %s. No found in YAML or MySQL Schemas", tableName), 1)
}
forwardDiff, err = table.DiffTables(yaml.Schema, mysql.Schema, true, true)
if util.ErrorCheck(err) {
return cli.NewExitError("Validation failed. Problems determining differences", 1)
}
util.VerboseOverrideSet(true)
mysql.GenerateAlters(forwardDiff)
util.VerboseOverrideRestore()
completeMessage := "Diff completed successfully."
if len(forwardDiff.Slice) > 0 {
completeMessage += fmt.Sprintf(" %d differences found.", len(forwardDiff.Slice))
} else {
completeMessage += " No differences found."
}
return cli.NewExitError(completeMessage, 0)
}