package store import ( "context" "fmt" "os" "time" "strings" "github.com/lithammer/shortuuid/v4" "github.com/pkg/errors" "github.com/usememos/memos/internal/log" ) // MigrateResourceInternalPath migrates resource internal path from absolute path to relative path. func (s *Store) MigrateResourceInternalPath(ctx context.Context) error { resources, err := s.ListResources(ctx, &FindResource{}) if err != nil { return errors.Wrap(err, "failed to list resources") } dataPath := strings.ReplaceAll(s.Profile.Data, `\`, "/") migrateStartTime := time.Now() migratedCount := 0 for _, resource := range resources { if resource.InternalPath == "" { continue } internalPath := strings.ReplaceAll(resource.InternalPath, `\`, "/") if !strings.HasPrefix(internalPath, dataPath) { continue } internalPath = strings.TrimPrefix(internalPath, dataPath) for os.IsPathSeparator(internalPath[0]) { internalPath = internalPath[1:] } _, err := s.UpdateResource(ctx, &UpdateResource{ ID: resource.ID, InternalPath: &internalPath, }) if err != nil { return errors.Wrap(err, "failed to update local resource path") } migratedCount++ } if migratedCount > 0 && s.Profile.Mode == "prod" { log.Info(fmt.Sprintf("migrated %d local resource paths in %s", migratedCount, time.Since(migrateStartTime))) } return nil } // MigrateResourceName migrates resource name from other format to short UUID. func (s *Store) MigrateResourceName(ctx context.Context) error { memos, err := s.ListMemos(ctx, &FindMemo{ ExcludeContent: true, }) if err != nil { return errors.Wrap(err, "failed to list memos") } for _, memo := range memos { if checkResourceName(memo.ResourceName) { continue } resourceName := shortuuid.New() err := s.UpdateMemo(ctx, &UpdateMemo{ ID: memo.ID, ResourceName: &resourceName, }) if err != nil { return errors.Wrap(err, "failed to update memo") } } resources, err := s.ListResources(ctx, &FindResource{}) if err != nil { return errors.Wrap(err, "failed to list resources") } for _, resource := range resources { if checkResourceName(resource.ResourceName) { continue } resourceName := shortuuid.New() _, err := s.UpdateResource(ctx, &UpdateResource{ ID: resource.ID, ResourceName: &resourceName, }) if err != nil { return errors.Wrap(err, "failed to update resource") } } return nil } func checkResourceName(resourceName string) bool { // 22 is the length of shortuuid. if len(resourceName) != 22 { return false } for _, c := range resourceName { if c >= '0' && c <= '9' { continue } if c >= 'a' && c <= 'z' { continue } if c >= 'A' && c <= 'Z' { continue } return false } return true }