diff --git a/fs/fs.go b/fs/fs.go index 0cd95434..99fe9aeb 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -70,9 +70,14 @@ func New() (http.FileSystem, error) { files["/"+zipFile.Name] = f } for fn := range files { + // Recursively go down the folders until get to the / dn := path.Dir(fn) - if _, ok := files[dn]; !ok { - files[dn] = file{FileInfo: dirInfo{dn}, fs: fs} + for dn != fn { + if _, ok := files[dn]; !ok { + files[dn] = file{FileInfo: dirInfo{path.Base(dn)}, fs: fs} + } + fn = dn + dn = path.Dir(fn) } } return fs, nil @@ -107,22 +112,23 @@ func unzip(zf *zip.File) ([]byte, error) { func (fs *statikFS) Open(name string) (http.File, error) { name = strings.Replace(name, "//", "/", -1) if f, ok := fs.files[name]; ok { - return newHTTPFile(f), nil + return newHTTPFile(f, name), nil } return nil, os.ErrNotExist } -func newHTTPFile(file file) *httpFile { +func newHTTPFile(file file, filePath string) *httpFile { if file.IsDir() { - return &httpFile{file: file, isDir: true} + return &httpFile{file: file, filePath: filePath, isDir: true} } - return &httpFile{file: file, reader: bytes.NewReader(file.data)} + return &httpFile{file: file, filePath: filePath, reader: bytes.NewReader(file.data)} } // httpFile represents an HTTP file and acts as a bridge // between file and http.File. type httpFile struct { file + filePath string reader *bytes.Reader isDir bool @@ -158,9 +164,9 @@ func (f *httpFile) Readdir(count int) ([]os.FileInfo, error) { if !f.isDir { return fis, nil } - prefix := f.Name() + prefix := f.filePath for fn, f := range f.file.fs.files { - if strings.HasPrefix(fn, prefix) && len(fn) > len(prefix) { + if strings.HasPrefix(fn, prefix) && len(fn) > len(prefix) && strings.Index(strings.TrimPrefix(strings.TrimPrefix(fn, prefix), "/"), "/") < 1 { fis = append(fis, f.FileInfo) } } diff --git a/fs/fs_test.go b/fs/fs_test.go index 7bea8349..452457c7 100644 --- a/fs/fs_test.go +++ b/fs/fs_test.go @@ -16,7 +16,9 @@ package fs import ( "archive/zip" "bytes" + "fmt" "io/ioutil" + "net/http" "os" "path/filepath" "reflect" @@ -102,7 +104,7 @@ func TestOpen(t *testing.T) { "/sub_dir": { isDir: true, mode: os.ModeDir | 0755, - name: "/sub_dir", + name: "sub_dir", }, }, }, @@ -199,6 +201,65 @@ func TestOpen_Parallel(t *testing.T) { wg.Wait() } +func mustIdenticalDirs(t *testing.T, d http.FileSystem, fs http.FileSystem, compareStr string) { + f, err := d.Open(compareStr) + if err != nil { + t.Fatalf("Open() = %v", err) + } + fsf, err := fs.Open(compareStr) + if err != nil { + t.Fatalf("Open (FS)() = %v", err) + } + fi, err := f.Readdir(-1) + if err != nil { + t.Fatalf("rdir() = %v", err) + } + fsi, err := fsf.Readdir(-1) + if err != nil { + t.Fatalf("rdir (FS)() = %v", err) + } + if len(fi) != len(fsi) { + for i := range fi { + fmt.Printf("-> %s\n", fi[i].Name()) + } + for i := range fsi { + fmt.Printf("!= %s\n", fsi[i].Name()) + } + t.Fatalf("readdir sizes don't match") + } + for i := range fi { + failed := true + for j := range fsi { + if fi[i].Name() == fsi[j].Name() { + failed = false + break + } + + } + if failed { + for j := range fsi { + fmt.Printf("-> %s != %s\n", fi[i].Name(), fsi[j].Name()) + + } + t.Errorf("Failed") + } + + } +} + +func TestReadDir(t *testing.T) { + Register(mustZipTree("../testdata")) + fs, err := New() + if err != nil { + t.Fatalf("New() = %v", err) + } + d := http.Dir("../testdata") + + mustIdenticalDirs(t, d, fs, "/") + mustIdenticalDirs(t, d, fs, "/index") + +} + func BenchmarkOpen(b *testing.B) { Register(mustZipTree("../testdata/index")) fs, err := New()