lib/versioner: Restore for all versioners, cross-device support (#5514)

* lib/versioner: Restore for all versioners, cross-device support

Fixes #4631
Fixes #4586
Fixes #1634
Fixes #5338
Fixes #5419
This commit is contained in:
Audrius Butkevicius
2019-04-28 23:30:16 +01:00
committed by GitHub
parent 2984d40641
commit 0ca1f26ff8
14 changed files with 636 additions and 289 deletions

View File

@@ -7,7 +7,6 @@
package versioner
import (
"os"
"path/filepath"
"strconv"
"time"
@@ -48,16 +47,9 @@ func NewStaggered(folderID string, folderFs fs.Filesystem, params map[string]str
cleanInterval = 3600 // Default: clean once per hour
}
// Use custom path if set, otherwise .stversions in folderPath
var versionsFs fs.Filesystem
if params["versionsPath"] == "" {
versionsFs = fs.NewFilesystem(folderFs.Type(), filepath.Join(folderFs.URI(), ".stversions"))
} else if filepath.IsAbs(params["versionsPath"]) {
versionsFs = fs.NewFilesystem(folderFs.Type(), params["versionsPath"])
} else {
versionsFs = fs.NewFilesystem(folderFs.Type(), filepath.Join(folderFs.URI(), params["versionsPath"]))
}
l.Debugln("%s folder using %s (%s) staggered versioner dir", folderID, versionsFs.URI(), versionsFs.Type())
// Backwards compatibility
params["fsPath"] = params["versionsPath"]
versionsFs := fsFromParams(folderFs, params)
s := &Staggered{
cleanInterval: cleanInterval,
@@ -225,53 +217,12 @@ func (v *Staggered) Archive(filePath string) error {
v.mutex.Lock()
defer v.mutex.Unlock()
info, err := v.folderFs.Lstat(filePath)
if fs.IsNotExist(err) {
l.Debugln("not archiving nonexistent file", filePath)
return nil
} else if err != nil {
if err := archiveFile(v.folderFs, v.versionsFs, filePath, TagFilename); err != nil {
return err
}
if info.IsSymlink() {
panic("bug: attempting to version a symlink")
}
if _, err := v.versionsFs.Stat("."); err != nil {
if fs.IsNotExist(err) {
l.Debugln("creating versions dir", v.versionsFs)
v.versionsFs.MkdirAll(".", 0755)
v.versionsFs.Hide(".")
} else {
return err
}
}
l.Debugln("archiving", filePath)
file := filepath.Base(filePath)
inFolderPath := filepath.Dir(filePath)
if err != nil {
return err
}
err = v.versionsFs.MkdirAll(inFolderPath, 0755)
if err != nil && !fs.IsExist(err) {
return err
}
ver := TagFilename(file, time.Now().Format(TimeFormat))
dst := filepath.Join(inFolderPath, ver)
l.Debugln("moving to", dst)
/// TODO: Fix this when we have an alternative filesystem implementation
if v.versionsFs.Type() != fs.FilesystemTypeBasic {
panic("bug: staggered versioner used with unsupported filesystem")
}
err = os.Rename(filepath.Join(v.folderFs.URI(), filePath), filepath.Join(v.versionsFs.URI(), dst))
if err != nil {
return err
}
// Glob according to the new file~timestamp.ext pattern.
pattern := filepath.Join(inFolderPath, TagFilename(file, TimeGlob))
@@ -295,3 +246,11 @@ func (v *Staggered) Archive(filePath string) error {
return nil
}
func (v *Staggered) GetVersions() (map[string][]FileVersion, error) {
return retrieveVersions(v.versionsFs)
}
func (v *Staggered) Restore(filepath string, versionTime time.Time) error {
return restoreFile(v.versionsFs, v.folderFs, filepath, versionTime, TagFilename)
}