Implement cache migrations
This commit is contained in:
parent
30d86d72ed
commit
2f0e1b0d46
12
internal/cache/cache.go
vendored
12
internal/cache/cache.go
vendored
@ -122,8 +122,16 @@ func (c *Cache) Read() error {
|
|||||||
d.Decode(c)
|
d.Decode(c)
|
||||||
|
|
||||||
// Perform migrations
|
// Perform migrations
|
||||||
if err := c.doMigrations(); err != nil {
|
err, migrated := c.doMigrations()
|
||||||
c.log.Error("Failed to run cache migrations", c.log.Args("error", err))
|
if err != nil {
|
||||||
|
c.log.Error("Failed to run cache migrations",
|
||||||
|
c.log.Args(
|
||||||
|
"migrated", migrated,
|
||||||
|
"error", err,
|
||||||
|
))
|
||||||
|
} else if migrated > 0 {
|
||||||
|
c.log.Info("Migrations run successfully", c.log.Args(
|
||||||
|
"migrated", migrated))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.readFromFile = true
|
c.readFromFile = true
|
||||||
|
37
internal/cache/cache_migrations.go
vendored
37
internal/cache/cache_migrations.go
vendored
@ -5,9 +5,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/mod/semver"
|
"golang.org/x/mod/semver"
|
||||||
|
|
||||||
|
"gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects"
|
||||||
)
|
)
|
||||||
|
|
||||||
type migrationFunc func(c *Cache) error
|
// Migrations funcs should return errors along with
|
||||||
|
// number of records updated
|
||||||
|
type migrationFunc func(c *Cache) (error, int)
|
||||||
|
|
||||||
// Registry of migrations by version
|
// Registry of migrations by version
|
||||||
var migrations = map[string]map[string]migrationFunc{
|
var migrations = map[string]map[string]migrationFunc{
|
||||||
@ -20,38 +24,55 @@ var migrations = map[string]map[string]migrationFunc{
|
|||||||
// of cache read from disk.
|
// of cache read from disk.
|
||||||
// Does not check to ensure migrations were successful,
|
// Does not check to ensure migrations were successful,
|
||||||
// only checks if a version has been achieved
|
// only checks if a version has been achieved
|
||||||
func (c *Cache) DoMigrations() error {
|
func (c *Cache) DoMigrations() (error, int) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
return c.doMigrations()
|
return c.doMigrations()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cache) doMigrations() error {
|
func (c *Cache) doMigrations() (error, int) {
|
||||||
var errs error
|
var errs error
|
||||||
|
var migrated int
|
||||||
for version, migrationFuncs := range migrations {
|
for version, migrationFuncs := range migrations {
|
||||||
|
var funcMigrated int
|
||||||
if semver.Compare(c.CacheVersion, version) < 0 {
|
if semver.Compare(c.CacheVersion, version) < 0 {
|
||||||
for name, migration := range migrationFuncs {
|
for name, migration := range migrationFuncs {
|
||||||
err := migration(c)
|
err, numMigrated := migration(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = errors.Join(
|
errs = errors.Join(
|
||||||
errs,
|
errs,
|
||||||
fmt.Errorf("%s - %s: %w", version, name, err),
|
fmt.Errorf("%s - %s: %w", version, name, err),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
funcMigrated += numMigrated
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've reached a cache version, update the CacheVersion
|
// We've reached a cache version, update the CacheVersion
|
||||||
// and write to disk
|
// and write to disk
|
||||||
if errs == nil {
|
if errs == nil && funcMigrated > 0 {
|
||||||
c.CacheVersion = version
|
c.CacheVersion = version
|
||||||
c.write()
|
c.write()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
migrated += funcMigrated
|
||||||
}
|
}
|
||||||
|
|
||||||
return errs
|
return errs, migrated
|
||||||
}
|
}
|
||||||
|
|
||||||
func v010_aliases(c *Cache) error {
|
func v010_aliases(c *Cache) (error, int) {
|
||||||
return errors.New("unimplemented migration")
|
var aliasesMigrated int
|
||||||
|
var errs error
|
||||||
|
for i, a := range c.Aliases {
|
||||||
|
if a.ID == "" {
|
||||||
|
if a.Remote == "" {
|
||||||
|
errs = errors.Join(errs,
|
||||||
|
fmt.Errorf("alias %s [id:%d] has no remote", a.Alias, a.ProjectID))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c.Aliases[i].ID = projects.MakeID(a.Remote, a.ProjectID)
|
||||||
|
aliasesMigrated++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errs, aliasesMigrated
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import (
|
|||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Git project metadata
|
||||||
|
// Do not use Project.ID directly (remotes may conflict), use Project.GetID()
|
||||||
type Project struct {
|
type Project struct {
|
||||||
ID int
|
ID int
|
||||||
Description string
|
Description string
|
||||||
@ -44,19 +46,30 @@ func (pl *ProjectLanguages) AddLanguage(lang *ProjectLanguage) {
|
|||||||
*pl = append(*pl, lang)
|
*pl = append(*pl, lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a unique ID using a short-sha of the http repo URL
|
// Gets a unique ID using a short-sha of the http repo
|
||||||
// along with the numerical ID of the project.
|
// along with the numerical ID of the project.
|
||||||
// Uses SSH URL and then Remote if previous is empty
|
// Uses SSH URL and then Remote if previous is empty
|
||||||
func (p *Project) GetID() string {
|
func (p *Project) GetID() string {
|
||||||
shaText := p.HTTPURLToRepo
|
return fmt.Sprintf("%s||%d", p.GetRemoteSha(), p.ID)
|
||||||
if shaText == "" && p.SSHURLToRepo != "" {
|
}
|
||||||
shaText = p.SSHURLToRepo
|
|
||||||
} else if shaText == "" {
|
func MakeID(remote string, projectID int) string {
|
||||||
shaText = p.Remote
|
return fmt.Sprintf("%s||%d", GetRemoteSha(remote), projectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Project) GetRemoteSha() string {
|
||||||
|
remote := p.Remote
|
||||||
|
if remote == "" && p.HTTPURLToRepo != "" {
|
||||||
|
remote = p.HTTPURLToRepo
|
||||||
|
} else if remote == "" && p.WebURL != "" {
|
||||||
|
remote = p.WebURL
|
||||||
}
|
}
|
||||||
|
|
||||||
shortSha := fmt.Sprintf("%x", sha1.Sum([]byte(shaText)))[:12]
|
return GetRemoteSha(remote)
|
||||||
return fmt.Sprintf("%s||%d", shortSha, p.ID)
|
}
|
||||||
|
|
||||||
|
func GetRemoteSha(remote string) string {
|
||||||
|
return fmt.Sprintf("%x", sha1.Sum([]byte(remote)))[:12]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Project) String() string {
|
func (p *Project) String() string {
|
||||||
|
Loading…
Reference in New Issue
Block a user