package discovery import ( "os" "strings" ) // PrefixTree narrows a Tree to the subtree below Prefix; paths passed in and // reported back are relative to that subtree. type PrefixTree struct { Tree Tree Prefix string } func (p *PrefixTree) Walk(fn func(rel string, isDir bool) error) error { prefix := strings.TrimSuffix(p.Prefix, "/") + "/" return p.Tree.Walk(func(rel string, isDir bool) error { if rel == p.Prefix || strings.HasPrefix(rel, prefix) { sub := strings.TrimPrefix(rel, prefix) if sub == "" { return nil } return fn(sub, isDir) } return nil }) } func (p *PrefixTree) ReadFile(rel string) ([]byte, error) { return p.Tree.ReadFile(p.Prefix + "/" + rel) } // FilesUnder delegates to the underlying tree with the prefix reapplied. func (p *PrefixTree) FilesUnder(prefix string) ([]string, error) { lister, ok := p.Tree.(interface { FilesUnder(prefix string) ([]string, error) }) if !ok { return nil, os.ErrNotExist } full := prefix if p.Prefix != "" { full = p.Prefix + "/" + strings.TrimSuffix(prefix, "/") } files, err := lister.FilesUnder(full) if err != nil { return nil, err } trim := p.Prefix + "/" out := make([]string, 0, len(files)) for _, f := range files { out = append(out, strings.TrimPrefix(f, trim)) } return out, nil } // MaterializeFile delegates to the underlying tree with the prefix reapplied. func (p *PrefixTree) MaterializeFile(rel, dst string) error { mt, ok := p.Tree.(interface { MaterializeFile(rel, dst string) error }) if !ok { return os.ErrNotExist } return mt.MaterializeFile(p.Prefix+"/"+rel, dst) }