blob: 2fcaa948a7858a69dd90b073bd7dc9fc163fae2d [file] [log] [blame] [edit]
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package fsys
import (
"io/fs"
"path/filepath"
)
// Copied from path/filepath.
// WalkDir is like filepath.WalkDir but over the virtual file system.
func WalkDir(root string, fn fs.WalkDirFunc) error {
info, err := Lstat(root)
if err != nil {
err = fn(root, nil, err)
} else {
err = walkDir(root, fs.FileInfoToDirEntry(info), fn)
}
if err == filepath.SkipDir || err == filepath.SkipAll {
return nil
}
return err
}
// walkDir recursively descends path, calling walkDirFn.
func walkDir(path string, d fs.DirEntry, walkDirFn fs.WalkDirFunc) error {
if err := walkDirFn(path, d, nil); err != nil || !d.IsDir() {
if err == filepath.SkipDir && d.IsDir() {
// Successfully skipped directory.
err = nil
}
return err
}
dirs, err := ReadDir(path)
if err != nil {
// Second call, to report ReadDir error.
err = walkDirFn(path, d, err)
if err != nil {
if err == filepath.SkipDir && d.IsDir() {
err = nil
}
return err
}
}
for _, d1 := range dirs {
path1 := filepath.Join(path, d1.Name())
if err := walkDir(path1, d1, walkDirFn); err != nil {
if err == filepath.SkipDir {
break
}
return err
}
}
return nil
}