github.com/wrgl/wrgl@v0.14.0/pkg/migrate/migrate.go (about)

     1  package migrate
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"sort"
     9  )
    10  
    11  type migration struct {
    12  	SemVer  *SemVer
    13  	Migrate func(dir string) error
    14  }
    15  
    16  var migrations []migration
    17  
    18  func insertMigration(sl []migration, m migration) []migration {
    19  	n := len(sl)
    20  	if i := sort.Search(n, func(i int) bool {
    21  		return sl[i].SemVer.CompareTo(m.SemVer) >= 0
    22  	}); i <= n-1 {
    23  		sl = append(sl[:i+1], sl[i:]...)
    24  		sl[i] = m
    25  	} else {
    26  		sl = append(sl, m)
    27  	}
    28  	return sl
    29  }
    30  
    31  func readVersion(dir string) (*SemVer, error) {
    32  	v := &SemVer{}
    33  	f, err := os.Open(filepath.Join(dir, "version"))
    34  	if err != nil {
    35  		return v, nil
    36  	}
    37  	defer f.Close()
    38  	b, err := io.ReadAll(f)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	if err = v.UnmarshalText(b); err != nil {
    43  		return nil, err
    44  	}
    45  	return v, nil
    46  }
    47  
    48  func writeVersion(dir string, v *SemVer) error {
    49  	f, err := os.Create(filepath.Join(dir, "version"))
    50  	if err != nil {
    51  		return err
    52  	}
    53  	defer f.Close()
    54  	_, err = f.Write([]byte(v.String()))
    55  	return err
    56  }
    57  
    58  func Migrate(dir string) (err error) {
    59  	semver, err := readVersion(dir)
    60  	var newSemver *SemVer
    61  	for _, m := range migrations {
    62  		if m.SemVer.CompareTo(semver) <= 0 {
    63  			continue
    64  		}
    65  		if err = m.Migrate(dir); err != nil {
    66  			return fmt.Errorf("error while migrating to v%s: %v", m.SemVer, err)
    67  		}
    68  		newSemver = m.SemVer
    69  	}
    70  	if newSemver != nil {
    71  		return writeVersion(dir, newSemver)
    72  	}
    73  	return nil
    74  }