migrator.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package store
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "time"
  7. "strings"
  8. "github.com/lithammer/shortuuid/v4"
  9. "github.com/pkg/errors"
  10. "github.com/usememos/memos/internal/log"
  11. )
  12. // MigrateResourceInternalPath migrates resource internal path from absolute path to relative path.
  13. func (s *Store) MigrateResourceInternalPath(ctx context.Context) error {
  14. resources, err := s.ListResources(ctx, &FindResource{})
  15. if err != nil {
  16. return errors.Wrap(err, "failed to list resources")
  17. }
  18. dataPath := strings.ReplaceAll(s.Profile.Data, `\`, "/")
  19. migrateStartTime := time.Now()
  20. migratedCount := 0
  21. for _, resource := range resources {
  22. if resource.InternalPath == "" {
  23. continue
  24. }
  25. internalPath := strings.ReplaceAll(resource.InternalPath, `\`, "/")
  26. if !strings.HasPrefix(internalPath, dataPath) {
  27. continue
  28. }
  29. internalPath = strings.TrimPrefix(internalPath, dataPath)
  30. for os.IsPathSeparator(internalPath[0]) {
  31. internalPath = internalPath[1:]
  32. }
  33. _, err := s.UpdateResource(ctx, &UpdateResource{
  34. ID: resource.ID,
  35. InternalPath: &internalPath,
  36. })
  37. if err != nil {
  38. return errors.Wrap(err, "failed to update local resource path")
  39. }
  40. migratedCount++
  41. }
  42. if migratedCount > 0 && s.Profile.Mode == "prod" {
  43. log.Info(fmt.Sprintf("migrated %d local resource paths in %s", migratedCount, time.Since(migrateStartTime)))
  44. }
  45. return nil
  46. }
  47. // MigrateResourceName migrates resource name from other format to short UUID.
  48. func (s *Store) MigrateResourceName(ctx context.Context) error {
  49. memos, err := s.ListMemos(ctx, &FindMemo{
  50. ExcludeContent: true,
  51. })
  52. if err != nil {
  53. return errors.Wrap(err, "failed to list memos")
  54. }
  55. for _, memo := range memos {
  56. if checkResourceName(memo.ResourceName) {
  57. continue
  58. }
  59. resourceName := shortuuid.New()
  60. err := s.UpdateMemo(ctx, &UpdateMemo{
  61. ID: memo.ID,
  62. ResourceName: &resourceName,
  63. })
  64. if err != nil {
  65. return errors.Wrap(err, "failed to update memo")
  66. }
  67. }
  68. resources, err := s.ListResources(ctx, &FindResource{})
  69. if err != nil {
  70. return errors.Wrap(err, "failed to list resources")
  71. }
  72. for _, resource := range resources {
  73. if checkResourceName(resource.ResourceName) {
  74. continue
  75. }
  76. resourceName := shortuuid.New()
  77. _, err := s.UpdateResource(ctx, &UpdateResource{
  78. ID: resource.ID,
  79. ResourceName: &resourceName,
  80. })
  81. if err != nil {
  82. return errors.Wrap(err, "failed to update resource")
  83. }
  84. }
  85. return nil
  86. }
  87. func checkResourceName(resourceName string) bool {
  88. // 22 is the length of shortuuid.
  89. if len(resourceName) != 22 {
  90. return false
  91. }
  92. for _, c := range resourceName {
  93. if c >= '0' && c <= '9' {
  94. continue
  95. }
  96. if c >= 'a' && c <= 'z' {
  97. continue
  98. }
  99. if c >= 'A' && c <= 'Z' {
  100. continue
  101. }
  102. return false
  103. }
  104. return true
  105. }