localversion.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. package localversion
  2. import (
  3. "errors"
  4. "os"
  5. "path/filepath"
  6. "sort"
  7. "strings"
  8. "imuslab.com/arozos/mod/filesystem"
  9. )
  10. /*
  11. localversion.go
  12. This is a local version management module for arozos files
  13. Author: tobychui
  14. */
  15. type FileSnapshot struct {
  16. HistoryID string
  17. Filename string
  18. ModTime int64
  19. OverwriteTime string
  20. Filesize int64
  21. Relpath string
  22. }
  23. type VersionList struct {
  24. CurrentFile string
  25. LatestModtime int64
  26. Versions []*FileSnapshot
  27. }
  28. func GetFileVersionData(realFilepath string) (*VersionList, error) {
  29. mtime, _ := filesystem.GetModTime(realFilepath)
  30. versionList := VersionList{
  31. CurrentFile: filepath.Base(realFilepath),
  32. LatestModtime: mtime,
  33. Versions: []*FileSnapshot{},
  34. }
  35. //Example folder structure: ./.localver/{date_time}/{file}
  36. expectedVersionFiles := filepath.Join(filepath.Dir(realFilepath), ".localver", "*", filepath.Base(realFilepath))
  37. versions, err := filepath.Glob(filepath.ToSlash(expectedVersionFiles))
  38. if err != nil {
  39. return &versionList, err
  40. }
  41. //Reverse the versions so latest version on top
  42. sort.Sort(sort.Reverse(sort.StringSlice(versions)))
  43. for _, version := range versions {
  44. historyID := filepath.Base(filepath.Dir(version))
  45. mtime, _ := filesystem.GetModTime(version)
  46. overwriteDisplayTime := strings.ReplaceAll(strings.Replace(strings.Replace(historyID, "-", "/", 2), "-", ":", 2), "_", " ")
  47. versionList.Versions = append(versionList.Versions, &FileSnapshot{
  48. HistoryID: historyID,
  49. Filename: filepath.Base(version),
  50. ModTime: mtime,
  51. OverwriteTime: overwriteDisplayTime,
  52. Filesize: filesystem.GetFileSize(version),
  53. Relpath: ".localver/" + historyID + "/" + filepath.Base(version),
  54. })
  55. }
  56. return &versionList, nil
  57. }
  58. func RestoreFileHistory(originalFilepath string, histroyID string) error {
  59. expectedVersionFile := filepath.Join(filepath.Dir(originalFilepath), ".localver", filepath.Base(histroyID), filepath.Base(originalFilepath))
  60. if !filesystem.FileExists(expectedVersionFile) {
  61. return errors.New("File version not exists")
  62. }
  63. //Restore it
  64. os.Rename(originalFilepath, originalFilepath+".backup")
  65. filesystem.BasicFileCopy(expectedVersionFile, originalFilepath)
  66. //Check if it has been restored correctly
  67. versionFileHash, _ := filesystem.GetFileMD5Sum(expectedVersionFile)
  68. copiedFileHash, _ := filesystem.GetFileMD5Sum(expectedVersionFile)
  69. if versionFileHash != copiedFileHash {
  70. //Rollback failed. Restore backup file
  71. os.Rename(originalFilepath+".backup", originalFilepath)
  72. return errors.New("Unable to restore file: file hash mismatch after restore")
  73. }
  74. //OK! Delete the backup file
  75. os.Remove(originalFilepath + ".backup")
  76. //Delete all history versions that is after the restored versions
  77. expectedVersionFiles := filepath.Join(filepath.Dir(originalFilepath), ".localver", "*", filepath.Base(originalFilepath))
  78. versions, err := filepath.Glob(filepath.ToSlash(expectedVersionFiles))
  79. if err != nil {
  80. return err
  81. }
  82. enableRemoval := false
  83. for _, version := range versions {
  84. if enableRemoval {
  85. //Remove this version as this is after the restored version
  86. os.Remove(version)
  87. } else {
  88. thisHistoryId := filepath.Base(filepath.Dir(version))
  89. if thisHistoryId == histroyID {
  90. //Match. Tag enable Removal
  91. enableRemoval = true
  92. //Remove this version
  93. os.Remove(version)
  94. }
  95. }
  96. }
  97. return nil
  98. }
  99. func RemoveFileHistory(originalFilepath string, histroyID string) error {
  100. return nil
  101. }
  102. func CreateFileSnapshot(realFilepath string) error {
  103. return nil
  104. }