fix(virtfs): support Each() with non-template directory names
Each('peer', ...) creates a named directory whose children come from
Bindings(). Previously, listDir and findChild only checked Bindings
for template names like {foo}. Now they also handle directories that
have Bindings but no Children.
This fixes the peer/ directory in olliesrv which was listing empty
even though peers were configured via peeradd.
Added test for the non-template Each pattern.
This commit is contained in:
parent
8960fb73fd
commit
2a34c4719a
|
|
@ -125,6 +125,27 @@ func build(d *FsNodeDecl, parentUid, parentGid string) *Tree {
|
|||
|
||||
func listDir(d *FsNodeDecl, uid, gid string) ([]os.DirEntry, error) {
|
||||
var entries []os.DirEntry
|
||||
|
||||
// If this directory has Bindings (from Each), enumerate them directly.
|
||||
if d.Bindings != nil && len(d.Children) == 0 {
|
||||
nodes, err := d.Bindings()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, n := range nodes {
|
||||
m := n.Mode
|
||||
if m == 0 {
|
||||
m = d.Mode
|
||||
}
|
||||
if len(n.Children) > 0 || n.Bindings != nil {
|
||||
entries = append(entries, dirEntry(n.Name, 0755))
|
||||
} else {
|
||||
entries = append(entries, fileEntry(n.Name, m))
|
||||
}
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
for _, c := range d.Children {
|
||||
if isTemplateName(c.Name) {
|
||||
if c.Bindings != nil {
|
||||
|
|
@ -355,6 +376,21 @@ func findChild(d *FsNodeDecl, name string) *FsNodeDecl {
|
|||
return findChild(child, rest)
|
||||
}
|
||||
|
||||
// If this directory has Bindings and no Children (from Each with non-template name),
|
||||
// look up children in the bindings directly.
|
||||
if d.Bindings != nil && len(d.Children) == 0 {
|
||||
entries, err := d.Bindings()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for i := range entries {
|
||||
if entries[i].Name == name || matchAlias(entries[i].Aliases, name) {
|
||||
return &entries[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Static children.
|
||||
for i := range d.Children {
|
||||
if !isTemplateName(d.Children[i].Name) && d.Children[i].Name == name {
|
||||
|
|
|
|||
|
|
@ -668,6 +668,66 @@ func TestNestedPath(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// Each with non-template name (like "peer/")
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
|
||||
func TestEachNonTemplateName(t *testing.T) {
|
||||
// This tests the pattern used by peer/ in olliesrv:
|
||||
// Each("peer", ...) creates a directory whose children come from Bindings
|
||||
writeData := ""
|
||||
spec := DirNode("/",
|
||||
Each("peer", func() ([]FsNodeDecl, error) {
|
||||
return []FsNodeDecl{
|
||||
{Name: "alice", Mode: 0222, Write: func(data []byte) error { writeData = string(data); return nil }},
|
||||
{Name: "bob", Mode: 0222, Write: func(data []byte) error { writeData = string(data); return nil }},
|
||||
}, nil
|
||||
}),
|
||||
)
|
||||
|
||||
tree := BuildTree(spec)
|
||||
|
||||
// List root should show "peer" as a directory
|
||||
entries, err := tree.List()
|
||||
if err != nil {
|
||||
t.Fatalf("List root: %v", err)
|
||||
}
|
||||
if len(entries) != 1 {
|
||||
t.Fatalf("got %d root entries, want 1", len(entries))
|
||||
}
|
||||
if entries[0].Name() != "peer" || !entries[0].IsDir() {
|
||||
t.Errorf("root entry = %v (dir=%v), want peer dir", entries[0].Name(), entries[0].IsDir())
|
||||
}
|
||||
|
||||
// List peer/ should show alice and bob
|
||||
entries, err = tree.Readdir("peer")
|
||||
if err != nil {
|
||||
t.Fatalf("Readdir peer: %v", err)
|
||||
}
|
||||
if len(entries) != 2 {
|
||||
t.Fatalf("got %d peer entries, want 2", len(entries))
|
||||
}
|
||||
names := map[string]bool{}
|
||||
for _, e := range entries {
|
||||
names[e.Name()] = true
|
||||
}
|
||||
if !names["alice"] || !names["bob"] {
|
||||
t.Errorf("peer entries = %v, want alice and bob", entries)
|
||||
}
|
||||
|
||||
// Open and write to peer/alice
|
||||
f, err := tree.Open("peer/alice")
|
||||
if err != nil {
|
||||
t.Fatalf("Open peer/alice: %v", err)
|
||||
}
|
||||
if err := f.Write([]byte("hello")); err != nil {
|
||||
t.Fatalf("Write: %v", err)
|
||||
}
|
||||
if writeData != "hello" {
|
||||
t.Errorf("writeData = %q, want hello", writeData)
|
||||
}
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
// GenerateHelp test
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
|
|
|
|||
Loading…
Reference in New Issue