github.com/astaxie/beego@v1.12.3/fs.go (about)

     1  package beego
     2  
     3  import (
     4  	"net/http"
     5  	"os"
     6  	"path/filepath"
     7  )
     8  
     9  type FileSystem struct {
    10  }
    11  
    12  func (d FileSystem) Open(name string) (http.File, error) {
    13  	return os.Open(name)
    14  }
    15  
    16  // Walk walks the file tree rooted at root in filesystem, calling walkFn for each file or
    17  // directory in the tree, including root. All errors that arise visiting files
    18  // and directories are filtered by walkFn.
    19  func Walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error {
    20  
    21  	f, err := fs.Open(root)
    22  	if err != nil {
    23  		return err
    24  	}
    25  	info, err := f.Stat()
    26  	if err != nil {
    27  		err = walkFn(root, nil, err)
    28  	} else {
    29  		err = walk(fs, root, info, walkFn)
    30  	}
    31  	if err == filepath.SkipDir {
    32  		return nil
    33  	}
    34  	return err
    35  }
    36  
    37  // walk recursively descends path, calling walkFn.
    38  func walk(fs http.FileSystem, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
    39  	var err error
    40  	if !info.IsDir() {
    41  		return walkFn(path, info, nil)
    42  	}
    43  
    44  	dir, err := fs.Open(path)
    45  	if err != nil {
    46  		if err1 := walkFn(path, info, err); err1 != nil {
    47  			return err1
    48  		}
    49  		return err
    50  	}
    51  	defer dir.Close()
    52  	dirs, err := dir.Readdir(-1)
    53  	err1 := walkFn(path, info, err)
    54  	// If err != nil, walk can't walk into this directory.
    55  	// err1 != nil means walkFn want walk to skip this directory or stop walking.
    56  	// Therefore, if one of err and err1 isn't nil, walk will return.
    57  	if err != nil || err1 != nil {
    58  		// The caller's behavior is controlled by the return value, which is decided
    59  		// by walkFn. walkFn may ignore err and return nil.
    60  		// If walkFn returns SkipDir, it will be handled by the caller.
    61  		// So walk should return whatever walkFn returns.
    62  		return err1
    63  	}
    64  
    65  	for _, fileInfo := range dirs {
    66  		filename := filepath.Join(path, fileInfo.Name())
    67  		if err = walk(fs, filename, fileInfo, walkFn); err != nil {
    68  			if !fileInfo.IsDir() || err != filepath.SkipDir {
    69  				return err
    70  			}
    71  		}
    72  	}
    73  	return nil
    74  }