From 517f5152e7bdea2339c754ef86a13080e2d04f26 Mon Sep 17 00:00:00 2001 From: Sergei Maklagin Date: Tue, 3 Mar 2026 00:51:04 +0300 Subject: [PATCH] Add migrate --- common/migrate/source/raw.go | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 common/migrate/source/raw.go diff --git a/common/migrate/source/raw.go b/common/migrate/source/raw.go new file mode 100644 index 00000000..ad496f56 --- /dev/null +++ b/common/migrate/source/raw.go @@ -0,0 +1,98 @@ +package source + +import ( + "io" + "io/fs" + "io/ioutil" + "strconv" + "strings" + + "github.com/golang-migrate/migrate/v4/source" + E "github.com/sagernet/sing/common/exceptions" +) + +type RawDriver struct { + migrations *source.Migrations + rawMigrations map[string]string +} + +func NewRawDriver(rawMigrations map[string]string) *RawDriver { + return &RawDriver{rawMigrations: rawMigrations} +} + +func (d *RawDriver) Init() error { + ms := source.NewMigrations() + for key := range d.rawMigrations { + m, err := source.DefaultParse(key) + if err != nil { + continue + } + if !ms.Append(m) { + return source.ErrDuplicateMigration{ + Migration: *m, + } + } + } + d.migrations = ms + return nil +} + +func (d *RawDriver) Open(url string) (source.Driver, error) { + return nil, E.New("open() cannot be called") +} + +func (d *RawDriver) Close() error { + return nil +} + +func (d *RawDriver) First() (version uint, err error) { + if version, ok := d.migrations.First(); ok { + return version, nil + } + return 0, &fs.PathError{ + Op: "first", + Err: fs.ErrNotExist, + } +} + +func (d *RawDriver) Prev(version uint) (prevVersion uint, err error) { + if version, ok := d.migrations.Prev(version); ok { + return version, nil + } + return 0, &fs.PathError{ + Op: "prev for version " + strconv.FormatUint(uint64(version), 10), + Err: fs.ErrNotExist, + } +} + +func (d *RawDriver) Next(version uint) (nextVersion uint, err error) { + if version, ok := d.migrations.Next(version); ok { + return version, nil + } + return 0, &fs.PathError{ + Op: "next for version " + strconv.FormatUint(uint64(version), 10), + Err: fs.ErrNotExist, + } +} + +func (d *RawDriver) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) { + if m, ok := d.migrations.Up(version); ok { + body := ioutil.NopCloser(strings.NewReader(d.rawMigrations[m.Raw])) + return body, m.Identifier, nil + } + return nil, "", &fs.PathError{ + Op: "read up for version " + strconv.FormatUint(uint64(version), 10), + Err: fs.ErrNotExist, + } +} + +func (d *RawDriver) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) { + if m, ok := d.migrations.Down(version); ok { + body := ioutil.NopCloser(strings.NewReader(d.rawMigrations[m.Raw])) + return body, m.Identifier, nil + } + return nil, "", &fs.PathError{ + Op: "read down for version " + strconv.FormatUint(uint64(version), 10), + Err: fs.ErrNotExist, + } +}