diff options
Diffstat (limited to 'internal/assets/public/public.go')
-rw-r--r-- | internal/assets/public/public.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/internal/assets/public/public.go b/internal/assets/public/public.go new file mode 100644 index 00000000..2bce7c7a --- /dev/null +++ b/internal/assets/public/public.go @@ -0,0 +1,143 @@ +// Copyright 2020 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package public + +import ( + "bytes" + "net/http" + "os" + "path/filepath" + "time" + + "gogs.io/gogs/internal/assets" +) + +//go:generate go-bindata -nomemcopy -pkg=public -ignore="\\.DS_Store|less" -prefix=../../../public -debug=false -o=public_gen.go ../../../public/... + +/* + This file is a modified version of https://github.com/go-bindata/go-bindata/pull/18. +*/ + +type fileInfo struct { + name string + size int64 +} + +func (d fileInfo) Name() string { + return d.name +} + +func (d fileInfo) Size() int64 { + return d.size +} + +func (d fileInfo) Mode() os.FileMode { + return os.FileMode(0644) | os.ModeDir +} + +func (d fileInfo) ModTime() time.Time { + return time.Time{} +} + +// IsDir return file whether a directory +func (d *fileInfo) IsDir() bool { + return true +} + +func (d fileInfo) Sys() interface{} { + return nil +} + +// file implements the http.File interface. +type file struct { + name string + *bytes.Reader + + children []os.FileInfo + childrenOffset int +} + +func (f *file) Close() error { + return nil +} + +// ⚠️ WARNING: This method is not concurrent-safe. +func (f *file) Readdir(count int) ([]os.FileInfo, error) { + if len(f.children) == 0 { + return nil, os.ErrNotExist + } + + if count <= 0 { + return f.children, nil + } + + if f.childrenOffset+count > len(f.children) { + count = len(f.children) - f.childrenOffset + } + offset := f.childrenOffset + f.childrenOffset += count + return f.children[offset : offset+count], nil +} + +func (f *file) Stat() (os.FileInfo, error) { + childCount := len(f.children) + if childCount != 0 { + return &fileInfo{ + name: f.name, + size: int64(childCount), + }, nil + } + return AssetInfo(f.name) +} + +// fileSystem implements the http.FileSystem interface. +type fileSystem struct{} + +func (f *fileSystem) Open(name string) (http.File, error) { + if len(name) > 0 && name[0] == '/' { + name = name[1:] + } + + // Attempt to get it as a file + p, err := Asset(name) + if err != nil && !assets.IsErrNotFound(err) { + return nil, err + } else if err == nil { + return &file{ + name: name, + Reader: bytes.NewReader(p), + }, nil + } + + // Attempt to get it as a directory + paths, err := AssetDir(name) + if err != nil && !assets.IsErrNotFound(err) { + return nil, err + } + + infos := make([]os.FileInfo, len(paths)) + for i, path := range paths { + path = filepath.Join(name, path) + info, err := AssetInfo(path) + if err != nil { + if !assets.IsErrNotFound(err) { + return nil, err + } + // Not found as a file, assume it's a directory. + infos[i] = &fileInfo{name: path} + } else { + infos[i] = info + } + } + return &file{ + name: name, + children: infos, + }, nil +} + +// NewFileSystem returns an http.FileSystem instance backed by embedded assets. +func NewFileSystem() http.FileSystem { + return &fileSystem{} +} |