Skip to content

Commit

Permalink
feat: fs utils
Browse files Browse the repository at this point in the history
  • Loading branch information
morlay committed Dec 19, 2023
1 parent cf22cfd commit 29e1f6f
Showing 1 changed file with 99 additions and 0 deletions.
99 changes: 99 additions & 0 deletions pkg/filesystem/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package filesystem

import (
"context"
"errors"
"io/fs"
"os"
"path"
"sort"
)

var (
SkipDir = fs.SkipDir
SkipAll = fs.SkipAll
)

func WalkDir(ctx context.Context, fsys FileSystem, root string, fn func(path string, d fs.DirEntry, err error) error) error {
info, err := Stat(ctx, fsys, root)
if err != nil {
err = fn(root, nil, err)
} else {
err = walkDir(ctx, fsys, root, &statDirEntry{info}, fn)
}
if errors.Is(err, SkipDir) || errors.Is(err, SkipAll) {
return nil
}
return err
}

func Stat(ctx context.Context, fsys FileSystem, name string) (FileInfo, error) {
file, err := fsys.OpenFile(ctx, name, os.O_RDONLY, os.ModePerm)
if err != nil {
return nil, err
}
defer file.Close()
return file.Stat()
}

func ReadDir(ctx context.Context, fsys FileSystem, name string) ([]os.DirEntry, error) {
file, err := fsys.OpenFile(ctx, name, os.O_RDONLY, os.ModePerm)
if err != nil {
return nil, err
}
defer file.Close()

dir, ok := file.(fs.ReadDirFile)
if !ok {
return nil, &fs.PathError{Op: "readdir", Path: name, Err: errors.New("not implemented")}
}

list, err := dir.ReadDir(-1)
sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
return list, err
}

func walkDir(ctx context.Context, fsys FileSystem, name string, d fs.DirEntry, walkDirFn fs.WalkDirFunc) error {
if err := walkDirFn(name, d, nil); err != nil || !d.IsDir() {
if errors.Is(err, SkipDir) && d.IsDir() {
// Successfully skipped directory.
err = nil
}
return err
}

dirs, err := ReadDir(ctx, fsys, name)
if err != nil {
// Second call, to report ReadDir error.
err = walkDirFn(name, d, err)
if err != nil {
if errors.Is(err, SkipDir) && d.IsDir() {
err = nil
}
return err
}
}

for _, d1 := range dirs {
name1 := path.Join(name, d1.Name())
if err := walkDir(ctx, fsys, name1, d1, walkDirFn); err != nil {
if errors.Is(err, SkipDir) {
break
}
return err
}
}
return nil
}

type statDirEntry struct {
info FileInfo
}

func (d *statDirEntry) Name() string { return d.info.Name() }
func (d *statDirEntry) IsDir() bool { return d.info.IsDir() }
func (d *statDirEntry) Type() fs.FileMode { return d.info.Mode().Type() }
func (d *statDirEntry) Info() (FileInfo, error) { return d.info, nil }
func (d *statDirEntry) String() string {
return fs.FormatDirEntry(d)
}

0 comments on commit 29e1f6f

Please sign in to comment.