package cache import ( "errors" "fmt" "golang.org/x/mod/semver" "gitea.libretechconsulting.com/rmcguire/git-project-manager/internal/remotes/projects" ) // Migrations funcs should return errors along with // number of records updated type migrationFunc func(c *Cache) (error, int) // Registry of migrations by version var migrations = map[string]map[string]migrationFunc{ "v0.1.0": { "Make Aliases Unique": v010_aliases, }, } // Performs any required updates based on version // of cache read from disk. // Does not check to ensure migrations were successful, // only checks if a version has been achieved func (c *Cache) DoMigrations() (error, int) { c.lock.Lock() defer c.lock.Unlock() return c.doMigrations() } func (c *Cache) doMigrations() (error, int) { var errs error var migrated int for version, migrationFuncs := range migrations { var funcMigrated int if semver.Compare(c.CacheVersion, version) < 0 { for name, migration := range migrationFuncs { err, numMigrated := migration(c) if err != nil { errs = errors.Join( errs, fmt.Errorf("%s - %s: %w", version, name, err), ) } funcMigrated += numMigrated } // We've reached a cache version, update the CacheVersion // and write to disk if errs == nil && funcMigrated > 0 { c.CacheVersion = version c.write() } } migrated += funcMigrated } return errs, migrated } func v010_aliases(c *Cache) (error, int) { 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 }