diff options
Diffstat (limited to 'vendor/github.com')
-rw-r--r-- | vendor/github.com/shurcooL/httpfs/filter/filter.go | 133 | ||||
-rw-r--r-- | vendor/github.com/shurcooL/httpfs/filter/filters.go | 26 |
2 files changed, 159 insertions, 0 deletions
diff --git a/vendor/github.com/shurcooL/httpfs/filter/filter.go b/vendor/github.com/shurcooL/httpfs/filter/filter.go new file mode 100644 index 00000000..6f03e597 --- /dev/null +++ b/vendor/github.com/shurcooL/httpfs/filter/filter.go @@ -0,0 +1,133 @@ +// Package filter offers an http.FileSystem wrapper with the ability to keep or skip files. +package filter + +import ( + "fmt" + "io" + "net/http" + "os" + pathpkg "path" + "time" +) + +// Func is a selection function which is provided two arguments, +// its '/'-separated cleaned rooted absolute path (i.e., it always begins with "/"), +// and the os.FileInfo of the considered file. +// +// The path is cleaned via pathpkg.Clean("/" + path). +// +// For example, if the considered file is named "a" and it's inside a directory "dir", +// then the value of path will be "/dir/a". +type Func func(path string, fi os.FileInfo) bool + +// Keep returns a filesystem that contains only those entries in source for which +// keep returns true. +func Keep(source http.FileSystem, keep Func) http.FileSystem { + return &filterFS{source: source, keep: keep} +} + +// Skip returns a filesystem that contains everything in source, except entries +// for which skip returns true. +func Skip(source http.FileSystem, skip Func) http.FileSystem { + keep := func(path string, fi os.FileInfo) bool { + return !skip(path, fi) + } + return &filterFS{source: source, keep: keep} +} + +type filterFS struct { + source http.FileSystem + keep Func // Keep entries that keep returns true for. +} + +func (fs *filterFS) Open(path string) (http.File, error) { + f, err := fs.source.Open(path) + if err != nil { + return nil, err + } + + fi, err := f.Stat() + if err != nil { + f.Close() + return nil, err + } + + if !fs.keep(clean(path), fi) { + // Skip. + f.Close() + return nil, &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist} + } + + if !fi.IsDir() { + return f, nil + } + defer f.Close() + + fis, err := f.Readdir(0) + if err != nil { + return nil, err + } + + var entries []os.FileInfo + for _, fi := range fis { + if !fs.keep(clean(pathpkg.Join(path, fi.Name())), fi) { + // Skip. + continue + } + entries = append(entries, fi) + } + + return &dir{ + name: fi.Name(), + entries: entries, + modTime: fi.ModTime(), + }, nil +} + +// clean turns a potentially relative path into an absolute one. +// +// This is needed to normalize path parameter for selection function. +func clean(path string) string { + return pathpkg.Clean("/" + path) +} + +// dir is an opened dir instance. +type dir struct { + name string + modTime time.Time + entries []os.FileInfo + pos int // Position within entries for Seek and Readdir. +} + +func (d *dir) Read([]byte) (int, error) { + return 0, fmt.Errorf("cannot Read from directory %s", d.name) +} +func (d *dir) Close() error { return nil } +func (d *dir) Stat() (os.FileInfo, error) { return d, nil } + +func (d *dir) Name() string { return d.name } +func (d *dir) Size() int64 { return 0 } +func (d *dir) Mode() os.FileMode { return 0755 | os.ModeDir } +func (d *dir) ModTime() time.Time { return d.modTime } +func (d *dir) IsDir() bool { return true } +func (d *dir) Sys() interface{} { return nil } + +func (d *dir) Seek(offset int64, whence int) (int64, error) { + if offset == 0 && whence == io.SeekStart { + d.pos = 0 + return 0, nil + } + return 0, fmt.Errorf("unsupported Seek in directory %s", d.name) +} + +func (d *dir) Readdir(count int) ([]os.FileInfo, error) { + if d.pos >= len(d.entries) && count > 0 { + return nil, io.EOF + } + if count <= 0 || count > len(d.entries)-d.pos { + count = len(d.entries) - d.pos + } + e := d.entries[d.pos : d.pos+count] + d.pos += count + return e, nil +} diff --git a/vendor/github.com/shurcooL/httpfs/filter/filters.go b/vendor/github.com/shurcooL/httpfs/filter/filters.go new file mode 100644 index 00000000..a20edaf4 --- /dev/null +++ b/vendor/github.com/shurcooL/httpfs/filter/filters.go @@ -0,0 +1,26 @@ +package filter + +import ( + "os" + pathpkg "path" +) + +// FilesWithExtensions returns a filter func that selects files (but not directories) +// that have any of the given extensions. For example: +// +// filter.FilesWithExtensions(".go", ".html") +// +// Would select both .go and .html files. It would not select any directories. +func FilesWithExtensions(exts ...string) Func { + return func(path string, fi os.FileInfo) bool { + if fi.IsDir() { + return false + } + for _, ext := range exts { + if pathpkg.Ext(path) == ext { + return true + } + } + return false + } +} |