| // Copyright 2020 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 fs |
| |
| import ( |
| "errors" |
| "sort" |
| ) |
| |
| // ReadDirFS is the interface implemented by a file system |
| // that provides an optimized implementation of ReadDir. |
| type ReadDirFS interface { |
| FS |
| |
| // ReadDir reads the named directory |
| // and returns a list of directory entries sorted by filename. |
| ReadDir(name string) ([]DirEntry, error) |
| } |
| |
| // ReadDir reads the named directory |
| // and returns a list of directory entries sorted by filename. |
| // |
| // If fs implements ReadDirFS, ReadDir calls fs.ReadDir. |
| // Otherwise ReadDir calls fs.Open and uses ReadDir and Close |
| // on the returned file. |
| func ReadDir(fsys FS, name string) ([]DirEntry, error) { |
| if fsys, ok := fsys.(ReadDirFS); ok { |
| return fsys.ReadDir(name) |
| } |
| |
| file, err := fsys.Open(name) |
| if err != nil { |
| return nil, err |
| } |
| defer file.Close() |
| |
| dir, ok := file.(ReadDirFile) |
| if !ok { |
| return nil, &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 |
| } |
| |
| // dirInfo is a DirEntry based on a FileInfo. |
| type dirInfo struct { |
| fileInfo FileInfo |
| } |
| |
| func (di dirInfo) IsDir() bool { |
| return di.fileInfo.IsDir() |
| } |
| |
| func (di dirInfo) Type() FileMode { |
| return di.fileInfo.Mode().Type() |
| } |
| |
| func (di dirInfo) Info() (FileInfo, error) { |
| return di.fileInfo, nil |
| } |
| |
| func (di dirInfo) Name() string { |
| return di.fileInfo.Name() |
| } |
| |
| func (di dirInfo) String() string { |
| return FormatDirEntry(di) |
| } |
| |
| // FileInfoToDirEntry returns a DirEntry that returns information from info. |
| // If info is nil, FileInfoToDirEntry returns nil. |
| func FileInfoToDirEntry(info FileInfo) DirEntry { |
| if info == nil { |
| return nil |
| } |
| return dirInfo{fileInfo: info} |
| } |