2013-07-16 23:02:27 -06:00
|
|
|
// Copyright 2013 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 httpfs implements http.FileSystem using a godoc vfs.FileSystem.
|
2014-12-08 21:00:58 -07:00
|
|
|
package httpfs // import "golang.org/x/tools/godoc/vfs/httpfs"
|
2013-07-16 23:02:27 -06:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
2014-11-09 14:50:40 -07:00
|
|
|
"golang.org/x/tools/godoc/vfs"
|
2013-07-16 23:02:27 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
func New(fs vfs.FileSystem) http.FileSystem {
|
|
|
|
return &httpFS{fs}
|
|
|
|
}
|
|
|
|
|
|
|
|
type httpFS struct {
|
|
|
|
fs vfs.FileSystem
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *httpFS) Open(name string) (http.File, error) {
|
|
|
|
fi, err := h.fs.Stat(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if fi.IsDir() {
|
|
|
|
return &httpDir{h.fs, name, nil}, nil
|
|
|
|
}
|
|
|
|
f, err := h.fs.Open(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &httpFile{h.fs, f, name}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// httpDir implements http.File for a directory in a FileSystem.
|
|
|
|
type httpDir struct {
|
|
|
|
fs vfs.FileSystem
|
|
|
|
name string
|
|
|
|
pending []os.FileInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *httpDir) Close() error { return nil }
|
|
|
|
func (h *httpDir) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
|
|
|
|
func (h *httpDir) Read([]byte) (int, error) {
|
|
|
|
return 0, fmt.Errorf("cannot Read from directory %s", h.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *httpDir) Seek(offset int64, whence int) (int64, error) {
|
|
|
|
if offset == 0 && whence == 0 {
|
|
|
|
h.pending = nil
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
return 0, fmt.Errorf("unsupported Seek in directory %s", h.name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *httpDir) Readdir(count int) ([]os.FileInfo, error) {
|
|
|
|
if h.pending == nil {
|
|
|
|
d, err := h.fs.ReadDir(h.name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if d == nil {
|
|
|
|
d = []os.FileInfo{} // not nil
|
|
|
|
}
|
|
|
|
h.pending = d
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(h.pending) == 0 && count > 0 {
|
|
|
|
return nil, io.EOF
|
|
|
|
}
|
|
|
|
if count <= 0 || count > len(h.pending) {
|
|
|
|
count = len(h.pending)
|
|
|
|
}
|
|
|
|
d := h.pending[:count]
|
|
|
|
h.pending = h.pending[count:]
|
|
|
|
return d, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// httpFile implements http.File for a file (not directory) in a FileSystem.
|
|
|
|
type httpFile struct {
|
|
|
|
fs vfs.FileSystem
|
|
|
|
vfs.ReadSeekCloser
|
|
|
|
name string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *httpFile) Stat() (os.FileInfo, error) { return h.fs.Stat(h.name) }
|
|
|
|
func (h *httpFile) Readdir(int) ([]os.FileInfo, error) {
|
|
|
|
return nil, fmt.Errorf("cannot Readdir from file %s", h.name)
|
|
|
|
}
|