Skip to content

Commit 80fc253

Browse files
feat(migrate): implement migration sort customization
1 parent 5a70b4e commit 80fc253

File tree

4 files changed

+63
-29
lines changed

4 files changed

+63
-29
lines changed

migrate/migration.go

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77
"fmt"
88
"io"
99
"io/fs"
10-
"sort"
11-
"strconv"
1210
"strings"
1311
"text/template"
1412
"time"
@@ -233,7 +231,7 @@ func (ms MigrationSlice) Applied() MigrationSlice {
233231
applied = append(applied, ms[i])
234232
}
235233
}
236-
sortDesc(applied)
234+
SafeDescSort(applied)
237235
return applied
238236
}
239237

@@ -246,7 +244,7 @@ func (ms MigrationSlice) Unapplied() MigrationSlice {
246244
unapplied = append(unapplied, ms[i])
247245
}
248246
}
249-
sortAsc(unapplied)
247+
SafeAscSort(unapplied)
250248
return unapplied
251249
}
252250

@@ -276,6 +274,8 @@ func (ms MigrationSlice) LastGroup() *MigrationGroup {
276274
group.Migrations = append(group.Migrations, ms[i])
277275
}
278276
}
277+
// Sort the migrations in the group using the global descending sort function
278+
SafeDescSort(group.Migrations)
279279
return group
280280
}
281281

@@ -322,27 +322,3 @@ func WithNopMigration() MigrationOption {
322322
cfg.nop = true
323323
}
324324
}
325-
326-
//------------------------------------------------------------------------------
327-
328-
func sortAsc(ms MigrationSlice) {
329-
sort.Slice(ms, func(i, j int) bool {
330-
ni, ei := strconv.ParseInt(ms[i].Name, 10, 64)
331-
nj, ej := strconv.ParseInt(ms[j].Name, 10, 64)
332-
if ei == nil && ej == nil && ni != nj {
333-
return ni < nj
334-
}
335-
return ms[i].Name < ms[j].Name
336-
})
337-
}
338-
339-
func sortDesc(ms MigrationSlice) {
340-
sort.Slice(ms, func(i, j int) bool {
341-
ni, ei := strconv.ParseInt(ms[i].Name, 10, 64)
342-
nj, ej := strconv.ParseInt(ms[j].Name, 10, 64)
343-
if ei == nil && ej == nil && ni != nj {
344-
return ni > nj
345-
}
346-
return ms[i].Name > ms[j].Name
347-
})
348-
}

migrate/migrations.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func NewMigrations(opts ...MigrationsOption) *Migrations {
3838
func (m *Migrations) Sorted() MigrationSlice {
3939
migrations := make(MigrationSlice, len(m.ms))
4040
copy(migrations, m.ms)
41-
sortAsc(migrations)
41+
SafeAscSort(migrations)
4242
return migrations
4343
}
4444

migrate/migrator.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ func WithTemplateData(data any) MigratorOption {
4747
}
4848
}
4949

50+
// WithSort overrides the default ascending sort function for all migrations.
51+
// This affects all sorting operations in the entire migrate package.
52+
func WithSort(ascSortFn, descSortFn MigrationSortFunc) {
53+
sortMutex.Lock()
54+
defer sortMutex.Unlock()
55+
AscSort = ascSortFn
56+
DescSort = descSortFn
57+
}
58+
5059
type Migrator struct {
5160
db *bun.DB
5261
migrations *Migrations

migrate/sort.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package migrate
2+
3+
import (
4+
"sort"
5+
"sync"
6+
)
7+
8+
// MigrationSortFunc defines the signature for functions that sort migrations.
9+
type MigrationSortFunc func(ms MigrationSlice)
10+
11+
// sortMutex protects access to the global sort functions.
12+
var sortMutex sync.RWMutex
13+
14+
// Default sort implementations
15+
var defaultAscSort MigrationSortFunc = func(ms MigrationSlice) {
16+
sort.Slice(ms, func(i, j int) bool {
17+
return ms[i].Name < ms[j].Name
18+
})
19+
}
20+
21+
var defaultDescSort MigrationSortFunc = func(ms MigrationSlice) {
22+
sort.Slice(ms, func(i, j int) bool {
23+
return ms[i].Name > ms[j].Name
24+
})
25+
}
26+
27+
// AscSort is the global ascending sort function.
28+
// Default is to sort by migration name in ascending order.
29+
// Can be overridden to use custom sorting logic.
30+
var AscSort MigrationSortFunc = defaultAscSort
31+
32+
// DescSort is the global descending sort function.
33+
// Default is to sort by migration name in descending order.
34+
// Can be overridden to use custom sorting logic.
35+
var DescSort MigrationSortFunc = defaultDescSort
36+
37+
// SafeAscSort applies the current ascending sort function in a thread-safe manner.
38+
func SafeAscSort(ms MigrationSlice) {
39+
sortMutex.RLock()
40+
defer sortMutex.RUnlock()
41+
AscSort(ms)
42+
}
43+
44+
// SafeDescSort applies the current descending sort function in a thread-safe manner.
45+
func SafeDescSort(ms MigrationSlice) {
46+
sortMutex.RLock()
47+
defer sortMutex.RUnlock()
48+
DescSort(ms)
49+
}

0 commit comments

Comments
 (0)