diff options
author | Jakob Borg <jakob@nym.se> | 2014-05-25 20:49:08 +0200 |
---|---|---|
committer | Jakob Borg <jakob@nym.se> | 2014-05-25 20:49:08 +0200 |
commit | 3d055bbb79166e3dfe35d496ddd0fc94fd2f7563 (patch) | |
tree | fcb5aed5d6d654a088b2683c8a34d291f25561e7 /versioner | |
parent | dd971b56e502795310bb4e24b8df4998e38f7a14 (diff) |
Simple file versioning (fixes #218)
Diffstat (limited to 'versioner')
-rw-r--r-- | versioner/debug.go | 13 | ||||
-rw-r--r-- | versioner/simple.go | 84 | ||||
-rw-r--r-- | versioner/versioner.go | 7 |
3 files changed, 104 insertions, 0 deletions
diff --git a/versioner/debug.go b/versioner/debug.go new file mode 100644 index 0000000000..6b5fda4273 --- /dev/null +++ b/versioner/debug.go @@ -0,0 +1,13 @@ +package versioner + +import ( + "os" + "strings" + + "github.com/calmh/syncthing/logger" +) + +var ( + debug = strings.Contains(os.Getenv("STTRACE"), "versioner") || os.Getenv("STTRACE") == "all" + l = logger.DefaultLogger +) diff --git a/versioner/simple.go b/versioner/simple.go new file mode 100644 index 0000000000..c1f36eb485 --- /dev/null +++ b/versioner/simple.go @@ -0,0 +1,84 @@ +package versioner + +import ( + "os" + "path/filepath" + "sort" + "strconv" + "time" + + "github.com/calmh/syncthing/osutil" +) + +func init() { + // Register the constructor for this type of versioner with the name "simple" + Factories["simple"] = NewSimple +} + +// The type holds our configuration +type Simple struct { + keep int +} + +// The constructor function takes a map of parameters and creates the type. +func NewSimple(params map[string]string) Versioner { + keep, err := strconv.Atoi(params["keep"]) + if err != nil { + keep = 5 // A reasonable default + } + + s := Simple{ + keep: keep, + } + + if debug { + l.Debugf("instantiated %#v", s) + } + return s +} + +// Move away the named file to a version archive. If this function returns +// nil, the named file does not exist any more (has been archived). +func (v Simple) Archive(path string) error { + _, err := os.Stat(path) + if err != nil && os.IsNotExist(err) { + return nil + } + + if debug { + l.Debugln("archiving", path) + } + + file := filepath.Base(path) + dir := filepath.Join(filepath.Dir(path), ".stversions") + err = os.MkdirAll(dir, 0755) + if err != nil && !os.IsExist(err) { + return err + } else { + osutil.HideFile(dir) + } + + ver := file + "~" + time.Now().Format("20060102-150405") + err = osutil.Rename(path, filepath.Join(dir, ver)) + if err != nil { + return err + } + + versions, err := filepath.Glob(filepath.Join(dir, file+"~*")) + if err != nil { + l.Warnln(err) + return nil + } + + if len(versions) > v.keep { + sort.Strings(versions) + for _, toRemove := range versions[:len(versions)-v.keep] { + err = os.Remove(toRemove) + if err != nil { + l.Warnln(err) + } + } + } + + return nil +} diff --git a/versioner/versioner.go b/versioner/versioner.go new file mode 100644 index 0000000000..19cb7c71c8 --- /dev/null +++ b/versioner/versioner.go @@ -0,0 +1,7 @@ +package versioner + +type Versioner interface { + Archive(path string) error +} + +var Factories = map[string]func(map[string]string) Versioner{} |