virtfs: inline tree options, remove newTree/with* indirection
The with* functional options and newTree constructor were private and
only used in two places (builder and tests). Replaced with direct
field assignment on &Tree{} literals. Less abstraction, same behavior.
This commit is contained in:
parent
5a09e603cd
commit
a40e1dbed0
|
|
@ -81,29 +81,28 @@ func build(d *FsNodeDecl, parentUid, parentGid string) *Tree {
|
|||
mode = 0755
|
||||
}
|
||||
|
||||
t := newTree(nil, mode,
|
||||
withLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
t := &Tree{perm: mode}
|
||||
t.listFn = func(_ []string) ([]os.DirEntry, error) {
|
||||
return listDir(d, uid, gid)
|
||||
}),
|
||||
withReaddir(func(_ []string, name string) ([]os.DirEntry, error) {
|
||||
}
|
||||
t.readdirFn = func(_ []string, name string) ([]os.DirEntry, error) {
|
||||
return readdirDir(d, uid, gid, name)
|
||||
}),
|
||||
withStat(func(_ []string, name string) (os.FileInfo, error) {
|
||||
}
|
||||
t.statFn = func(_ []string, name string) (os.FileInfo, error) {
|
||||
return statDir(d, uid, gid, name)
|
||||
}),
|
||||
withOpener(func(_ []string, name string) (File, error) {
|
||||
}
|
||||
t.openFn = func(_ []string, name string) (File, error) {
|
||||
return openDir(d, uid, gid, name)
|
||||
}),
|
||||
withDeleter(func(_ []string, name string) error {
|
||||
}
|
||||
t.deleteFn = func(_ []string, name string) error {
|
||||
return deleteDir(d, name)
|
||||
}),
|
||||
withCreator(func(_ []string, name string, _ os.FileMode) error {
|
||||
}
|
||||
t.createFn = func(_ []string, name string, _ os.FileMode) error {
|
||||
return fmt.Errorf("create not supported")
|
||||
}),
|
||||
withRenamer(func(_ []string, old, new string) error {
|
||||
}
|
||||
t.renameFn = func(_ []string, old, new string) error {
|
||||
return renameDir(d, old, new)
|
||||
}),
|
||||
)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
|
|
@ -111,14 +110,14 @@ func build(d *FsNodeDecl, parentUid, parentGid string) *Tree {
|
|||
if mode == 0 {
|
||||
mode = 0444
|
||||
}
|
||||
return newTree(nil, 0,
|
||||
withLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
t := &Tree{}
|
||||
t.listFn = func(_ []string) ([]os.DirEntry, error) {
|
||||
return nil, fmt.Errorf("%s: is a file", d.Name)
|
||||
}),
|
||||
withOpener(func(_ []string, name string) (File, error) {
|
||||
}
|
||||
t.openFn = func(_ []string, name string) (File, error) {
|
||||
return openLeaf(d, uid, gid, mode, name)
|
||||
}),
|
||||
)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// ── directory ops ────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -85,12 +85,11 @@ func TestNodeOptions(t *testing.T) {
|
|||
// ══════════════════════════════════════════════════════════════════
|
||||
|
||||
func TestTreeMount(t *testing.T) {
|
||||
parent := newTree(nil, 0755)
|
||||
child := newTree(nil, 0755,
|
||||
withLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
parent := &Tree{perm: 0755}
|
||||
child := &Tree{perm: 0755}
|
||||
child.listFn = func(_ []string) ([]os.DirEntry, error) {
|
||||
return []os.DirEntry{fileEntry("childfile", 0444)}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
parent.Mount("subdir", child)
|
||||
|
||||
|
|
@ -111,8 +110,8 @@ func TestTreeMount(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeSplit(t *testing.T) {
|
||||
parent := newTree(nil, 0755)
|
||||
child := newTree(nil, 0755)
|
||||
parent := &Tree{perm: 0755}
|
||||
child := &Tree{perm: 0755}
|
||||
parent.Mount("sub", child)
|
||||
|
||||
c, rest, ok := parent.split("sub")
|
||||
|
|
|
|||
|
|
@ -33,54 +33,6 @@ type Tree struct {
|
|||
Data any // user-attached state
|
||||
}
|
||||
|
||||
// treeOption configures a Tree.
|
||||
type treeOption func(*Tree)
|
||||
|
||||
// withLister overrides how the tree lists its entries.
|
||||
func withLister(fn func(dirs []string) ([]os.DirEntry, error)) treeOption {
|
||||
return func(d *Tree) { d.listFn = fn }
|
||||
}
|
||||
|
||||
// withCreator overrides file creation logic.
|
||||
func withCreator(fn func(dirs []string, name string, perm os.FileMode) error) treeOption {
|
||||
return func(d *Tree) { d.createFn = fn }
|
||||
}
|
||||
|
||||
// withDeleter overrides file deletion logic.
|
||||
func withDeleter(fn func(dirs []string, name string) error) treeOption {
|
||||
return func(d *Tree) { d.deleteFn = fn }
|
||||
}
|
||||
|
||||
// withRenamer overrides rename logic.
|
||||
func withRenamer(fn func(dirs []string, old, new string) error) treeOption {
|
||||
return func(d *Tree) { d.renameFn = fn }
|
||||
}
|
||||
|
||||
// withOpener overrides how entries are opened.
|
||||
func withOpener(fn func(dirs []string, name string) (File, error)) treeOption {
|
||||
return func(d *Tree) { d.openFn = fn }
|
||||
}
|
||||
|
||||
// withStat overrides how entries are stat'd.
|
||||
func withStat(fn func(dirs []string, name string) (os.FileInfo, error)) treeOption {
|
||||
return func(d *Tree) { d.statFn = fn }
|
||||
}
|
||||
|
||||
// withReaddir overrides subdirectory listing.
|
||||
func withReaddir(fn func(dirs []string, name string) ([]os.DirEntry, error)) treeOption {
|
||||
return func(d *Tree) { d.readdirFn = fn }
|
||||
}
|
||||
|
||||
// newTree creates a Tree. In EDSL usage, dirs is nil and all behavior
|
||||
// is provided via options.
|
||||
func newTree(dirs []string, perm os.FileMode, opts ...treeOption) *Tree {
|
||||
d := &Tree{Tree: dirs, perm: perm}
|
||||
for _, o := range opts {
|
||||
o(d)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// Mount attaches a child Tree at the given name.
|
||||
func (d *Tree) Mount(name string, child *Tree) {
|
||||
if d.children == nil {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
func TestTreeMkdirAll(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
tree := newTree([]string{tmpDir}, 0755)
|
||||
tree := &Tree{Tree: []string{tmpDir}, perm: 0755}
|
||||
|
||||
err := tree.MkdirAll("a/b/c")
|
||||
if err != nil {
|
||||
|
|
@ -25,7 +25,7 @@ func TestTreeMkdirAll(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeMkdirAllNoBackingDir(t *testing.T) {
|
||||
tree := newTree(nil, 0755)
|
||||
tree := &Tree{perm: 0755}
|
||||
err := tree.MkdirAll("somedir")
|
||||
if err == nil {
|
||||
t.Fatal("expected error for nil backing dir")
|
||||
|
|
@ -34,12 +34,11 @@ func TestTreeMkdirAllNoBackingDir(t *testing.T) {
|
|||
|
||||
func TestTreeWithCustomFunctions(t *testing.T) {
|
||||
listed := false
|
||||
tree := newTree(nil, 0755,
|
||||
withLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
tree := &Tree{perm: 0755}
|
||||
tree.listFn = func(_ []string) ([]os.DirEntry, error) {
|
||||
listed = true
|
||||
return []os.DirEntry{fileEntry("a", 0644)}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
entries, err := tree.List()
|
||||
if err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
|
|
@ -53,16 +52,15 @@ func TestTreeWithCustomFunctions(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeOpen(t *testing.T) {
|
||||
tree := newTree(nil, 0644,
|
||||
withOpener(func(_ []string, name string) (File, error) {
|
||||
tree := &Tree{perm: 0644}
|
||||
tree.openFn = func(_ []string, name string) (File, error) {
|
||||
return &fileConfig{
|
||||
StatFn: func() (os.FileInfo, error) { return &SyntheticFileInfo{Name_: name}, nil },
|
||||
ReadFn: func() ([]byte, error) { return []byte("content"), nil },
|
||||
WriteFn: func([]byte) error { return nil },
|
||||
BlockingReadFn: func(context.Context, string) ([]byte, string, error) { return nil, "", nil },
|
||||
}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
f, err := tree.Open("test")
|
||||
if err != nil {
|
||||
t.Fatalf("Open: %v", err)
|
||||
|
|
@ -77,7 +75,7 @@ func TestTreeOpen(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeOpenNotFound(t *testing.T) {
|
||||
tree := newTree(nil, 0644)
|
||||
tree := &Tree{perm: 0644}
|
||||
_, err := tree.Open("nonexistent")
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
|
|
@ -85,11 +83,10 @@ func TestTreeOpenNotFound(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeStat(t *testing.T) {
|
||||
tree := newTree(nil, 0755,
|
||||
withStat(func(_ []string, name string) (os.FileInfo, error) {
|
||||
tree := &Tree{perm: 0755}
|
||||
tree.statFn = func(_ []string, name string) (os.FileInfo, error) {
|
||||
return &SyntheticFileInfo{Name_: name, Mode_: 0644, Size_: 42}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
fi, err := tree.Stat("hello")
|
||||
if err != nil {
|
||||
t.Fatalf("Stat: %v", err)
|
||||
|
|
@ -100,8 +97,8 @@ func TestTreeStat(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeStatOpenerFallback(t *testing.T) {
|
||||
tree := newTree(nil, 0755,
|
||||
withOpener(func(_ []string, name string) (File, error) {
|
||||
tree := &Tree{perm: 0755}
|
||||
tree.openFn = func(_ []string, name string) (File, error) {
|
||||
return &fileConfig{
|
||||
StatFn: func() (os.FileInfo, error) {
|
||||
return &SyntheticFileInfo{Name_: name, Size_: 99}, nil
|
||||
|
|
@ -110,8 +107,7 @@ func TestTreeStatOpenerFallback(t *testing.T) {
|
|||
WriteFn: func([]byte) error { return nil },
|
||||
BlockingReadFn: func(context.Context, string) ([]byte, string, error) { return nil, "", nil },
|
||||
}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
fi, err := tree.Stat("x")
|
||||
if err != nil {
|
||||
t.Fatalf("Stat: %v", err)
|
||||
|
|
@ -122,21 +118,20 @@ func TestTreeStatOpenerFallback(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeChildDelegation(t *testing.T) {
|
||||
child := newTree(nil, 0755,
|
||||
withOpener(func(_ []string, name string) (File, error) {
|
||||
child := &Tree{perm: 0755}
|
||||
child.openFn = func(_ []string, name string) (File, error) {
|
||||
return &fileConfig{
|
||||
StatFn: func() (os.FileInfo, error) { return &SyntheticFileInfo{Name_: name}, nil },
|
||||
ReadFn: func() ([]byte, error) { return []byte("child:" + name), nil },
|
||||
WriteFn: func([]byte) error { return nil },
|
||||
BlockingReadFn: func(context.Context, string) ([]byte, string, error) { return nil, "", nil },
|
||||
}, nil
|
||||
}),
|
||||
withLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
}
|
||||
child.listFn = func(_ []string) ([]os.DirEntry, error) {
|
||||
return []os.DirEntry{fileEntry("inner", 0644)}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
parent := newTree(nil, 0755)
|
||||
parent := &Tree{perm: 0755}
|
||||
parent.Mount("sub", child)
|
||||
|
||||
// Open delegated to child
|
||||
|
|
@ -176,8 +171,8 @@ func TestTreeChildDelegation(t *testing.T) {
|
|||
|
||||
func TestTreeChildMkdirAll(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
child := newTree([]string{tmpDir}, 0755)
|
||||
parent := newTree(nil, 0755)
|
||||
child := &Tree{Tree: []string{tmpDir}, perm: 0755}
|
||||
parent := &Tree{perm: 0755}
|
||||
parent.Mount("sub", child)
|
||||
|
||||
err := parent.MkdirAll("sub/new/deep/path")
|
||||
|
|
@ -192,12 +187,11 @@ func TestTreeChildMkdirAll(t *testing.T) {
|
|||
|
||||
func TestTreeCreate(t *testing.T) {
|
||||
created := ""
|
||||
tree := newTree(nil, 0644,
|
||||
withCreator(func(_ []string, name string, _ os.FileMode) error {
|
||||
tree := &Tree{perm: 0644}
|
||||
tree.createFn = func(_ []string, name string, _ os.FileMode) error {
|
||||
created = name
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
if err := tree.Create("newfile"); err != nil {
|
||||
t.Fatalf("Create: %v", err)
|
||||
}
|
||||
|
|
@ -208,12 +202,11 @@ func TestTreeCreate(t *testing.T) {
|
|||
|
||||
func TestTreeDelete(t *testing.T) {
|
||||
deleted := ""
|
||||
tree := newTree(nil, 0644,
|
||||
withDeleter(func(_ []string, name string) error {
|
||||
tree := &Tree{perm: 0644}
|
||||
tree.deleteFn = func(_ []string, name string) error {
|
||||
deleted = name
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
if err := tree.Delete("old"); err != nil {
|
||||
t.Fatalf("Delete: %v", err)
|
||||
}
|
||||
|
|
@ -224,12 +217,11 @@ func TestTreeDelete(t *testing.T) {
|
|||
|
||||
func TestTreeRename(t *testing.T) {
|
||||
var oldN, newN string
|
||||
tree := newTree(nil, 0644,
|
||||
withRenamer(func(_ []string, old, new string) error {
|
||||
tree := &Tree{perm: 0644}
|
||||
tree.renameFn = func(_ []string, old, new string) error {
|
||||
oldN, newN = old, new
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
if err := tree.Rename("a", "b"); err != nil {
|
||||
t.Fatalf("Rename: %v", err)
|
||||
}
|
||||
|
|
@ -239,11 +231,10 @@ func TestTreeRename(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTreeReaddir(t *testing.T) {
|
||||
tree := newTree(nil, 0755,
|
||||
withReaddir(func(_ []string, name string) ([]os.DirEntry, error) {
|
||||
tree := &Tree{perm: 0755}
|
||||
tree.readdirFn = func(_ []string, name string) ([]os.DirEntry, error) {
|
||||
return []os.DirEntry{fileEntry("child", 0644)}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
entries, err := tree.Readdir("subdir")
|
||||
if err != nil {
|
||||
t.Fatalf("Readdir: %v", err)
|
||||
|
|
@ -254,7 +245,7 @@ func TestTreeReaddir(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestReaddirNotFound(t *testing.T) {
|
||||
tree := newTree(nil, 0755)
|
||||
tree := &Tree{perm: 0755}
|
||||
_, err := tree.Readdir("nowhere")
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
|
|
|
|||
Loading…
Reference in New Issue