util.go 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package model
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "github.com/calmh/syncthing/protocol"
  6. "github.com/calmh/syncthing/scanner"
  7. )
  8. func fileFromFileInfo(f protocol.FileInfo) scanner.File {
  9. var blocks = make([]scanner.Block, len(f.Blocks))
  10. var offset int64
  11. for i, b := range f.Blocks {
  12. blocks[i] = scanner.Block{
  13. Offset: offset,
  14. Size: b.Size,
  15. Hash: b.Hash,
  16. }
  17. offset += int64(b.Size)
  18. }
  19. return scanner.File{
  20. // Name is with native separator and normalization
  21. Name: filepath.FromSlash(f.Name),
  22. Size: offset,
  23. Flags: f.Flags &^ protocol.FlagInvalid,
  24. Modified: f.Modified,
  25. Version: f.Version,
  26. Blocks: blocks,
  27. Suppressed: f.Flags&protocol.FlagInvalid != 0,
  28. }
  29. }
  30. func fileInfoFromFile(f scanner.File) protocol.FileInfo {
  31. var blocks = make([]protocol.BlockInfo, len(f.Blocks))
  32. for i, b := range f.Blocks {
  33. blocks[i] = protocol.BlockInfo{
  34. Size: b.Size,
  35. Hash: b.Hash,
  36. }
  37. }
  38. pf := protocol.FileInfo{
  39. Name: filepath.ToSlash(f.Name),
  40. Flags: f.Flags,
  41. Modified: f.Modified,
  42. Version: f.Version,
  43. Blocks: blocks,
  44. }
  45. if f.Suppressed {
  46. pf.Flags |= protocol.FlagInvalid
  47. }
  48. return pf
  49. }
  50. func cmMap(cm protocol.ClusterConfigMessage) map[string]map[string]uint32 {
  51. m := make(map[string]map[string]uint32)
  52. for _, repo := range cm.Repositories {
  53. m[repo.ID] = make(map[string]uint32)
  54. for _, node := range repo.Nodes {
  55. m[repo.ID][node.ID] = node.Flags
  56. }
  57. }
  58. return m
  59. }
  60. type ClusterConfigMismatch error
  61. // compareClusterConfig returns nil for two equivalent configurations,
  62. // otherwise a decriptive error
  63. func compareClusterConfig(local, remote protocol.ClusterConfigMessage) error {
  64. lm := cmMap(local)
  65. rm := cmMap(remote)
  66. for repo, lnodes := range lm {
  67. _ = lnodes
  68. if rnodes, ok := rm[repo]; ok {
  69. for node, lflags := range lnodes {
  70. if rflags, ok := rnodes[node]; ok {
  71. if lflags&protocol.FlagShareBits != rflags&protocol.FlagShareBits {
  72. return ClusterConfigMismatch(fmt.Errorf("remote has different sharing flags for node %q in repository %q", node, repo))
  73. }
  74. }
  75. }
  76. } else {
  77. return ClusterConfigMismatch(fmt.Errorf("remote is missing repository %q", repo))
  78. }
  79. }
  80. for repo := range rm {
  81. if _, ok := lm[repo]; !ok {
  82. return ClusterConfigMismatch(fmt.Errorf("remote has extra repository %q", repo))
  83. }
  84. }
  85. return nil
  86. }