Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions fs/chdir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package fs

import (
"net/http"
"os"
"path/filepath"
)

type chdirFileSystem struct {
prefix string
system http.FileSystem
}

func (c chdirFileSystem) Open(name string) (http.File, error) {
name = filepath.Clean(name)
return c.system.Open(filepath.Join(c.prefix, name))
}

func Chdir(httpFS http.FileSystem, dir string) (http.FileSystem, error) {
switch fs := httpFS.(type) {
case *chdirFileSystem:
return chdirOnChdirFS(fs, dir)
default:
return chdirOnOtherFS(fs, dir)
}
}

func chdirOnChdirFS(fs *chdirFileSystem, dir string) (*chdirFileSystem, error) {
if !isExistingDir(fs, dir) {
return nil, os.ErrNotExist
}
prefix := filepath.Join(fs.prefix, dir)
newFS := &chdirFileSystem{
prefix: filepath.Clean(prefix),
system: fs.system,
}
return newFS, nil
}

func chdirOnOtherFS(fs http.FileSystem, dir string) (http.FileSystem, error) {
if !isExistingDir(fs, dir) {
return nil, os.ErrNotExist
}
return &chdirFileSystem{
prefix: dir,
system: fs,
}, nil
}

func isExistingDir(fs http.FileSystem, dir string) bool {
f, err := fs.Open(dir)
if err != nil {
return false
}
defer f.Close()

info, err := f.Stat()
if err != nil {
return false
}
return info.IsDir()
}
18 changes: 18 additions & 0 deletions fs/fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,24 @@ func TestWalk(t *testing.T) {
}
}

func TestChdir(t *testing.T) {
Register(mustZipTree("../testdata"))
fs, err := New()
if err != nil {
t.Errorf("New() = %v", err)
return
}
fs, err = Chdir(fs, "/file")
if err != nil {
t.Errorf("Chdir(fs, /file) = %v", err)
return
}
if _, err := fs.Open("/file.txt"); err != nil {
t.Errorf("fs.Open(/file.txt) = %v", err)
return
}
}

func TestHTTPFile_Readdir(t *testing.T) {
Register(mustZipTree("../testdata/readdir"))
fs, err := New()
Expand Down