package iox import ( "io/fs" "os" "path" ) type GlobFS struct { base fs.FS patterns []string } // NewGlobFS creates a new GlobFS that exposes only files matching any of the given glob patterns. func NewGlobFS(base fs.FS, patterns ...string) *GlobFS { return &GlobFS{base: base, patterns: patterns} } // match reports whether the given path matches any of the configured patterns. func (g *GlobFS) match(name string) bool { for _, pat := range g.patterns { if matched, _ := path.Match(pat, name); matched { return true } } return false } func (g *GlobFS) contains(dir string) bool { queue := []string{dir} visited := make(map[string]struct{}) for len(queue) > 0 { current := queue[0] queue = queue[1:] // dequeue // Prevent visiting same dir multiple times if _, seen := visited[current]; seen { continue } visited[current] = struct{}{} entries, err := fs.ReadDir(g.base, current) if err != nil { continue } for _, entry := range entries { rel := path.Join(current, entry.Name()) if g.match(rel) { return true } if entry.IsDir() { queue = append(queue, rel) } } } return false } func (g *GlobFS) Open(name string) (fs.File, error) { if g.match(name) { return g.base.Open(name) } fi, err := fs.Stat(g.base, name) if err != nil || !fi.IsDir() { return nil, fs.ErrNotExist } if g.contains(name) { return g.base.Open(name) } return nil, fs.ErrNotExist } func (g *GlobFS) ReadDir(name string) ([]fs.DirEntry, error) { if g.match(name) { return fs.ReadDir(g.base, name) } entries, err := fs.ReadDir(g.base, name) if err != nil { return nil, err } var children []fs.DirEntry for _, entry := range entries { rel := path.Join(name, entry.Name()) if g.match(rel) { children = append(children, entry) } if entry.IsDir() && g.contains(rel) { children = append(children, entry) } } if len(children) == 0 { return nil, os.ErrNotExist } return children, nil }