simple.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
  2. // Use of this source code is governed by an MIT-style license that can be
  3. // found in the LICENSE file.
  4. package versioner
  5. import (
  6. "os"
  7. "path/filepath"
  8. "sort"
  9. "strconv"
  10. "time"
  11. "github.com/calmh/syncthing/osutil"
  12. )
  13. func init() {
  14. // Register the constructor for this type of versioner with the name "simple"
  15. Factories["simple"] = NewSimple
  16. }
  17. // The type holds our configuration
  18. type Simple struct {
  19. keep int
  20. }
  21. // The constructor function takes a map of parameters and creates the type.
  22. func NewSimple(params map[string]string) Versioner {
  23. keep, err := strconv.Atoi(params["keep"])
  24. if err != nil {
  25. keep = 5 // A reasonable default
  26. }
  27. s := Simple{
  28. keep: keep,
  29. }
  30. if debug {
  31. l.Debugf("instantiated %#v", s)
  32. }
  33. return s
  34. }
  35. // Move away the named file to a version archive. If this function returns
  36. // nil, the named file does not exist any more (has been archived).
  37. func (v Simple) Archive(path string) error {
  38. _, err := os.Stat(path)
  39. if err != nil && os.IsNotExist(err) {
  40. return nil
  41. }
  42. if debug {
  43. l.Debugln("archiving", path)
  44. }
  45. file := filepath.Base(path)
  46. dir := filepath.Join(filepath.Dir(path), ".stversions")
  47. err = os.MkdirAll(dir, 0755)
  48. if err != nil && !os.IsExist(err) {
  49. return err
  50. } else {
  51. osutil.HideFile(dir)
  52. }
  53. ver := file + "~" + time.Now().Format("20060102-150405")
  54. err = osutil.Rename(path, filepath.Join(dir, ver))
  55. if err != nil {
  56. return err
  57. }
  58. versions, err := filepath.Glob(filepath.Join(dir, file+"~*"))
  59. if err != nil {
  60. l.Warnln(err)
  61. return nil
  62. }
  63. if len(versions) > v.keep {
  64. sort.Strings(versions)
  65. for _, toRemove := range versions[:len(versions)-v.keep] {
  66. err = os.Remove(toRemove)
  67. if err != nil {
  68. l.Warnln(err)
  69. }
  70. }
  71. }
  72. return nil
  73. }