Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dirs and large file count #7

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions cmd/resources/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ var (
TrimPath = flag.String("trim", "", "Path prefix to remove from the resulting file path")
)

type nope struct{}

func main() {

flag.Parse()
Expand All @@ -41,15 +39,15 @@ func main() {
res := resources.New()
res.Config = config

files := make(map[string]nope)
files := make(map[string]struct{})

for _, g := range flag.Args() {
matches, err := filepath.Glob(g)
if err != nil {
log.Fatal(err)
}
for _, m := range matches {
files[m] = nope{}
files[m] = struct{}{}
}
}

Expand Down
233 changes: 46 additions & 187 deletions resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,11 @@ package resources

import (
"bytes"
"fmt"
"io"
"os"
"text/template"
"path/filepath"
)

type File interface {
io.Reader
Stat() (os.FileInfo, error)
}

//Create a new Package.
func New() *Package {
return &Package{
Expand All @@ -23,7 +17,7 @@ func New() *Package {
Var: "FS",
Declare: true,
},
Files: make(map[string]File),
Files: make(map[string]*Entry),
}
}

Expand All @@ -35,207 +29,72 @@ type Config struct {
Declare bool // Dictates whatever there should be a defintion Variable
}

type Package struct {
Config
Files map[string]File
type Entry struct {
RenderedFileInfo string
RenderedData string
FileInfos []string
}

//Add a file to the package at the give path.
func (p *Package) Add(path string, file File) {
p.Files[path] = file
}
func NewEntry(f *os.File) *Entry {
entry := &Entry{}

//Add a file to the package at the give path, the files is the location of a file on the filesystem.
func (p *Package) AddFile(path string, file string) error {
f, err := os.Open(file)
if err != nil {
return err
}
p.Files[path] = f
return nil
buf := &bytes.Buffer{}
fileInfoTpl.Execute(buf, f)
entry.RenderedFileInfo = buf.String()
buf.Reset()
fileDataTpl.Execute(buf, f)
entry.RenderedData = buf.String()

return entry
}

//Build the package
func (p *Package) Build(out io.Writer) error {
return pkg.Execute(out, p)
type Package struct {
Config
Files map[string]*Entry
}

//Write the build to a file, you don't need to call Build.
func (p *Package) Write(path string) error {
f, err := os.Create(path)
//Add a file to the package at the give path, the files is the location of a file on the filesystem.
func (p *Package) AddFile(pathKey string, path string) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()

return p.Build(f)
}

//Template
e := NewEntry(f)
p.Files[pathKey] = e
f.Close()

var pkg *template.Template
dirKey := filepath.Dir(pathKey)
dir := filepath.Dir(path)

func reader(input io.Reader) (string, error) {

var (
buff bytes.Buffer
err error
blockwidth int = 12
curblock int = 0
)

b := make([]byte, blockwidth)

for n, err := input.Read(b); err == nil; n, err = input.Read(b) {
for i := 0; i < n; i++ {
fmt.Fprintf(&buff, "0x%02x,", b[i])
curblock++
if curblock < blockwidth {
continue
}
buff.WriteByte('\n')
buff.Write([]byte{'\t', '\t'})
curblock = 0
}
if dirKey == "/" {
dirKey = "."
}

return buff.String(), err
}

func init() {

pkg = template.Must(template.New("file").Funcs(template.FuncMap{"reader": reader}).Parse(` File{
data: []byte{
{{ reader . }}
},
fi: FileInfo {
name: "{{ .Stat.Name }}",
size: {{ .Stat.Size }},
modTime: time.Unix({{ .Stat.ModTime.Unix }},{{ .Stat.ModTime.UnixNano }}),
isDir: {{ .Stat.IsDir }},
},
}`))

pkg = template.Must(pkg.New("pkg").Parse(`{{ if .Tag }}// +build {{ .Tag }}

{{ end }}//Generated by github.com/omeid/go-resources
package {{ .Pkg }}

import (
"net/http"
"time"
"bytes"
"os"
"path/filepath"
"strings"
"errors"
)


{{ if .Declare }}
var {{ .Var }} http.FileSystem
{{ end }}

// http.FileSystem implementation.
type FileSystem struct {
files map[string]File
}

func (fs *FileSystem) Open(name string) (http.File, error) {
if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
strings.Contains(name, "\x00") {
return nil, errors.New("http: invalid character in file path")
// if dir and path are equal, we're already the root
if dirKey == pathKey {
return nil
}
file, ok := fs.files[name]
if !ok {
files := []os.FileInfo{}
for path, file := range fs.files {
if strings.HasPrefix(path, name) {
fi := file.fi
files = append(files, &fi)
}
}

if len(files) == 0 {
return nil, os.ErrNotExist
}

//We have a directory.
return &File{
fi: FileInfo{
isDir: true,
files: files,
}}, nil
if _, exists := p.Files[dirKey]; !exists {
p.AddFile(dirKey, dir)
}
file.Reader = bytes.NewReader(file.data)
return &file, nil
}
p.Files[dirKey].FileInfos = append(p.Files[dirKey].FileInfos, e.RenderedFileInfo)

type File struct {
*bytes.Reader
data []byte
fi FileInfo
}

// A noop-closer.
func (f *File) Close() error {
return nil
}

func (f *File) Readdir(count int) ([]os.FileInfo, error) {
return nil, os.ErrNotExist
}


func (f *File) Stat() (os.FileInfo, error) {
return &f.fi, nil
}

type FileInfo struct {
name string
size int64
mode os.FileMode
modTime time.Time
isDir bool
sys interface{}

files []os.FileInfo
}

func (f *FileInfo) Name() string {
return f.name
}
func (f *FileInfo) Size() int64 {
return f.size
}

func (f *FileInfo) Mode() os.FileMode {
return f.mode
}

func (f *FileInfo) ModTime() time.Time {
return f.modTime
}

func (f *FileInfo) IsDir() bool {
return f.isDir
}

func (f *FileInfo) Readdir(count int) ([]os.FileInfo, error) {
return f.files, nil
}

func (f *FileInfo) Sys() interface{} {
return f.sys
//Build the package
func (p *Package) Build(out io.Writer) error {
return pkgTpl.Execute(out, p)
}

//Write the build to a file, you don't need to call Build.
func (p *Package) Write(path string) error {
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()

func init() {
{{ .Var }} = &FileSystem{
files: map[string]File{
{{range $path, $file := .Files }} "/{{ $path }}": {{ template "file" $file }}, {{ end }}
},
}
}
`))
return p.Build(f)
}
Loading