Skip to content

Commit bb53bbe

Browse files
authored
Merge pull request #5 from coldze/multi-migration
more flexible format for migrations
2 parents a2a34b4 + 67e93ae commit bb53bbe

File tree

1 file changed

+119
-8
lines changed

1 file changed

+119
-8
lines changed

engine/changelog.go

Lines changed: 119 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/hex"
66
"encoding/json"
77
"fmt"
8-
"github.com/pkg/errors"
98
"hash"
109
"io/ioutil"
1110
"path/filepath"
@@ -138,20 +137,132 @@ type ChangeFile struct {
138137
}
139138

140139
type changeFileInternal struct {
141-
Forward *MigrationFile `json:"migration,omitempty"`
142-
ForwardArr []*MigrationFile `json:"migrations,omitempty"`
143-
Backward *MigrationFile `json:"rollback,omitempty"`
144-
BackwardArr []*MigrationFile `json:"rollbacks,omitempty"`
140+
Forward interface{} `json:"migration,omitempty"`
141+
Backward interface{} `json:"rollback,omitempty"`
142+
}
143+
144+
func collectMigrationFilesFromMap(mapVal map[string]interface{}) ([]*MigrationFile, custom_error.CustomError) {
145+
if len(mapVal) > 2 {
146+
return nil, custom_error.MakeErrorf("Extra fields specified. %+v", mapVal)
147+
}
148+
relative := true
149+
relativeInterface, ok := mapVal["relativeToChangelogFile"]
150+
if ok {
151+
relative, ok = relativeInterface.(bool)
152+
if !ok {
153+
return nil, custom_error.MakeErrorf("Invalid format for `relativeToChangelogFile`. Type: %T", relativeInterface)
154+
}
155+
}
156+
157+
paths, ok := mapVal["include"]
158+
if !ok {
159+
return nil, custom_error.MakeErrorf("Missing `include` entry")
160+
}
161+
strPath, ok := paths.(string)
162+
if ok {
163+
return []*MigrationFile{
164+
&MigrationFile{
165+
Path: strPath,
166+
RelativePath: relative,
167+
},
168+
}, nil
169+
}
170+
pathArr, ok := paths.([]string)
171+
if !ok {
172+
return nil, custom_error.MakeErrorf("Unexpected type for `include` entry. Type: %T", paths)
173+
}
174+
migrations := make([]*MigrationFile, 0, len(pathArr))
175+
for i := range pathArr {
176+
migrations = append(migrations, &MigrationFile{
177+
Path: pathArr[i],
178+
RelativePath: relative,
179+
})
180+
}
181+
return migrations, nil
182+
}
183+
184+
func collectMigrationFiles(in interface{}) ([]*MigrationFile, custom_error.CustomError) {
185+
if in == nil {
186+
return []*MigrationFile{}, nil
187+
}
188+
strVal, ok := in.(string)
189+
if ok {
190+
return []*MigrationFile{
191+
&MigrationFile{
192+
Path: strVal,
193+
RelativePath: true,
194+
},
195+
}, nil
196+
}
197+
strArrVal, ok := in.([]string)
198+
if ok {
199+
migrations := make([]*MigrationFile, 0, len(strArrVal))
200+
for i := range strArrVal {
201+
migrations = append(migrations, &MigrationFile{
202+
Path: strArrVal[i],
203+
RelativePath: true,
204+
})
205+
}
206+
return migrations, nil
207+
}
208+
mapVal, ok := in.(map[string]interface{})
209+
if ok {
210+
res, err := collectMigrationFilesFromMap(mapVal)
211+
if err != nil {
212+
return nil, custom_error.NewErrorf(err, "Failed to collect migration's description")
213+
}
214+
return res, nil
215+
}
216+
217+
arrVal, ok := in.([]interface{})
218+
if !ok {
219+
return nil, custom_error.MakeErrorf("Unexpected type of migration description: %T", in)
220+
}
221+
migrations := make([]*MigrationFile, 0, len(arrVal))
222+
for i := range arrVal {
223+
strVal, ok := arrVal[i].(string)
224+
if ok {
225+
migrations = append(migrations, &MigrationFile{
226+
Path: strVal,
227+
RelativePath: true,
228+
})
229+
continue
230+
}
231+
val, ok := arrVal[i].(map[string]interface{})
232+
if !ok {
233+
return nil, custom_error.MakeErrorf("Invalid format. Expected object. Type: %T", arrVal[i])
234+
}
235+
migration, err := collectMigrationFilesFromMap(val)
236+
if err != nil {
237+
return nil, custom_error.NewErrorf(err, "Failed to collect migration's description")
238+
}
239+
migrations = append(migrations, migration...)
240+
}
241+
return migrations, nil
145242
}
146243

147244
func (c *ChangeFile) UnmarshalJSON(data []byte) error {
148245
c.Backward = []*MigrationFile{}
149246
changeInternal := changeFileInternal{}
150247
err := json.Unmarshal(data, &changeInternal)
151248
if err != nil {
152-
return err
249+
return custom_error.MakeErrorf("Failed to unmarshal change file. Error: %v", err)
153250
}
154-
isSingleForward := changeInternal.Forward != nil
251+
forward, cErr := collectMigrationFiles(changeInternal.Forward)
252+
if cErr != nil {
253+
return custom_error.NewErrorf(cErr, "Failed to process migration's description (forward)")
254+
}
255+
backward, cErr := collectMigrationFiles(changeInternal.Forward)
256+
if cErr != nil {
257+
return custom_error.NewErrorf(cErr, "Failed to process migration's description (forward)")
258+
}
259+
if forward == nil || len(forward) <= 0 {
260+
return custom_error.MakeErrorf("Empty forward migration")
261+
}
262+
c.Forward = forward
263+
c.Backward = backward
264+
return c.validate()
265+
/*isSingleForward := changeInternal.Forward != nil
155266
isMultipleForward := changeInternal.ForwardArr != nil
156267
if !isSingleForward && (!isMultipleForward || len(changeInternal.ForwardArr) <= 0) {
157268
return errors.New("Forward migration is empty")
@@ -176,7 +287,7 @@ func (c *ChangeFile) UnmarshalJSON(data []byte) error {
176287
if isSingleBackward {
177288
c.Backward = []*MigrationFile{changeInternal.Backward}
178289
}
179-
return c.validate()
290+
return c.validate()*/
180291
}
181292

182293
func validate(migrations []*MigrationFile) custom_error.CustomError {

0 commit comments

Comments
 (0)