pkger/file.go

180 lines
2.9 KiB
Go
Raw Normal View History

2019-07-31 00:21:26 +03:00
package pkger
import (
"bytes"
"encoding/json"
2019-07-31 18:53:36 +03:00
"fmt"
2019-07-31 00:21:26 +03:00
"io"
"net/http"
"os"
"path/filepath"
"regexp"
2019-08-09 04:51:58 +03:00
"strings"
2019-07-31 00:21:26 +03:00
"time"
2019-08-05 00:13:27 +03:00
"github.com/markbates/pkger/here"
2019-07-31 00:21:26 +03:00
)
const timeFmt = time.RFC3339Nano
2019-08-02 06:21:37 +03:00
var _ http.File = &File{}
2019-07-31 00:21:26 +03:00
type File struct {
info *FileInfo
her here.Info
path Path
data []byte
parent Path
writer *bytes.Buffer
reader io.Reader
excludes []string
2019-07-31 00:21:26 +03:00
}
2019-08-02 06:21:37 +03:00
func (f *File) Seek(offset int64, whence int) (int64, error) {
2019-08-02 06:23:46 +03:00
if sk, ok := f.reader.(io.Seeker); ok {
2019-08-02 06:21:37 +03:00
return sk.Seek(offset, whence)
}
return 0, nil
}
2019-07-31 23:29:49 +03:00
func (f *File) Close() error {
defer func() {
2019-08-02 06:23:46 +03:00
f.reader = nil
2019-07-31 23:29:49 +03:00
f.writer = nil
}()
2019-08-02 06:23:46 +03:00
if f.reader != nil {
if c, ok := f.reader.(io.Closer); ok {
2019-07-31 23:29:49 +03:00
if err := c.Close(); err != nil {
return err
}
}
}
if f.writer == nil {
return nil
}
2019-08-02 06:21:37 +03:00
f.data = f.writer.Bytes()
2019-07-31 23:29:49 +03:00
fi := f.info
fi.size = int64(len(f.data))
fi.modTime = time.Now()
f.info = fi
return nil
}
func (f *File) Read(p []byte) (int, error) {
2019-08-03 23:36:56 +03:00
if len(f.data) > 0 && f.reader == nil {
f.reader = bytes.NewReader(f.data)
2019-07-31 23:29:49 +03:00
}
2019-08-02 06:23:46 +03:00
if f.reader != nil {
return f.reader.Read(p)
2019-07-31 23:29:49 +03:00
}
2019-08-01 19:03:12 +03:00
of, err := f.her.Open(f.FilePath())
2019-07-31 23:29:49 +03:00
if err != nil {
return 0, err
}
2019-08-02 06:23:46 +03:00
f.reader = of
return f.reader.Read(p)
2019-07-31 23:29:49 +03:00
}
func (f *File) Write(b []byte) (int, error) {
if f.writer == nil {
f.writer = &bytes.Buffer{}
}
i, err := f.writer.Write(b)
return i, err
}
2019-08-02 06:23:46 +03:00
func (f File) Info() here.Info {
2019-07-31 23:29:49 +03:00
return f.her
}
2019-07-31 00:21:26 +03:00
func (f File) Stat() (os.FileInfo, error) {
if f.info == nil {
return nil, os.ErrNotExist
}
return f.info, nil
}
func (f File) Name() string {
return f.info.Name()
}
2019-08-01 19:03:12 +03:00
func (f File) FilePath() string {
2019-07-31 18:53:36 +03:00
return f.her.FilePath(f.Name())
2019-07-31 00:21:26 +03:00
}
2019-08-02 05:34:32 +03:00
func (f File) Path() Path {
2019-08-01 19:03:12 +03:00
return f.path
}
2019-07-31 00:21:26 +03:00
func (f File) String() string {
2019-08-02 06:21:37 +03:00
return f.Path().String()
}
func (f File) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
if st.Flag('+') {
b, err := json.MarshalIndent(f, "", " ")
if err != nil {
fmt.Fprint(os.Stderr, err)
return
}
fmt.Fprint(st, string(b))
return
}
fmt.Fprint(st, f.String())
case 'q':
fmt.Fprintf(st, "%q", f.String())
default:
fmt.Fprint(st, f.String())
2019-07-31 00:21:26 +03:00
}
}
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
2019-08-09 04:51:58 +03:00
var infos []os.FileInfo
err := Walk(f.Name(), func(pt Path, info os.FileInfo) error {
if count > 0 && len(infos) == count {
return io.EOF
}
for _, x := range f.excludes {
rx, err := regexp.Compile(x)
if err != nil {
return err
}
if rx.MatchString(pt.Name) {
if info.IsDir() {
return filepath.SkipDir
}
return nil
}
}
2019-08-09 04:51:58 +03:00
if pt.Name == f.parent.Name {
return nil
}
2019-08-09 22:30:12 +03:00
if f.parent.Name != "/" {
info = WithName(strings.TrimPrefix(info.Name(), f.parent.Name), info)
2019-08-09 04:51:58 +03:00
}
infos = append(infos, info)
return nil
})
2019-08-09 22:30:12 +03:00
if err != nil {
if _, ok := err.(*os.PathError); ok {
return infos, nil
}
if err != io.EOF {
return nil, err
}
2019-07-31 00:21:26 +03:00
}
2019-08-09 04:51:58 +03:00
return infos, nil
2019-07-31 00:21:26 +03:00
}