56 lines
1.0 KiB
Go
56 lines
1.0 KiB
Go
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))
|
||
|
|
}
|