refactor: audit fsedsl exports — remove dead code, unexport internals

Dead code removed:
- CreateFile option + FsNodeDecl.Create field (never set in production)
- Alias option function (Binding.Aliases field retained — used by fs/)
- FileTree interface (unused anywhere)
- Validation for Create-on-non-dir (no longer possible)

Unexported (internal-only plumbing):
- NewTree → newTree, TreeOption → treeOption
- WithLister/Creator/Deleter/Renamer/Opener/Stat/Readdir → with*
- FileConfig → fileConfig
- SyntheticEntry → syntheticEntry
- FileEntry/DirEntry → fileEntry/dirEntry

Retained (used by fs/):
- Tree, BuildTree, FsNodeDecl, File, SyntheticFileInfo
- All active NodeOptions (Read/Write/Stream/BlockOnce/Request/
  RemoveNode/StatOverride/UID/GID/Bind/Doc)
- Perm* constants, Binding, Each, DirNode, FileNode
- GenerateHelp, NodeOption type
This commit is contained in:
Ollie Agent 2026-08-09 12:30:33 +02:00
parent 199acabd61
commit f5efd90fbe
6 changed files with 123 additions and 191 deletions

View File

@ -21,7 +21,6 @@ func validate[Ctx any](d *FsNodeDecl[Ctx], path string) {
hasChildren := len(d.Children) > 0
hasBindings := d.Bindings != nil
hasFileHandlers := d.Read != nil || d.Write != nil || d.BlockOnce != nil || d.Stream != nil || d.Request != nil
hasCreate := d.Create != nil
hasRemove := d.Remove != nil
// A node is a directory if it has children.
@ -55,10 +54,6 @@ func validate[Ctx any](d *FsNodeDecl[Ctx], path string) {
panic(fmt.Sprintf("BuildTree: %q: at most one of BlockOnce, Stream, Request may be set", fullPath))
}
// Create only valid on directory nodes.
if hasCreate && !isDir {
panic(fmt.Sprintf("BuildTree: %q: Create on non-directory node", fullPath))
}
// Remove is valid on directories and file templates (Bindings with file handlers).
isFileTemplate := hasBindings && !isDir && hasFileHandlers
if hasRemove && !isDir && !isFileTemplate {
@ -99,29 +94,26 @@ func build[Ctx any](d *FsNodeDecl[Ctx], parentUid, parentGid string, parentCtx C
mode = 0755
}
t := NewTree(nil, mode,
WithLister(func(_ []string) ([]os.DirEntry, error) {
t := newTree(nil, mode,
withLister(func(_ []string) ([]os.DirEntry, error) {
return listDir(d, uid, gid, parentCtx)
}),
WithReaddir(func(_ []string, name string) ([]os.DirEntry, error) {
withReaddir(func(_ []string, name string) ([]os.DirEntry, error) {
return readdirDir(d, uid, gid, name, parentCtx)
}),
WithStat(func(_ []string, name string) (os.FileInfo, error) {
withStat(func(_ []string, name string) (os.FileInfo, error) {
return statDir(d, uid, gid, name, parentCtx)
}),
WithOpener(func(_ []string, name string) (File, error) {
withOpener(func(_ []string, name string) (File, error) {
return openDir(d, uid, gid, name, parentCtx)
}),
WithDeleter(func(_ []string, name string) error {
withDeleter(func(_ []string, name string) error {
return deleteDir(d, name, parentCtx)
}),
WithCreator(func(_ []string, name string, _ os.FileMode) error {
if d.Create != nil {
return d.Create(parentCtx, name)
}
withCreator(func(_ []string, name string, _ os.FileMode) error {
return fmt.Errorf("create not supported")
}),
WithRenamer(func(_ []string, old, new string) error {
withRenamer(func(_ []string, old, new string) error {
return renameDir(d, old, new, parentCtx)
}),
)
@ -132,11 +124,11 @@ func build[Ctx any](d *FsNodeDecl[Ctx], parentUid, parentGid string, parentCtx C
if mode == 0 {
mode = 0444
}
return NewTree(nil, 0,
WithLister(func(_ []string) ([]os.DirEntry, error) {
return newTree(nil, 0,
withLister(func(_ []string) ([]os.DirEntry, error) {
return nil, fmt.Errorf("%s: is a file", d.Name)
}),
WithOpener(func(_ []string, name string) (File, error) {
withOpener(func(_ []string, name string) (File, error) {
return openLeaf(d, uid, gid, mode, parentCtx, name)
}),
)
@ -165,9 +157,9 @@ func listDir[Ctx any](d *FsNodeDecl[Ctx], uid, gid string, ctx Ctx) ([]os.DirEnt
m = 0755
}
if isFileTemplate {
entries = append(entries, FileEntry(b.Name, m))
entries = append(entries, fileEntry(b.Name, m))
} else {
entries = append(entries, DirEntry(b.Name, m))
entries = append(entries, dirEntry(b.Name, m))
}
}
}
@ -181,9 +173,9 @@ func listDir[Ctx any](d *FsNodeDecl[Ctx], uid, gid string, ctx Ctx) ([]os.DirEnt
hasFileHandlers := c.Read != nil || c.Write != nil || c.BlockOnce != nil || c.Stream != nil || c.Request != nil
isDir := len(c.Children) > 0 || (c.Bindings != nil && !hasFileHandlers)
if isDir {
entries = append(entries, DirEntry(c.Name, m))
entries = append(entries, dirEntry(c.Name, m))
} else {
entries = append(entries, FileEntry(c.Name, m))
entries = append(entries, fileEntry(c.Name, m))
}
}
return entries, nil
@ -323,7 +315,7 @@ func openLeaf[Ctx any](d *FsNodeDecl[Ctx], uid, gid string, mode os.FileMode, ct
blockFn = notBlocking
}
return &FileConfig{
return &fileConfig{
StatFn: func() (os.FileInfo, error) {
if d.Stat != nil {
return d.Stat(), nil

View File

@ -68,8 +68,7 @@ type FsNodeDecl[Ctx any] struct {
// Request — rdwr: write triggers result, read returns it once.
Request func(ctx Ctx, data []byte) ([]byte, error)
// Tcreate + Tremove + Trename (directory ops).
Create func(ctx Ctx, name string) error
// Tremove + Trename (directory ops).
Remove func(ctx Ctx) error
Rename func(newName string) error
}
@ -181,11 +180,6 @@ func Request[Ctx any](fn func(Ctx, []byte) ([]byte, error)) NodeOption[Ctx] {
return func(d *FsNodeDecl[Ctx]) { d.Request = fn }
}
// CreateFile sets the file creation handler for a directory node.
func CreateFile[Ctx any](fn func(Ctx, string) error) NodeOption[Ctx] {
return func(d *FsNodeDecl[Ctx]) { d.Create = fn }
}
// RemoveNode sets the removal handler for a node.
func RemoveNode[Ctx any](fn func(Ctx) error) NodeOption[Ctx] {
return func(d *FsNodeDecl[Ctx]) { d.Remove = fn }
@ -206,11 +200,6 @@ func GID[Ctx any](gid string) NodeOption[Ctx] {
return func(d *FsNodeDecl[Ctx]) { d.GID = gid }
}
// Alias adds alternate names for resolving this node.
func Alias[Ctx any](names ...string) NodeOption[Ctx] {
return func(d *FsNodeDecl[Ctx]) { d.Aliases = append(d.Aliases, names...) }
}
// Bind declares how Each bindings populate the context.
// This is advisory metadata; the actual binding is done by Binding.Applier.
func Bind[Ctx any](targets ...BindTarget) NodeOption[Ctx] {

View File

@ -51,20 +51,6 @@ func TestNodeOptions(t *testing.T) {
}
})
// Test CreateFile option
t.Run("CreateFile", func(t *testing.T) {
createFn := func(ctx TestCtx, name string) error {
return nil
}
spec := DirNode[TestCtx]("test",
FileNode[TestCtx]("child", 0444),
CreateFile[TestCtx](createFn),
)
if spec.Create == nil {
t.Error("Create not set")
}
})
// Test RemoveNode option
t.Run("RemoveNode", func(t *testing.T) {
removeFn := func(ctx TestCtx) error {
@ -107,16 +93,6 @@ func TestNodeOptions(t *testing.T) {
})
// Test Alias option
t.Run("Alias", func(t *testing.T) {
spec := FileNode[TestCtx]("test", 0444, Alias[TestCtx]("alt1", "alt2"))
if len(spec.Aliases) != 2 {
t.Errorf("Aliases = %v, want 2 elements", spec.Aliases)
}
if spec.Aliases[0] != "alt1" || spec.Aliases[1] != "alt2" {
t.Errorf("Aliases = %v, want [alt1, alt2]", spec.Aliases)
}
})
// Test Bind option
t.Run("Bind", func(t *testing.T) {
spec := DirNode[TestCtx]("test",
@ -134,10 +110,10 @@ func TestNodeOptions(t *testing.T) {
// ══════════════════════════════════════════════════════════════════
func TestTreeMount(t *testing.T) {
parent := NewTree(nil, 0755)
child := NewTree(nil, 0755,
WithLister(func(_ []string) ([]os.DirEntry, error) {
return []os.DirEntry{FileEntry("childfile", 0444)}, nil
parent := newTree(nil, 0755)
child := newTree(nil, 0755,
withLister(func(_ []string) ([]os.DirEntry, error) {
return []os.DirEntry{fileEntry("childfile", 0444)}, nil
}),
)
@ -166,8 +142,8 @@ func TestTreeMount(t *testing.T) {
}
func TestTreeSplit(t *testing.T) {
parent := NewTree(nil, 0755)
child := NewTree(nil, 0755)
parent := newTree(nil, 0755)
child := newTree(nil, 0755)
parent.Mount("sub", child)
// Test exact match
@ -201,7 +177,7 @@ func TestTreeSplit(t *testing.T) {
}
// Test tree without children
empty := NewTree(nil, 0755)
empty := newTree(nil, 0755)
_, _, ok4 := empty.split("anything")
if ok4 {
t.Error("split should not find anything in empty tree")
@ -219,11 +195,11 @@ func TestTreeIndexOf(t *testing.T) {
}
// ══════════════════════════════════════════════════════════════════
// FileConfig tests
// fileConfig tests
// ══════════════════════════════════════════════════════════════════
func TestFileConfigMethods(t *testing.T) {
fc := &FileConfig{
fc := &fileConfig{
StatFn: func() (os.FileInfo, error) { return &SyntheticFileInfo{Name_: "test"}, nil },
ReadFn: func() ([]byte, error) { return []byte("content"), nil },
WriteFn: func(data []byte) error { return nil },
@ -257,25 +233,25 @@ func TestFileConfigMethods(t *testing.T) {
func TestFileConfigModes(t *testing.T) {
// Default: all false
fc := &FileConfig{}
fc := &fileConfig{}
if fc.BlockingReadMode() || fc.StreamMode() || fc.RequestRespMode() {
t.Error("default modes should be false")
}
// BlockingReadMode
fc2 := &FileConfig{BlockingRead_: true}
fc2 := &fileConfig{BlockingRead_: true}
if !fc2.BlockingReadMode() {
t.Error("BlockingReadMode should be true")
}
// StreamMode
fc3 := &FileConfig{StreamMode_: true}
fc3 := &fileConfig{StreamMode_: true}
if !fc3.StreamMode() {
t.Error("StreamMode should be true")
}
// RequestRespMode
fc4 := &FileConfig{RequestResp_: true}
fc4 := &fileConfig{RequestResp_: true}
if !fc4.RequestRespMode() {
t.Error("RequestRespMode should be true")
}
@ -323,12 +299,12 @@ func TestSyntheticFileInfo(t *testing.T) {
}
// ══════════════════════════════════════════════════════════════════
// SyntheticEntry tests
// syntheticEntry tests
// ══════════════════════════════════════════════════════════════════
func TestSyntheticEntry(t *testing.T) {
// File entry
fe := &SyntheticEntry{Name_: "file", Mode_: 0644, IsDir_: false}
fe := &syntheticEntry{name: "file", mode: 0644, isDir: false}
if fe.Name() != "file" {
t.Errorf("Name = %q", fe.Name())
}
@ -347,7 +323,7 @@ func TestSyntheticEntry(t *testing.T) {
}
// Dir entry
de := &SyntheticEntry{Name_: "dir", Mode_: 0755, IsDir_: true}
de := &syntheticEntry{name: "dir", mode: 0755, isDir: true}
if !de.IsDir() {
t.Error("IsDir should be true")
}
@ -357,12 +333,12 @@ func TestSyntheticEntry(t *testing.T) {
}
func TestFileEntryAndDirEntry(t *testing.T) {
fe := FileEntry("myfile", 0644)
fe := fileEntry("myfile", 0644)
if fe.Name() != "myfile" || fe.IsDir() {
t.Error("FileEntry wrong")
t.Error("fileEntry wrong")
}
de := DirEntry("mydir", 0755)
de := dirEntry("mydir", 0755)
if de.Name() != "mydir" || !de.IsDir() {
t.Error("DirEntry wrong")
}
@ -730,21 +706,6 @@ func TestValidateMultipleBlockingModes(t *testing.T) {
BuildTree(spec, TestCtx{})
}
func TestValidateCreateOnNonDir(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("should panic for Create on non-dir")
}
}()
spec := DirNode[TestCtx]("/",
FileNode[TestCtx]("file", 0444,
CreateFile(func(ctx TestCtx, name string) error { return nil }),
),
)
BuildTree(spec, TestCtx{})
}
func TestValidateTemplateWithoutBindings(t *testing.T) {
defer func() {
if r := recover(); r == nil {
@ -1010,7 +971,7 @@ func TestStatDirNotFound(t *testing.T) {
func TestCreateNotSupported(t *testing.T) {
spec := DirNode[TestCtx]("/",
FileNode[TestCtx]("file", 0444),
// No CreateFile handler
// No create handler — always returns error
)
tree := BuildTree(spec, TestCtx{})

View File

@ -6,6 +6,14 @@ import (
"time"
)
// Standard permission constants for EDSL-built trees.
const (
PermChildDir os.FileMode = 0555
PermIdx os.FileMode = 0444
PermMkdir os.FileMode = 0755
PermMkdirPrivate os.FileMode = 0700
)
// File is an open handle to a single named blob.
type File interface {
Stat() (os.FileInfo, error)
@ -22,18 +30,8 @@ type File interface {
RequestRespMode() bool
}
// FileTree is a named collection of entries.
type FileTree interface {
Stat(name string) (os.FileInfo, error)
List() ([]os.DirEntry, error)
Open(name string) (File, error)
Create(name string) error
Delete(name string) error
Rename(oldName, newName string) error
}
// FileConfig implements File via function pointers.
type FileConfig struct {
// fileConfig implements File via function pointers.
type fileConfig struct {
StatFn func() (os.FileInfo, error)
ReadFn func() ([]byte, error)
WriteFn func([]byte) error
@ -43,15 +41,15 @@ type FileConfig struct {
RequestResp_ bool // rdwr: write blocks on write, read returns result once
}
func (e *FileConfig) Stat() (os.FileInfo, error) { return e.StatFn() }
func (e *FileConfig) Read() ([]byte, error) { return e.ReadFn() }
func (e *FileConfig) Write(data []byte) error { return e.WriteFn(data) }
func (e *FileConfig) BlockingRead(ctx context.Context, base string) ([]byte, string, error) {
func (e *fileConfig) Stat() (os.FileInfo, error) { return e.StatFn() }
func (e *fileConfig) Read() ([]byte, error) { return e.ReadFn() }
func (e *fileConfig) Write(data []byte) error { return e.WriteFn(data) }
func (e *fileConfig) BlockingRead(ctx context.Context, base string) ([]byte, string, error) {
return e.BlockingReadFn(ctx, base)
}
func (e *FileConfig) BlockingReadMode() bool { return e.BlockingRead_ }
func (e *FileConfig) StreamMode() bool { return e.StreamMode_ }
func (e *FileConfig) RequestRespMode() bool { return e.RequestResp_ }
func (e *fileConfig) BlockingReadMode() bool { return e.BlockingRead_ }
func (e *fileConfig) StreamMode() bool { return e.StreamMode_ }
func (e *fileConfig) RequestRespMode() bool { return e.RequestResp_ }
// SyntheticFileInfo implements os.FileInfo for entries with no backing file.
type SyntheticFileInfo struct {
@ -71,39 +69,31 @@ func (f *SyntheticFileInfo) ModTime() time.Time { return time.Time{} }
func (f *SyntheticFileInfo) IsDir() bool { return f.IsDir_ }
func (f *SyntheticFileInfo) Sys() any { return nil }
// SyntheticEntry implements os.DirEntry for entries with no backing file.
type SyntheticEntry struct {
Name_ string
Mode_ os.FileMode
IsDir_ bool
// syntheticEntry implements os.DirEntry for entries with no backing file.
type syntheticEntry struct {
name string
mode os.FileMode
isDir bool
}
func (e *SyntheticEntry) Name() string { return e.Name_ }
func (e *SyntheticEntry) IsDir() bool { return e.IsDir_ }
func (e *SyntheticEntry) Type() os.FileMode {
if e.IsDir_ {
func (e *syntheticEntry) Name() string { return e.name }
func (e *syntheticEntry) IsDir() bool { return e.isDir }
func (e *syntheticEntry) Type() os.FileMode {
if e.isDir {
return os.ModeDir
}
return 0
}
func (e *SyntheticEntry) Info() (os.FileInfo, error) {
return &SyntheticFileInfo{Name_: e.Name_, Mode_: e.Mode_, IsDir_: e.IsDir_}, nil
func (e *syntheticEntry) Info() (os.FileInfo, error) {
return &SyntheticFileInfo{Name_: e.name, Mode_: e.mode, IsDir_: e.isDir}, nil
}
// FileEntry returns a synthetic file DirEntry.
func FileEntry(name string, mode os.FileMode) os.DirEntry {
return &SyntheticEntry{Name_: name, Mode_: mode}
// fileEntry returns a synthetic file DirEntry.
func fileEntry(name string, mode os.FileMode) os.DirEntry {
return &syntheticEntry{name: name, mode: mode}
}
// DirEntry returns a synthetic directory DirEntry.
func DirEntry(name string, mode os.FileMode) os.DirEntry {
return &SyntheticEntry{Name_: name, Mode_: mode, IsDir_: true}
// dirEntry returns a synthetic directory DirEntry.
func dirEntry(name string, mode os.FileMode) os.DirEntry {
return &syntheticEntry{name: name, mode: mode, isDir: true}
}
// Structural permissions — used by Tree for mounted children and synthetic files.
const (
PermChildDir os.FileMode = 0555
PermIdx os.FileMode = 0444
PermMkdir os.FileMode = 0755
PermMkdirPrivate os.FileMode = 0700
)

View File

@ -22,47 +22,47 @@ type Tree struct {
Data any // user-attached state
}
// TreeOption configures a Tree.
type TreeOption func(*Tree)
// 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 {
// 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 {
// 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 {
// 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 {
// 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 {
// 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 {
// 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 {
// 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
// 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 {
func newTree(dirs []string, perm os.FileMode, opts ...treeOption) *Tree {
d := &Tree{Tree: dirs, perm: perm}
for _, o := range opts {
o(d)
@ -144,14 +144,14 @@ func (d *Tree) List() ([]os.DirEntry, error) {
return nil, err
}
for name := range d.children {
entries = append(entries, DirEntry(name, PermChildDir))
entries = append(entries, dirEntry(name, PermChildDir))
}
return entries, nil
}
// No list function and no backing dirs — return children only.
var result []os.DirEntry
for name := range d.children {
result = append(result, DirEntry(name, PermChildDir))
result = append(result, dirEntry(name, PermChildDir))
}
return result, nil
}

View File

@ -9,7 +9,7 @@ import (
func TestTreeMkdirAll(t *testing.T) {
tmpDir := t.TempDir()
tree := NewTree([]string{tmpDir}, 0755)
tree := newTree([]string{tmpDir}, 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 := newTree(nil, 0755)
err := tree.MkdirAll("somedir")
if err == nil {
t.Fatal("expected error for nil backing dir")
@ -34,10 +34,10 @@ func TestTreeMkdirAllNoBackingDir(t *testing.T) {
func TestTreeWithCustomFunctions(t *testing.T) {
listed := false
tree := NewTree(nil, 0755,
WithLister(func(_ []string) ([]os.DirEntry, error) {
tree := newTree(nil, 0755,
withLister(func(_ []string) ([]os.DirEntry, error) {
listed = true
return []os.DirEntry{FileEntry("a", 0644)}, nil
return []os.DirEntry{fileEntry("a", 0644)}, nil
}),
)
entries, err := tree.List()
@ -53,9 +53,9 @@ func TestTreeWithCustomFunctions(t *testing.T) {
}
func TestTreeOpen(t *testing.T) {
tree := NewTree(nil, 0644,
WithOpener(func(_ []string, name string) (File, error) {
return &FileConfig{
tree := newTree(nil, 0644,
withOpener(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 },
@ -77,7 +77,7 @@ func TestTreeOpen(t *testing.T) {
}
func TestTreeOpenNotFound(t *testing.T) {
tree := NewTree(nil, 0644)
tree := newTree(nil, 0644)
_, err := tree.Open("nonexistent")
if err == nil {
t.Fatal("expected error")
@ -85,8 +85,8 @@ func TestTreeOpenNotFound(t *testing.T) {
}
func TestTreeStat(t *testing.T) {
tree := NewTree(nil, 0755,
WithStat(func(_ []string, name string) (os.FileInfo, error) {
tree := newTree(nil, 0755,
withStat(func(_ []string, name string) (os.FileInfo, error) {
return &SyntheticFileInfo{Name_: name, Mode_: 0644, Size_: 42}, nil
}),
)
@ -100,9 +100,9 @@ func TestTreeStat(t *testing.T) {
}
func TestTreeStatOpenerFallback(t *testing.T) {
tree := NewTree(nil, 0755,
WithOpener(func(_ []string, name string) (File, error) {
return &FileConfig{
tree := newTree(nil, 0755,
withOpener(func(_ []string, name string) (File, error) {
return &fileConfig{
StatFn: func() (os.FileInfo, error) {
return &SyntheticFileInfo{Name_: name, Size_: 99}, nil
},
@ -122,21 +122,21 @@ func TestTreeStatOpenerFallback(t *testing.T) {
}
func TestTreeChildDelegation(t *testing.T) {
child := NewTree(nil, 0755,
WithOpener(func(_ []string, name string) (File, error) {
return &FileConfig{
child := newTree(nil, 0755,
withOpener(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) {
return []os.DirEntry{FileEntry("inner", 0644)}, nil
withLister(func(_ []string) ([]os.DirEntry, error) {
return []os.DirEntry{fileEntry("inner", 0644)}, nil
}),
)
parent := NewTree(nil, 0755)
parent := newTree(nil, 0755)
parent.Mount("sub", child)
// Open delegated to child
@ -176,8 +176,8 @@ func TestTreeChildDelegation(t *testing.T) {
func TestTreeChildMkdirAll(t *testing.T) {
tmpDir := t.TempDir()
child := NewTree([]string{tmpDir}, 0755)
parent := NewTree(nil, 0755)
child := newTree([]string{tmpDir}, 0755)
parent := newTree(nil, 0755)
parent.Mount("sub", child)
err := parent.MkdirAll("sub/new/deep/path")
@ -192,8 +192,8 @@ func TestTreeChildMkdirAll(t *testing.T) {
func TestTreeCreate(t *testing.T) {
created := ""
tree := NewTree(nil, 0644,
WithCreator(func(_ []string, name string, _ os.FileMode) error {
tree := newTree(nil, 0644,
withCreator(func(_ []string, name string, _ os.FileMode) error {
created = name
return nil
}),
@ -208,8 +208,8 @@ func TestTreeCreate(t *testing.T) {
func TestTreeDelete(t *testing.T) {
deleted := ""
tree := NewTree(nil, 0644,
WithDeleter(func(_ []string, name string) error {
tree := newTree(nil, 0644,
withDeleter(func(_ []string, name string) error {
deleted = name
return nil
}),
@ -224,8 +224,8 @@ 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 := newTree(nil, 0644,
withRenamer(func(_ []string, old, new string) error {
oldN, newN = old, new
return nil
}),
@ -239,9 +239,9 @@ func TestTreeRename(t *testing.T) {
}
func TestTreeReaddir(t *testing.T) {
tree := NewTree(nil, 0755,
WithReaddir(func(_ []string, name string) ([]os.DirEntry, error) {
return []os.DirEntry{FileEntry("child", 0644)}, nil
tree := newTree(nil, 0755,
withReaddir(func(_ []string, name string) ([]os.DirEntry, error) {
return []os.DirEntry{fileEntry("child", 0644)}, nil
}),
)
entries, err := tree.Readdir("subdir")
@ -254,7 +254,7 @@ func TestTreeReaddir(t *testing.T) {
}
func TestReaddirNotFound(t *testing.T) {
tree := NewTree(nil, 0755)
tree := newTree(nil, 0755)
_, err := tree.Readdir("nowhere")
if err == nil {
t.Fatal("expected error")