tree_item.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * Rufs - Remote Union File System
  3. *
  4. * Copyright 2017 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package rufs
  11. import (
  12. "bytes"
  13. "fmt"
  14. "path"
  15. "sort"
  16. "devt.de/krotik/common/errorutil"
  17. "devt.de/krotik/common/stringutil"
  18. )
  19. /*
  20. treeItem models an item in the tree. This is an internal data structure
  21. which is not exposed.
  22. */
  23. type treeItem struct {
  24. children map[string]*treeItem // Mapping from path component to branch
  25. remoteBranches []string // List of remote branches which are present on this level
  26. remoteBranchWriting []bool // Flag if the remote branch should receive write requests
  27. }
  28. /*
  29. findPathBranches finds all relevant branches for a single path. The iterator
  30. function receives 4 parameters: The tree item, the total path within the tree,
  31. the subpath within the branch and a list of all branches for the tree path.
  32. Calling code should always give a treePath of "/".
  33. */
  34. func (t *treeItem) findPathBranches(treePath string, branchPath []string,
  35. recursive bool, visit func(*treeItem, string, []string, []string, []bool)) {
  36. visit(t, treePath, branchPath, t.remoteBranches, t.remoteBranchWriting)
  37. if len(branchPath) > 0 {
  38. if c, ok := t.children[branchPath[0]]; ok {
  39. // Check if a subpath matches
  40. c.findPathBranches(path.Join(treePath, branchPath[0]),
  41. branchPath[1:], recursive, visit)
  42. }
  43. } else if recursive {
  44. var childNames []string
  45. for n := range t.children {
  46. childNames = append(childNames, n)
  47. }
  48. sort.Strings(childNames)
  49. for _, n := range childNames {
  50. t.children[n].findPathBranches(path.Join(treePath, n),
  51. branchPath, recursive, visit)
  52. }
  53. }
  54. }
  55. /*
  56. addMapping adds a new mapping.
  57. */
  58. func (t *treeItem) addMapping(mappingPath []string, branchName string, writable bool) {
  59. // Add mapping to a child
  60. if len(mappingPath) > 0 {
  61. childName := mappingPath[0]
  62. rest := mappingPath[1:]
  63. errorutil.AssertTrue(childName != "",
  64. "Adding a mapping with an empty path is not supported")
  65. // Ensure child exists
  66. child, ok := t.children[childName]
  67. if !ok {
  68. child = &treeItem{make(map[string]*treeItem), []string{}, []bool{}}
  69. t.children[childName] = child
  70. }
  71. // Add rest of the mapping to the child
  72. child.addMapping(rest, branchName, writable)
  73. return
  74. }
  75. // Add branch name to this branch - keep the order in which the branches were added
  76. t.remoteBranches = append(t.remoteBranches, branchName)
  77. t.remoteBranchWriting = append(t.remoteBranchWriting, writable)
  78. }
  79. /*
  80. String returns a string representation of this item and its children.
  81. */
  82. func (t *treeItem) String(indent int, buf *bytes.Buffer) {
  83. for i, b := range t.remoteBranches {
  84. buf.WriteString(b)
  85. if t.remoteBranchWriting[i] {
  86. buf.WriteString("(w)")
  87. } else {
  88. buf.WriteString("(r)")
  89. }
  90. if i < len(t.remoteBranches)-1 {
  91. buf.WriteString(", ")
  92. }
  93. }
  94. buf.WriteString("\n")
  95. names := make([]string, 0, len(t.children))
  96. for n := range t.children {
  97. names = append(names, n)
  98. }
  99. sort.Strings(names)
  100. for _, n := range names {
  101. i := t.children[n]
  102. buf.WriteString(stringutil.GenerateRollingString(" ", indent*2))
  103. buf.WriteString(fmt.Sprintf("%v/: ", n))
  104. i.String(indent+1, buf)
  105. }
  106. }