|
@@ -34,8 +34,9 @@ type VersionList struct {
|
|
|
Versions []*FileSnapshot
|
|
|
}
|
|
|
|
|
|
-func GetFileVersionData(realFilepath string) (*VersionList, error) {
|
|
|
- mtime, _ := filesystem.GetModTime(realFilepath)
|
|
|
+func GetFileVersionData(fsh *filesystem.FileSystemHandler, realFilepath string) (*VersionList, error) {
|
|
|
+ fshAbs := fsh.FileSystemAbstraction
|
|
|
+ mtime, _ := fshAbs.GetModTime(realFilepath)
|
|
|
versionList := VersionList{
|
|
|
CurrentFile: filepath.Base(realFilepath),
|
|
|
LatestModtime: mtime,
|
|
@@ -43,7 +44,7 @@ func GetFileVersionData(realFilepath string) (*VersionList, error) {
|
|
|
}
|
|
|
//Example folder structure: ./.localver/{date_time}/{file}
|
|
|
expectedVersionFiles := filepath.Join(filepath.Dir(realFilepath), ".metadata/.localver", "*", filepath.Base(realFilepath))
|
|
|
- versions, err := filepath.Glob(filepath.ToSlash(expectedVersionFiles))
|
|
|
+ versions, err := fshAbs.Glob(filepath.ToSlash(expectedVersionFiles))
|
|
|
if err != nil {
|
|
|
return &versionList, err
|
|
|
}
|
|
@@ -53,14 +54,14 @@ func GetFileVersionData(realFilepath string) (*VersionList, error) {
|
|
|
|
|
|
for _, version := range versions {
|
|
|
historyID := filepath.Base(filepath.Dir(version))
|
|
|
- mtime, _ := filesystem.GetModTime(version)
|
|
|
+ mtime, _ := fshAbs.GetModTime(version)
|
|
|
overwriteDisplayTime := strings.ReplaceAll(strings.Replace(strings.Replace(historyID, "-", "/", 2), "-", ":", 2), "_", " ")
|
|
|
versionList.Versions = append(versionList.Versions, &FileSnapshot{
|
|
|
HistoryID: historyID,
|
|
|
Filename: filepath.Base(version),
|
|
|
ModTime: mtime,
|
|
|
OverwriteTime: overwriteDisplayTime,
|
|
|
- Filesize: filesystem.GetFileSize(version),
|
|
|
+ Filesize: fshAbs.GetFileSize(version),
|
|
|
Relpath: ".metadata/.localver/" + historyID + "/" + filepath.Base(version),
|
|
|
})
|
|
|
}
|
|
@@ -68,31 +69,43 @@ func GetFileVersionData(realFilepath string) (*VersionList, error) {
|
|
|
return &versionList, nil
|
|
|
}
|
|
|
|
|
|
-func RestoreFileHistory(originalFilepath string, histroyID string) error {
|
|
|
+func RestoreFileHistory(fsh *filesystem.FileSystemHandler, originalFilepath string, histroyID string) error {
|
|
|
+ fshAbs := fsh.FileSystemAbstraction
|
|
|
expectedVersionFile := filepath.Join(filepath.Dir(originalFilepath), ".metadata/.localver", filepath.Base(histroyID), filepath.Base(originalFilepath))
|
|
|
- if !filesystem.FileExists(expectedVersionFile) {
|
|
|
+ if !fshAbs.FileExists(expectedVersionFile) {
|
|
|
return errors.New("File version not exists")
|
|
|
}
|
|
|
|
|
|
//Restore it
|
|
|
- os.Rename(originalFilepath, originalFilepath+".backup")
|
|
|
- filesystem.BasicFileCopy(expectedVersionFile, originalFilepath)
|
|
|
+ fshAbs.Rename(originalFilepath, originalFilepath+".backup")
|
|
|
+ srcf, err := fshAbs.ReadStream(expectedVersionFile)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ err = fshAbs.WriteStream(originalFilepath, srcf, 0775)
|
|
|
+ if err != nil {
|
|
|
+ srcf.Close()
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ srcf.Close()
|
|
|
|
|
|
//Check if it has been restored correctly
|
|
|
- versionFileHash, _ := filesystem.GetFileMD5Sum(expectedVersionFile)
|
|
|
- copiedFileHash, _ := filesystem.GetFileMD5Sum(expectedVersionFile)
|
|
|
+ versionFileHash, _ := filesystem.GetFileMD5Sum(fsh, expectedVersionFile)
|
|
|
+ copiedFileHash, _ := filesystem.GetFileMD5Sum(fsh, expectedVersionFile)
|
|
|
if versionFileHash != copiedFileHash {
|
|
|
//Rollback failed. Restore backup file
|
|
|
- os.Rename(originalFilepath+".backup", originalFilepath)
|
|
|
+ fshAbs.Rename(originalFilepath+".backup", originalFilepath)
|
|
|
return errors.New("Unable to restore file: file hash mismatch after restore")
|
|
|
}
|
|
|
|
|
|
//OK! Delete the backup file
|
|
|
- os.Remove(originalFilepath + ".backup")
|
|
|
+ fshAbs.Remove(originalFilepath + ".backup")
|
|
|
|
|
|
//Delete all history versions that is after the restored versions
|
|
|
expectedVersionFiles := filepath.Join(filepath.Dir(originalFilepath), ".metadata/.localver", "*", filepath.Base(originalFilepath))
|
|
|
- versions, err := filepath.Glob(filepath.ToSlash(expectedVersionFiles))
|
|
|
+ versions, err := fshAbs.Glob(filepath.ToSlash(expectedVersionFiles))
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
@@ -101,15 +114,22 @@ func RestoreFileHistory(originalFilepath string, histroyID string) error {
|
|
|
for _, version := range versions {
|
|
|
if enableRemoval {
|
|
|
//Remove this version as this is after the restored version
|
|
|
- os.Remove(version)
|
|
|
+ fshAbs.Remove(version)
|
|
|
+ fileInVersion, _ := fshAbs.Glob(filepath.ToSlash(filepath.Dir(version) + "/*"))
|
|
|
+ if len(fileInVersion) == 0 {
|
|
|
+ fshAbs.RemoveAll(filepath.Dir(version))
|
|
|
+ }
|
|
|
} else {
|
|
|
thisHistoryId := filepath.Base(filepath.Dir(version))
|
|
|
if thisHistoryId == histroyID {
|
|
|
//Match. Tag enable Removal
|
|
|
enableRemoval = true
|
|
|
-
|
|
|
//Remove this version
|
|
|
- os.Remove(version)
|
|
|
+ fshAbs.Remove(version)
|
|
|
+ fileInVersion, _ := fshAbs.Glob(filepath.ToSlash(filepath.Dir(version) + "/*"))
|
|
|
+ if len(fileInVersion) == 0 {
|
|
|
+ fshAbs.RemoveAll(filepath.Dir(version))
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -118,17 +138,17 @@ func RestoreFileHistory(originalFilepath string, histroyID string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func RemoveFileHistory(originalFilepath string, histroyID string) error {
|
|
|
+func RemoveFileHistory(fsh *filesystem.FileSystemHandler, originalFilepath string, histroyID string) error {
|
|
|
expectedVersionFile := filepath.Join(filepath.Dir(originalFilepath), ".metadata/.localver", filepath.Base(histroyID), filepath.Base(originalFilepath))
|
|
|
- if !filesystem.FileExists(expectedVersionFile) {
|
|
|
+ if !fsh.FileSystemAbstraction.FileExists(expectedVersionFile) {
|
|
|
return errors.New("File version not exists")
|
|
|
}
|
|
|
|
|
|
- return os.Remove(expectedVersionFile)
|
|
|
+ return fsh.FileSystemAbstraction.Remove(expectedVersionFile)
|
|
|
}
|
|
|
|
|
|
-func RemoveAllRelatedFileHistory(originalFilepath string) error {
|
|
|
- expectedVersionFiles, err := filepath.Glob(filepath.Join(filepath.Dir(originalFilepath), ".metadata/.localver", "*", filepath.Base(originalFilepath)))
|
|
|
+func RemoveAllRelatedFileHistory(fsh *filesystem.FileSystemHandler, originalFilepath string) error {
|
|
|
+ expectedVersionFiles, err := fsh.FileSystemAbstraction.Glob(filepath.Join(filepath.Dir(originalFilepath), ".metadata/.localver", "*", filepath.Base(originalFilepath)))
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
@@ -138,26 +158,33 @@ func RemoveAllRelatedFileHistory(originalFilepath string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func CreateFileSnapshot(realFilepath string) error {
|
|
|
- if !filesystem.FileExists(realFilepath) {
|
|
|
+func CreateFileSnapshot(fsh *filesystem.FileSystemHandler, realFilepath string) error {
|
|
|
+ fshAbs := fsh.FileSystemAbstraction
|
|
|
+ if !fshAbs.FileExists(realFilepath) {
|
|
|
return errors.New("Source file not exists")
|
|
|
}
|
|
|
//Create the snapshot folder for this file
|
|
|
snapshotID := time.Now().Format("2006-01-02_15-04-05")
|
|
|
expectedSnapshotFolder := filepath.Join(filepath.Dir(realFilepath), ".metadata/.localver", snapshotID)
|
|
|
- err := os.MkdirAll(expectedSnapshotFolder, 0775)
|
|
|
+ err := fshAbs.MkdirAll(expectedSnapshotFolder, 0775)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
//Copy the target file to snapshot dir
|
|
|
targetVersionFilepath := filepath.Join(expectedSnapshotFolder, filepath.Base(realFilepath))
|
|
|
- return filesystem.BasicFileCopy(realFilepath, targetVersionFilepath)
|
|
|
+ srcf, err := fshAbs.ReadStream(realFilepath)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ defer srcf.Close()
|
|
|
+ return fshAbs.WriteStream(targetVersionFilepath, srcf, 0775)
|
|
|
}
|
|
|
|
|
|
//Clearn expired version backups that is older than maxReserveTime
|
|
|
-func CleanExpiredVersionBackups(walkRoot string, maxReserveTime int64) {
|
|
|
+func CleanExpiredVersionBackups(fsh *filesystem.FileSystemHandler, walkRoot string, maxReserveTime int64) {
|
|
|
+ fshAbs := fsh.FileSystemAbstraction
|
|
|
localVerFolders := []string{}
|
|
|
- filepath.Walk(walkRoot,
|
|
|
+ fshAbs.Walk(walkRoot,
|
|
|
func(path string, info os.FileInfo, err error) error {
|
|
|
if err != nil {
|
|
|
//Skip this file
|
|
@@ -165,16 +192,16 @@ func CleanExpiredVersionBackups(walkRoot string, maxReserveTime int64) {
|
|
|
}
|
|
|
if !info.IsDir() && inLocalVersionFolder(path) {
|
|
|
//This is a file inside the localver folder. Check its modtime
|
|
|
- mtime, _ := filesystem.GetModTime(path)
|
|
|
+ mtime, _ := fshAbs.GetModTime(path)
|
|
|
if time.Now().Unix()-mtime > maxReserveTime {
|
|
|
//Too old! Remove this version history
|
|
|
- os.Remove(path)
|
|
|
+ fshAbs.Remove(path)
|
|
|
}
|
|
|
|
|
|
//Check if the folder still contains files. If not, remove it
|
|
|
- files, _ := filepath.Glob(filepath.ToSlash(filepath.Dir(path)) + "/*")
|
|
|
+ files, _ := fshAbs.Glob(filepath.ToSlash(filepath.Dir(path)) + "/*")
|
|
|
if len(files) == 0 {
|
|
|
- os.RemoveAll(filepath.Dir(path))
|
|
|
+ fshAbs.RemoveAll(filepath.Dir(path))
|
|
|
}
|
|
|
} else if info.IsDir() && filepath.Base(path) == ".localver" {
|
|
|
localVerFolders = append(localVerFolders, path)
|
|
@@ -185,9 +212,9 @@ func CleanExpiredVersionBackups(walkRoot string, maxReserveTime int64) {
|
|
|
|
|
|
for _, path := range localVerFolders {
|
|
|
//Check if a localver folder still contains folder. If not, delete this
|
|
|
- files, _ := filepath.Glob(filepath.ToSlash(path) + "/*")
|
|
|
+ files, _ := fshAbs.Glob(filepath.ToSlash(path) + "/*")
|
|
|
if len(files) == 0 {
|
|
|
- os.RemoveAll(path)
|
|
|
+ fshAbs.RemoveAll(path)
|
|
|
}
|
|
|
}
|
|
|
}
|