gogs/internal/assets/public/public.go

144 lines
2.8 KiB
Go

// 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 -nometadata -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 (fileInfo) Mode() os.FileMode {
return os.FileMode(0644) | os.ModeDir
}
func (fileInfo) ModTime() time.Time {
return time.Time{}
}
// IsDir return file whether a directory
func (*fileInfo) IsDir() bool {
return true
}
func (fileInfo) Sys() interface{} {
return nil
}
// file implements the http.File interface.
type file struct {
name string
*bytes.Reader
children []os.FileInfo
childrenOffset int
}
func (*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 (*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{}
}