folderconfiguration.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package config
  7. import (
  8. "os"
  9. "path/filepath"
  10. "runtime"
  11. "strings"
  12. "github.com/syncthing/syncthing/lib/osutil"
  13. "github.com/syncthing/syncthing/lib/protocol"
  14. )
  15. type FolderConfiguration struct {
  16. ID string `xml:"id,attr" json:"id"`
  17. RawPath string `xml:"path,attr" json:"path"`
  18. Devices []FolderDeviceConfiguration `xml:"device" json:"devices"`
  19. ReadOnly bool `xml:"ro,attr" json:"readOnly"`
  20. RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"`
  21. IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"`
  22. AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"`
  23. MinDiskFreePct float64 `xml:"minDiskFreePct" json:"minDiskFreePct"`
  24. Versioning VersioningConfiguration `xml:"versioning" json:"versioning"`
  25. Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently.
  26. Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines.
  27. Hashers int `xml:"hashers" json:"hashers"` // Less than one sets the value to the number of cores. These are CPU bound due to hashing.
  28. Order PullOrder `xml:"order" json:"order"`
  29. IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"`
  30. ScanProgressIntervalS int `xml:"scanProgressIntervalS" json:"scanProgressIntervalS"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value)
  31. PullerSleepS int `xml:"pullerSleepS" json:"pullerSleepS"`
  32. PullerPauseS int `xml:"pullerPauseS" json:"pullerPauseS"`
  33. MaxConflicts int `xml:"maxConflicts" json:"maxConflicts"`
  34. Invalid string `xml:"-" json:"invalid"` // Set at runtime when there is an error, not saved
  35. }
  36. type FolderDeviceConfiguration struct {
  37. DeviceID protocol.DeviceID `xml:"id,attr" json:"deviceID"`
  38. }
  39. func (f FolderConfiguration) Copy() FolderConfiguration {
  40. c := f
  41. c.Devices = make([]FolderDeviceConfiguration, len(f.Devices))
  42. copy(c.Devices, f.Devices)
  43. c.Versioning = f.Versioning.Copy()
  44. return c
  45. }
  46. func (f FolderConfiguration) Path() string {
  47. // This is intentionally not a pointer method, because things like
  48. // cfg.Folders["default"].Path() should be valid.
  49. // Attempt tilde expansion; leave unchanged in case of error
  50. if path, err := osutil.ExpandTilde(f.RawPath); err == nil {
  51. f.RawPath = path
  52. }
  53. // Attempt absolutification; leave unchanged in case of error
  54. if !filepath.IsAbs(f.RawPath) {
  55. // Abs() looks like a fairly expensive syscall on Windows, while
  56. // IsAbs() is a whole bunch of string mangling. I think IsAbs() may be
  57. // somewhat faster in the general case, hence the outer if...
  58. if path, err := filepath.Abs(f.RawPath); err == nil {
  59. f.RawPath = path
  60. }
  61. }
  62. // Attempt to enable long filename support on Windows. We may still not
  63. // have an absolute path here if the previous steps failed.
  64. if runtime.GOOS == "windows" && filepath.IsAbs(f.RawPath) && !strings.HasPrefix(f.RawPath, `\\`) {
  65. return `\\?\` + f.RawPath
  66. }
  67. return f.RawPath
  68. }
  69. func (f *FolderConfiguration) CreateMarker() error {
  70. if !f.HasMarker() {
  71. marker := filepath.Join(f.Path(), ".stfolder")
  72. fd, err := os.Create(marker)
  73. if err != nil {
  74. return err
  75. }
  76. fd.Close()
  77. osutil.HideFile(marker)
  78. }
  79. return nil
  80. }
  81. func (f *FolderConfiguration) HasMarker() bool {
  82. _, err := os.Stat(filepath.Join(f.Path(), ".stfolder"))
  83. if err != nil {
  84. return false
  85. }
  86. return true
  87. }
  88. func (f *FolderConfiguration) DeviceIDs() []protocol.DeviceID {
  89. deviceIDs := make([]protocol.DeviceID, len(f.Devices))
  90. for i, n := range f.Devices {
  91. deviceIDs[i] = n.DeviceID
  92. }
  93. return deviceIDs
  94. }
  95. type FolderDeviceConfigurationList []FolderDeviceConfiguration
  96. func (l FolderDeviceConfigurationList) Less(a, b int) bool {
  97. return l[a].DeviceID.Compare(l[b].DeviceID) == -1
  98. }
  99. func (l FolderDeviceConfigurationList) Swap(a, b int) {
  100. l[a], l[b] = l[b], l[a]
  101. }
  102. func (l FolderDeviceConfigurationList) Len() int {
  103. return len(l)
  104. }