fs.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package blocks
  2. import (
  3. "fmt"
  4. "io/fs"
  5. "net/http"
  6. "os"
  7. "path/filepath"
  8. )
  9. func getFS(fsOrDir interface{}) fs.FS {
  10. switch v := fsOrDir.(type) {
  11. case string:
  12. return os.DirFS(v)
  13. case http.FileSystem: // handles go-bindata.
  14. return &httpFS{v}
  15. case fs.FS:
  16. return v
  17. default:
  18. panic(fmt.Errorf(`blocks: unexpected "fsOrDir" argument type of %T (string or fs.FS or embed.FS or http.FileSystem)`, v))
  19. }
  20. }
  21. // walk recursively in "fileSystem" descends "root" path, calling "walkFn".
  22. func walk(fileSystem fs.FS, root string, walkFn filepath.WalkFunc) error {
  23. if root != "" && root != "/" {
  24. sub, err := fs.Sub(fileSystem, root)
  25. if err != nil {
  26. return err
  27. }
  28. fileSystem = sub
  29. }
  30. if root == "" {
  31. root = "."
  32. }
  33. return fs.WalkDir(fileSystem, root, func(path string, d fs.DirEntry, err error) error {
  34. if err != nil {
  35. return fmt.Errorf("%s: %w", path, err)
  36. }
  37. info, err := d.Info()
  38. if err != nil {
  39. if err != filepath.SkipDir {
  40. return fmt.Errorf("%s: %w", path, err)
  41. }
  42. return nil
  43. }
  44. if info.IsDir() {
  45. return nil
  46. }
  47. return walkFn(path, info, err)
  48. })
  49. }
  50. func asset(fileSystem fs.FS, name string) ([]byte, error) {
  51. return fs.ReadFile(fileSystem, name)
  52. }
  53. type httpFS struct {
  54. fs http.FileSystem
  55. }
  56. func (f *httpFS) Open(name string) (fs.File, error) {
  57. if name == "." {
  58. name = "/"
  59. }
  60. return f.fs.Open(filepath.ToSlash(name))
  61. }
  62. func (f *httpFS) ReadDir(name string) ([]fs.DirEntry, error) {
  63. name = filepath.ToSlash(name)
  64. if name == "." {
  65. name = "/"
  66. }
  67. file, err := f.fs.Open(name)
  68. if err != nil {
  69. return nil, err
  70. }
  71. defer file.Close()
  72. infos, err := file.Readdir(-1)
  73. if err != nil {
  74. return nil, err
  75. }
  76. entries := make([]fs.DirEntry, 0, len(infos))
  77. for _, info := range infos {
  78. if info.IsDir() { // http file's does not return the whole tree, so read it.
  79. sub, err := f.ReadDir(info.Name())
  80. if err != nil {
  81. return nil, err
  82. }
  83. entries = append(entries, sub...)
  84. continue
  85. }
  86. entry := fs.FileInfoToDirEntry(info)
  87. entries = append(entries, entry)
  88. }
  89. return entries, nil
  90. }