1package migrate23import (4 "context"5 "os"6 "path/filepath"7 "strconv"89 "github.com/charmbracelet/log/v2"10 "github.com/charmbracelet/soft-serve/pkg/config"11 "github.com/charmbracelet/soft-serve/pkg/db"12 "github.com/charmbracelet/soft-serve/pkg/db/models"13)1415const (16 migrateLfsObjectsName = "migrate_lfs_objects"17 migrateLfsObjectsVersion = 318)1920// Correct LFS objects relative path.21// From OID[:2]/OID[2:4]/OID[4:] to OID[:2]/OID[2:4]/OID22// See: https://github.com/git-lfs/git-lfs/blob/main/docs/spec.md#intercepting-git23var migrateLfsObjects = Migration{24 Name: migrateLfsObjectsName,25 Version: migrateLfsObjectsVersion,26 Migrate: func(ctx context.Context, tx *db.Tx) error {27 cfg := config.FromContext(ctx)28 logger := log.FromContext(ctx).WithPrefix("migrate_lfs_objects")2930 var repoIDs []int6431 if err := tx.Select(&repoIDs, "SELECT id FROM repos"); err != nil {32 return err33 }34 for _, r := range repoIDs {35 var objs []models.LFSObject36 if err := tx.Select(&objs, "SELECT * FROM lfs_objects WHERE repo_id = ?", r); err != nil {37 return err38 }39 objsp := filepath.Join(cfg.DataPath, "lfs", strconv.FormatInt(r, 10), "objects")40 for _, obj := range objs {41 oldpath := filepath.Join(objsp, badRelativePath(obj.Oid))42 newpath := filepath.Join(objsp, goodRelativePath(obj.Oid))43 if _, err := os.Stat(oldpath); err == nil {44 if err := os.Rename(oldpath, newpath); err != nil {45 logger.Error("rename lfs object", "oldpath", oldpath, "newpath", newpath, "err", err)46 continue47 }48 }49 }50 }51 return nil52 },53 Rollback: func(context.Context, *db.Tx) error {54 return nil55 },56}5758func goodRelativePath(oid string) string {59 if len(oid) < 5 {60 return oid61 }62 return filepath.Join(oid[:2], oid[2:4], oid)63}6465func badRelativePath(oid string) string {66 if len(oid) < 5 {67 return oid68 }69 return filepath.Join(oid[:2], oid[2:4], oid[4:])70}