123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- /*
- * Rufs - Remote Union File System
- *
- * Copyright 2017 Matthias Ladkau. All rights reserved.
- *
- * This Source Code Form is subject to the terms of the MIT
- * License, If a copy of the MIT License was not distributed with this
- * file, You can obtain one at https://opensource.org/licenses/MIT.
- */
- package rufs
- import (
- "bytes"
- "fmt"
- "path"
- "sort"
- "devt.de/krotik/common/errorutil"
- "devt.de/krotik/common/stringutil"
- )
- /*
- treeItem models an item in the tree. This is an internal data structure
- which is not exposed.
- */
- type treeItem struct {
- children map[string]*treeItem // Mapping from path component to branch
- remoteBranches []string // List of remote branches which are present on this level
- remoteBranchWriting []bool // Flag if the remote branch should receive write requests
- }
- /*
- findPathBranches finds all relevant branches for a single path. The iterator
- function receives 4 parameters: The tree item, the total path within the tree,
- the subpath within the branch and a list of all branches for the tree path.
- Calling code should always give a treePath of "/".
- */
- func (t *treeItem) findPathBranches(treePath string, branchPath []string,
- recursive bool, visit func(*treeItem, string, []string, []string, []bool)) {
- visit(t, treePath, branchPath, t.remoteBranches, t.remoteBranchWriting)
- if len(branchPath) > 0 {
- if c, ok := t.children[branchPath[0]]; ok {
- // Check if a subpath matches
- c.findPathBranches(path.Join(treePath, branchPath[0]),
- branchPath[1:], recursive, visit)
- }
- } else if recursive {
- var childNames []string
- for n := range t.children {
- childNames = append(childNames, n)
- }
- sort.Strings(childNames)
- for _, n := range childNames {
- t.children[n].findPathBranches(path.Join(treePath, n),
- branchPath, recursive, visit)
- }
- }
- }
- /*
- addMapping adds a new mapping.
- */
- func (t *treeItem) addMapping(mappingPath []string, branchName string, writable bool) {
- // Add mapping to a child
- if len(mappingPath) > 0 {
- childName := mappingPath[0]
- rest := mappingPath[1:]
- errorutil.AssertTrue(childName != "",
- "Adding a mapping with an empty path is not supported")
- // Ensure child exists
- child, ok := t.children[childName]
- if !ok {
- child = &treeItem{make(map[string]*treeItem), []string{}, []bool{}}
- t.children[childName] = child
- }
- // Add rest of the mapping to the child
- child.addMapping(rest, branchName, writable)
- return
- }
- // Add branch name to this branch - keep the order in which the branches were added
- t.remoteBranches = append(t.remoteBranches, branchName)
- t.remoteBranchWriting = append(t.remoteBranchWriting, writable)
- }
- /*
- String returns a string representation of this item and its children.
- */
- func (t *treeItem) String(indent int, buf *bytes.Buffer) {
- for i, b := range t.remoteBranches {
- buf.WriteString(b)
- if t.remoteBranchWriting[i] {
- buf.WriteString("(w)")
- } else {
- buf.WriteString("(r)")
- }
- if i < len(t.remoteBranches)-1 {
- buf.WriteString(", ")
- }
- }
- buf.WriteString("\n")
- names := make([]string, 0, len(t.children))
- for n := range t.children {
- names = append(names, n)
- }
- sort.Strings(names)
- for _, n := range names {
- i := t.children[n]
- buf.WriteString(stringutil.GenerateRollingString(" ", indent*2))
- buf.WriteString(fmt.Sprintf("%v/: ", n))
- i.String(indent+1, buf)
- }
- }
|