package discovery import ( "io/fs" "os" "path/filepath" "sort" "strings" ) // FsTree adapts a filesystem root to the Tree interface (used for scanning // the work repository's own items). type FsTree struct { Root string } func (f *FsTree) Walk(fn func(rel string, isDir bool) error) error { var paths []string err := filepath.WalkDir(f.Root, func(p string, d fs.DirEntry, err error) error { if err != nil { return err } if p == f.Root { return nil } paths = append(paths, p) return nil }) if err != nil { return err } sort.Strings(paths) for _, p := range paths { rel, err := filepath.Rel(f.Root, p) if err != nil { return err } info, err := os.Stat(p) if err != nil { return err } if err := fn(filepath.ToSlash(rel), info.IsDir()); err != nil { return err } } return nil } func (f *FsTree) ReadFile(rel string) ([]byte, error) { clean := filepath.FromSlash(rel) if strings.Contains(clean, "..") { return nil, os.ErrNotExist } return os.ReadFile(filepath.Join(f.Root, clean)) }