gopass/internal/tree/tree.go
Dominik Schulz 00d04c40c6
Do not omit shadowed entries in ls output (#2341)
* Do not omit shadowed entries in ls output

Fixes #2338

RELEASE_NOTES=[BUGFIX] Do not shadow entries behind folders.

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

* Add shadow marker

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

* Adjust tests to match the new shadow behaviour

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

* Update list docs wrt. shadowing

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

* Do not mark mounts as shadowed. That's already implicit.

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

* Add more comments and some other cleanup

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>

Signed-off-by: Dominik Schulz <dominik.schulz@gauner.org>
2022-09-16 19:42:02 +02:00

83 lines
1.6 KiB
Go

// Package tree implements a tree for displaying hierarchical
// password store entries. It is loosely based on
// https://github.com/restic/restic/blob/master/internal/restic/tree.go
package tree
import (
"fmt"
"sort"
)
// ErrNodePresent is returned when a node with the same name is already present.
var ErrNodePresent = fmt.Errorf("node already present")
// Tree is a tree.
type Tree struct {
Nodes []*Node
}
// NewTree creates a new tree.
func NewTree() *Tree {
return &Tree{
Nodes: []*Node{},
}
}
// String returns the name of this tree.
func (t *Tree) String() string {
return fmt.Sprintf("Tree<%d nodes>", len(t.Nodes))
}
// Equals compares to another tree.
func (t *Tree) Equals(other *Tree) bool {
if len(t.Nodes) != len(other.Nodes) {
return false
}
for i, node := range t.Nodes {
if !node.Equals(*other.Nodes[i]) {
return false
}
}
return true
}
// Insert adds a new node at the right position.
func (t *Tree) Insert(other *Node) *Node {
pos, node := t.findPositionFor(other.Name)
if node != nil {
m := node.Merge(*other)
t.Nodes[pos] = m
return m
}
// insert at the right position, see
// https://code.google.com/p/go-wiki/wiki/SliceTricks
t.Nodes = append(t.Nodes, &Node{})
copy(t.Nodes[pos+1:], t.Nodes[pos:])
t.Nodes[pos] = other
return other
}
func (t *Tree) findPositionFor(name string) (int, *Node) {
pos := sort.Search(len(t.Nodes), func(i int) bool {
return t.Nodes[i].Name >= name
})
if pos < len(t.Nodes) && t.Nodes[pos].Name == name {
return pos, t.Nodes[pos]
}
return pos, nil
}
// Sort ensures this tree is sorted.
func (t *Tree) Sort() {
list := Nodes(t.Nodes)
sort.Sort(list)
t.Nodes = list
}