aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/shurcooL
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/shurcooL')
-rw-r--r--vendor/github.com/shurcooL/httpfs/vfsutil/file.go21
-rw-r--r--vendor/github.com/shurcooL/httpfs/vfsutil/vfsutil.go39
-rw-r--r--vendor/github.com/shurcooL/httpfs/vfsutil/walk.go146
-rw-r--r--vendor/github.com/shurcooL/vfsgen/.travis.yml16
-rw-r--r--vendor/github.com/shurcooL/vfsgen/CONTRIBUTING.md10
-rw-r--r--vendor/github.com/shurcooL/vfsgen/README.md178
-rw-r--r--vendor/github.com/shurcooL/vfsgen/commentwriter.go45
-rw-r--r--vendor/github.com/shurcooL/vfsgen/doc.go15
-rw-r--r--vendor/github.com/shurcooL/vfsgen/generator.go486
-rw-r--r--vendor/github.com/shurcooL/vfsgen/options.go45
-rw-r--r--vendor/github.com/shurcooL/vfsgen/stringwriter.go27
11 files changed, 1028 insertions, 0 deletions
diff --git a/vendor/github.com/shurcooL/httpfs/vfsutil/file.go b/vendor/github.com/shurcooL/httpfs/vfsutil/file.go
new file mode 100644
index 00000000..4cb0dada
--- /dev/null
+++ b/vendor/github.com/shurcooL/httpfs/vfsutil/file.go
@@ -0,0 +1,21 @@
+package vfsutil
+
+import (
+ "net/http"
+ "os"
+)
+
+// File implements http.FileSystem using the native file system restricted to a
+// specific file served at root.
+//
+// While the FileSystem.Open method takes '/'-separated paths, a File's string
+// value is a filename on the native file system, not a URL, so it is separated
+// by filepath.Separator, which isn't necessarily '/'.
+type File string
+
+func (f File) Open(name string) (http.File, error) {
+ if name != "/" {
+ return nil, &os.PathError{Op: "open", Path: name, Err: os.ErrNotExist}
+ }
+ return os.Open(string(f))
+}
diff --git a/vendor/github.com/shurcooL/httpfs/vfsutil/vfsutil.go b/vendor/github.com/shurcooL/httpfs/vfsutil/vfsutil.go
new file mode 100644
index 00000000..df071d11
--- /dev/null
+++ b/vendor/github.com/shurcooL/httpfs/vfsutil/vfsutil.go
@@ -0,0 +1,39 @@
+// Package vfsutil implements some I/O utility functions for http.FileSystem.
+package vfsutil
+
+import (
+ "io/ioutil"
+ "net/http"
+ "os"
+)
+
+// ReadDir reads the contents of the directory associated with file and
+// returns a slice of FileInfo values in directory order.
+func ReadDir(fs http.FileSystem, name string) ([]os.FileInfo, error) {
+ f, err := fs.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return f.Readdir(0)
+}
+
+// Stat returns the FileInfo structure describing file.
+func Stat(fs http.FileSystem, name string) (os.FileInfo, error) {
+ f, err := fs.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return f.Stat()
+}
+
+// ReadFile reads the file named by path from fs and returns the contents.
+func ReadFile(fs http.FileSystem, path string) ([]byte, error) {
+ rc, err := fs.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer rc.Close()
+ return ioutil.ReadAll(rc)
+}
diff --git a/vendor/github.com/shurcooL/httpfs/vfsutil/walk.go b/vendor/github.com/shurcooL/httpfs/vfsutil/walk.go
new file mode 100644
index 00000000..f256bbec
--- /dev/null
+++ b/vendor/github.com/shurcooL/httpfs/vfsutil/walk.go
@@ -0,0 +1,146 @@
+package vfsutil
+
+import (
+ "io"
+ "net/http"
+ "os"
+ pathpkg "path"
+ "path/filepath"
+ "sort"
+)
+
+// Walk walks the filesystem rooted at root, calling walkFn for each file or
+// directory in the filesystem, including root. All errors that arise visiting files
+// and directories are filtered by walkFn. The files are walked in lexical
+// order.
+func Walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error {
+ info, err := Stat(fs, root)
+ if err != nil {
+ return walkFn(root, nil, err)
+ }
+ return walk(fs, root, info, walkFn)
+}
+
+// readDirNames reads the directory named by dirname and returns
+// a sorted list of directory entries.
+func readDirNames(fs http.FileSystem, dirname string) ([]string, error) {
+ fis, err := ReadDir(fs, dirname)
+ if err != nil {
+ return nil, err
+ }
+ names := make([]string, len(fis))
+ for i := range fis {
+ names[i] = fis[i].Name()
+ }
+ sort.Strings(names)
+ return names, nil
+}
+
+// walk recursively descends path, calling walkFn.
+func walk(fs http.FileSystem, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
+ err := walkFn(path, info, nil)
+ if err != nil {
+ if info.IsDir() && err == filepath.SkipDir {
+ return nil
+ }
+ return err
+ }
+
+ if !info.IsDir() {
+ return nil
+ }
+
+ names, err := readDirNames(fs, path)
+ if err != nil {
+ return walkFn(path, info, err)
+ }
+
+ for _, name := range names {
+ filename := pathpkg.Join(path, name)
+ fileInfo, err := Stat(fs, filename)
+ if err != nil {
+ if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
+ return err
+ }
+ } else {
+ err = walk(fs, filename, fileInfo, walkFn)
+ if err != nil {
+ if !fileInfo.IsDir() || err != filepath.SkipDir {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// WalkFilesFunc is the type of the function called for each file or directory visited by WalkFiles.
+// It's like filepath.WalkFunc, except it provides an additional ReadSeeker parameter for file being visited.
+type WalkFilesFunc func(path string, info os.FileInfo, rs io.ReadSeeker, err error) error
+
+// WalkFiles walks the filesystem rooted at root, calling walkFn for each file or
+// directory in the filesystem, including root. In addition to FileInfo, it passes an
+// ReadSeeker to walkFn for each file it visits.
+func WalkFiles(fs http.FileSystem, root string, walkFn WalkFilesFunc) error {
+ file, info, err := openStat(fs, root)
+ if err != nil {
+ return walkFn(root, nil, nil, err)
+ }
+ return walkFiles(fs, root, info, file, walkFn)
+}
+
+// walkFiles recursively descends path, calling walkFn.
+// It closes the input file after it's done with it, so the caller shouldn't.
+func walkFiles(fs http.FileSystem, path string, info os.FileInfo, file http.File, walkFn WalkFilesFunc) error {
+ err := walkFn(path, info, file, nil)
+ file.Close()
+ if err != nil {
+ if info.IsDir() && err == filepath.SkipDir {
+ return nil
+ }
+ return err
+ }
+
+ if !info.IsDir() {
+ return nil
+ }
+
+ names, err := readDirNames(fs, path)
+ if err != nil {
+ return walkFn(path, info, nil, err)
+ }
+
+ for _, name := range names {
+ filename := pathpkg.Join(path, name)
+ file, fileInfo, err := openStat(fs, filename)
+ if err != nil {
+ if err := walkFn(filename, nil, nil, err); err != nil && err != filepath.SkipDir {
+ return err
+ }
+ } else {
+ err = walkFiles(fs, filename, fileInfo, file, walkFn)
+ // file is closed by walkFiles, so we don't need to close it here.
+ if err != nil {
+ if !fileInfo.IsDir() || err != filepath.SkipDir {
+ return err
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// openStat performs Open and Stat and returns results, or first error encountered.
+// The caller is responsible for closing the returned file when done.
+func openStat(fs http.FileSystem, name string) (http.File, os.FileInfo, error) {
+ f, err := fs.Open(name)
+ if err != nil {
+ return nil, nil, err
+ }
+ fi, err := f.Stat()
+ if err != nil {
+ f.Close()
+ return nil, nil, err
+ }
+ return f, fi, nil
+}
diff --git a/vendor/github.com/shurcooL/vfsgen/.travis.yml b/vendor/github.com/shurcooL/vfsgen/.travis.yml
new file mode 100644
index 00000000..93b1fcdb
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/.travis.yml
@@ -0,0 +1,16 @@
+sudo: false
+language: go
+go:
+ - 1.x
+ - master
+matrix:
+ allow_failures:
+ - go: master
+ fast_finish: true
+install:
+ - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
+script:
+ - go get -t -v ./...
+ - diff -u <(echo -n) <(gofmt -d -s .)
+ - go tool vet .
+ - go test -v -race ./...
diff --git a/vendor/github.com/shurcooL/vfsgen/CONTRIBUTING.md b/vendor/github.com/shurcooL/vfsgen/CONTRIBUTING.md
new file mode 100644
index 00000000..6127ddce
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/CONTRIBUTING.md
@@ -0,0 +1,10 @@
+Contributing
+============
+
+vfsgen is open source, thanks for considering contributing!
+
+Please note that vfsgen aims to be simple and minimalistic, with as little to configure as possible. If you'd like to remove or simplify code (while having tests continue to pass), fix bugs, or improve code (e.g., add missing error checking, etc.), PRs and issues are welcome.
+
+However, if you'd like to add new functionality that increases complexity or scope, please make an issue and discuss your proposal first. I'm unlikely to accept such changes outright. It might be that your request is already a part of other similar packages, or it might fit in their scope better. See [Comparison and Alternatives](https://github.com/shurcooL/vfsgen/tree/README-alternatives-and-comparison-section#comparison) sections.
+
+Thank you!
diff --git a/vendor/github.com/shurcooL/vfsgen/README.md b/vendor/github.com/shurcooL/vfsgen/README.md
new file mode 100644
index 00000000..a7781cb1
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/README.md
@@ -0,0 +1,178 @@
+vfsgen
+======
+
+[![Build Status](https://travis-ci.org/shurcooL/vfsgen.svg?branch=master)](https://travis-ci.org/shurcooL/vfsgen) [![GoDoc](https://godoc.org/github.com/shurcooL/vfsgen?status.svg)](https://godoc.org/github.com/shurcooL/vfsgen)
+
+Package vfsgen takes an http.FileSystem (likely at `go generate` time) and
+generates Go code that statically implements the provided http.FileSystem.
+
+Features:
+
+- Efficient generated code without unneccessary overhead.
+
+- Uses gzip compression internally (selectively, only for files that compress well).
+
+- Enables direct access to internal gzip compressed bytes via an optional interface.
+
+- Outputs `gofmt`ed Go code.
+
+Installation
+------------
+
+```bash
+go get -u github.com/shurcooL/vfsgen
+```
+
+Usage
+-----
+
+This code will generate an assets_vfsdata.go file with `var assets http.FileSystem = ...` that statically implements the contents of "assets" directory.
+
+```Go
+var fs http.FileSystem = http.Dir("assets")
+
+err := vfsgen.Generate(fs, vfsgen.Options{})
+if err != nil {
+ log.Fatalln(err)
+}
+```
+
+Then, in your program, you can use `assets` as any other [`http.FileSystem`](https://godoc.org/net/http#FileSystem), for example:
+
+```Go
+file, err := assets.Open("/some/file.txt")
+if err != nil { ... }
+defer file.Close()
+```
+
+```Go
+http.Handle("/assets/", http.FileServer(assets))
+```
+
+### `go generate` Usage
+
+vfsgen is great to use with go generate directives. The code invoking `vfsgen.Generate` can go in an assets_generate.go file, which can then be invoked via "//go:generate go run assets_generate.go". The input virtual filesystem can read directly from disk, or it can be more involved.
+
+By using build tags, you can create a development mode where assets are loaded directly from disk via `http.Dir`, but then statically implemented for final releases.
+
+For example, suppose your source filesystem is defined in a package with import path "example.com/project/data" as:
+
+```Go
+// +build dev
+
+package data
+
+import "net/http"
+
+// Assets contains project assets.
+var Assets http.FileSystem = http.Dir("assets")
+```
+
+When built with the "dev" build tag, accessing `data.Assets` will read from disk directly via `http.Dir`.
+
+A generate helper file assets_generate.go can be invoked via "//go:generate go run -tags=dev assets_generate.go" directive:
+
+```Go
+// +build ignore
+
+package main
+
+import (
+ "log"
+
+ "example.com/project/data"
+ "github.com/shurcooL/vfsgen"
+)
+
+func main() {
+ err := vfsgen.Generate(data.Assets, vfsgen.Options{
+ PackageName: "data",
+ BuildTags: "!dev",
+ VariableName: "Assets",
+ })
+ if err != nil {
+ log.Fatalln(err)
+ }
+}
+```
+
+Note that "dev" build tag is used to access the source filesystem, and the output file will contain "!dev" build tag. That way, the statically implemented version will be used during normal builds and `go get`, when custom builds tags are not specified.
+
+### `vfsgendev` Usage
+
+`vfsgendev` is a binary that can be used to replace the need for the assets_generate.go file.
+
+Make sure it's installed and available in your PATH.
+
+```bash
+go get -u github.com/shurcooL/vfsgen/cmd/vfsgendev
+```
+
+Then the "//go:generate go run -tags=dev assets_generate.go" directive can be replaced with:
+
+```
+//go:generate vfsgendev -source="example.com/project/data".Assets
+```
+
+vfsgendev accesses the source variable using "dev" build tag, and generates an output file with "!dev" build tag.
+
+### Additional Embedded Information
+
+All compressed files implement [`httpgzip.GzipByter` interface](https://godoc.org/github.com/shurcooL/httpgzip#GzipByter) for efficient direct access to the internal compressed bytes:
+
+```Go
+// GzipByter is implemented by compressed files for
+// efficient direct access to the internal compressed bytes.
+type GzipByter interface {
+ // GzipBytes returns gzip compressed contents of the file.
+ GzipBytes() []byte
+}
+```
+
+Files that have been determined to not be worth gzip compressing (their compressed size is larger than original) implement [`httpgzip.NotWorthGzipCompressing` interface](https://godoc.org/github.com/shurcooL/httpgzip#NotWorthGzipCompressing):
+
+```Go
+// NotWorthGzipCompressing is implemented by files that were determined
+// not to be worth gzip compressing (the file size did not decrease as a result).
+type NotWorthGzipCompressing interface {
+ // NotWorthGzipCompressing is a noop. It's implemented in order to indicate
+ // the file is not worth gzip compressing.
+ NotWorthGzipCompressing()
+}
+```
+
+Comparison
+----------
+
+vfsgen aims to be conceptually simple to use. The [`http.FileSystem`](https://godoc.org/net/http#FileSystem) abstraction is central to vfsgen. It's used as both input for code generation, and as output in the generated code.
+
+That enables great flexibility through orthogonality, since helpers and wrappers can operate on `http.FileSystem` without knowing about vfsgen. If you want, you can perform pre-processing, minifying assets, merging folders, filtering out files and otherwise modifying input via generic `http.FileSystem` middleware.
+
+It avoids unneccessary overhead by merging what was previously done with two distinct packages into a single package.
+
+It strives to be the best in its class in terms of code quality and efficiency of generated code. However, if your use goals are different, there are other similar packages that may fit your needs better.
+
+### Alternatives
+
+- [`go-bindata`](https://github.com/jteeuwen/go-bindata) - Reads from disk, generates Go code that provides access to data via a [custom API](https://github.com/jteeuwen/go-bindata#accessing-an-asset).
+- [`go-bindata-assetfs`](https://github.com/elazarl/go-bindata-assetfs) - Takes output of go-bindata and provides a wrapper that implements `http.FileSystem` interface (the same as what vfsgen outputs directly).
+- [`becky`](https://github.com/tv42/becky) - Embeds assets as string literals in Go source.
+- [`statik`](https://github.com/rakyll/statik) - Embeds a directory of static files to be accessed via `http.FileSystem` interface (sounds very similar to vfsgen); implementation sourced from [camlistore](https://camlistore.org).
+- [`go.rice`](https://github.com/GeertJohan/go.rice) - Makes working with resources such as HTML, JS, CSS, images and templates very easy.
+- [`esc`](https://github.com/mjibson/esc) - Embeds files into Go programs and provides `http.FileSystem` interfaces to them.
+- [`staticfiles`](https://github.com/bouk/staticfiles) - Allows you to embed a directory of files into your Go binary.
+- [`togo`](https://github.com/flazz/togo) - Generates a Go source file with a `[]byte` var containing the given file's contents.
+- [`fileb0x`](https://github.com/UnnoTed/fileb0x) - Simple customizable tool to embed files in Go.
+- [`embedfiles`](https://github.com/leighmcculloch/embedfiles) - Simple tool for embedding files in Go code as a map.
+- [`packr`](https://github.com/gobuffalo/packr) - Simple solution for bundling static assets inside of Go binaries.
+- [`rsrc`](https://github.com/akavel/rsrc) - Tool for embedding .ico & manifest resources in Go programs for Windows.
+
+Attribution
+-----------
+
+This package was originally based on the excellent work by [@jteeuwen](https://github.com/jteeuwen) on [`go-bindata`](https://github.com/jteeuwen/go-bindata) and [@elazarl](https://github.com/elazarl) on [`go-bindata-assetfs`](https://github.com/elazarl/go-bindata-assetfs).
+
+License
+-------
+
+- [MIT License](https://opensource.org/licenses/mit-license.php)
diff --git a/vendor/github.com/shurcooL/vfsgen/commentwriter.go b/vendor/github.com/shurcooL/vfsgen/commentwriter.go
new file mode 100644
index 00000000..b6847f52
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/commentwriter.go
@@ -0,0 +1,45 @@
+package vfsgen
+
+import "io"
+
+// commentWriter writes a Go comment to the underlying io.Writer,
+// using line comment form (//).
+type commentWriter struct {
+ W io.Writer
+ wroteSlashes bool // Wrote "//" at the beginning of the current line.
+}
+
+func (c *commentWriter) Write(p []byte) (int, error) {
+ var n int
+ for i, b := range p {
+ if !c.wroteSlashes {
+ s := "//"
+ if b != '\n' {
+ s = "// "
+ }
+ if _, err := io.WriteString(c.W, s); err != nil {
+ return n, err
+ }
+ c.wroteSlashes = true
+ }
+ n0, err := c.W.Write(p[i : i+1])
+ n += n0
+ if err != nil {
+ return n, err
+ }
+ if b == '\n' {
+ c.wroteSlashes = false
+ }
+ }
+ return len(p), nil
+}
+
+func (c *commentWriter) Close() error {
+ if !c.wroteSlashes {
+ if _, err := io.WriteString(c.W, "//"); err != nil {
+ return err
+ }
+ c.wroteSlashes = true
+ }
+ return nil
+}
diff --git a/vendor/github.com/shurcooL/vfsgen/doc.go b/vendor/github.com/shurcooL/vfsgen/doc.go
new file mode 100644
index 00000000..46f28504
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/doc.go
@@ -0,0 +1,15 @@
+/*
+Package vfsgen takes an http.FileSystem (likely at `go generate` time) and
+generates Go code that statically implements the provided http.FileSystem.
+
+Features:
+
+- Efficient generated code without unneccessary overhead.
+
+- Uses gzip compression internally (selectively, only for files that compress well).
+
+- Enables direct access to internal gzip compressed bytes via an optional interface.
+
+- Outputs `gofmt`ed Go code.
+*/
+package vfsgen
diff --git a/vendor/github.com/shurcooL/vfsgen/generator.go b/vendor/github.com/shurcooL/vfsgen/generator.go
new file mode 100644
index 00000000..a95c81cb
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/generator.go
@@ -0,0 +1,486 @@
+package vfsgen
+
+import (
+ "bytes"
+ "compress/gzip"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "os"
+ pathpkg "path"
+ "sort"
+ "strconv"
+ "text/template"
+ "time"
+
+ "github.com/shurcooL/httpfs/vfsutil"
+)
+
+// Generate Go code that statically implements input filesystem,
+// write the output to a file specified in opt.
+func Generate(input http.FileSystem, opt Options) error {
+ opt.fillMissing()
+
+ // Use an in-memory buffer to generate the entire output.
+ buf := new(bytes.Buffer)
+
+ err := t.ExecuteTemplate(buf, "Header", opt)
+ if err != nil {
+ return err
+ }
+
+ var toc toc
+ err = findAndWriteFiles(buf, input, &toc)
+ if err != nil {
+ return err
+ }
+
+ err = t.ExecuteTemplate(buf, "DirEntries", toc.dirs)
+ if err != nil {
+ return err
+ }
+
+ err = t.ExecuteTemplate(buf, "Trailer", toc)
+ if err != nil {
+ return err
+ }
+
+ // Write output file (all at once).
+ fmt.Println("writing", opt.Filename)
+ err = ioutil.WriteFile(opt.Filename, buf.Bytes(), 0644)
+ return err
+}
+
+type toc struct {
+ dirs []*dirInfo
+
+ HasCompressedFile bool // There's at least one compressedFile.
+ HasFile bool // There's at least one uncompressed file.
+}
+
+// fileInfo is a definition of a file.
+type fileInfo struct {
+ Path string
+ Name string
+ ModTime time.Time
+ UncompressedSize int64
+}
+
+// dirInfo is a definition of a directory.
+type dirInfo struct {
+ Path string
+ Name string
+ ModTime time.Time
+ Entries []string
+}
+
+// findAndWriteFiles recursively finds all the file paths in the given directory tree.
+// They are added to the given map as keys. Values will be safe function names
+// for each file, which will be used when generating the output code.
+func findAndWriteFiles(buf *bytes.Buffer, fs http.FileSystem, toc *toc) error {
+ walkFn := func(path string, fi os.FileInfo, r io.ReadSeeker, err error) error {
+ if err != nil {
+ log.Printf("can't stat file %q: %v\n", path, err)
+ return nil
+ }
+
+ switch fi.IsDir() {
+ case false:
+ file := &fileInfo{
+ Path: path,
+ Name: pathpkg.Base(path),
+ ModTime: fi.ModTime().UTC(),
+ UncompressedSize: fi.Size(),
+ }
+
+ marker := buf.Len()
+
+ // Write CompressedFileInfo.
+ err = writeCompressedFileInfo(buf, file, r)
+ switch err {
+ default:
+ return err
+ case nil:
+ toc.HasCompressedFile = true
+ // If compressed file is not smaller than original, revert and write original file.
+ case errCompressedNotSmaller:
+ _, err = r.Seek(0, io.SeekStart)
+ if err != nil {
+ return err
+ }
+
+ buf.Truncate(marker)
+
+ // Write FileInfo.
+ err = writeFileInfo(buf, file, r)
+ if err != nil {
+ return err
+ }
+ toc.HasFile = true
+ }
+ case true:
+ entries, err := readDirPaths(fs, path)
+ if err != nil {
+ return err
+ }
+
+ dir := &dirInfo{
+ Path: path,
+ Name: pathpkg.Base(path),
+ ModTime: fi.ModTime().UTC(),
+ Entries: entries,
+ }
+
+ toc.dirs = append(toc.dirs, dir)
+
+ // Write DirInfo.
+ err = t.ExecuteTemplate(buf, "DirInfo", dir)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
+
+ err := vfsutil.WalkFiles(fs, "/", walkFn)
+ return err
+}
+
+// readDirPaths reads the directory named by dirname and returns
+// a sorted list of directory paths.
+func readDirPaths(fs http.FileSystem, dirname string) ([]string, error) {
+ fis, err := vfsutil.ReadDir(fs, dirname)
+ if err != nil {
+ return nil, err
+ }
+ paths := make([]string, len(fis))
+ for i := range fis {
+ paths[i] = pathpkg.Join(dirname, fis[i].Name())
+ }
+ sort.Strings(paths)
+ return paths, nil
+}
+
+// writeCompressedFileInfo writes CompressedFileInfo.
+// It returns errCompressedNotSmaller if compressed file is not smaller than original.
+func writeCompressedFileInfo(w io.Writer, file *fileInfo, r io.Reader) error {
+ err := t.ExecuteTemplate(w, "CompressedFileInfo-Before", file)
+ if err != nil {
+ return err
+ }
+ sw := &stringWriter{Writer: w}
+ gw := gzip.NewWriter(sw)
+ _, err = io.Copy(gw, r)
+ if err != nil {
+ return err
+ }
+ err = gw.Close()
+ if err != nil {
+ return err
+ }
+ if sw.N >= file.UncompressedSize {
+ return errCompressedNotSmaller
+ }
+ err = t.ExecuteTemplate(w, "CompressedFileInfo-After", file)
+ return err
+}
+
+var errCompressedNotSmaller = errors.New("compressed file is not smaller than original")
+
+// Write FileInfo.
+func writeFileInfo(w io.Writer, file *fileInfo, r io.Reader) error {
+ err := t.ExecuteTemplate(w, "FileInfo-Before", file)
+ if err != nil {
+ return err
+ }
+ sw := &stringWriter{Writer: w}
+ _, err = io.Copy(sw, r)
+ if err != nil {
+ return err
+ }
+ err = t.ExecuteTemplate(w, "FileInfo-After", file)
+ return err
+}
+
+var t = template.Must(template.New("").Funcs(template.FuncMap{
+ "quote": strconv.Quote,
+ "comment": func(s string) (string, error) {
+ var buf bytes.Buffer
+ cw := &commentWriter{W: &buf}
+ _, err := io.WriteString(cw, s)
+ if err != nil {
+ return "", err
+ }
+ err = cw.Close()
+ return buf.String(), err
+ },
+}).Parse(`{{define "Header"}}// Code generated by vfsgen; DO NOT EDIT.
+
+{{with .BuildTags}}// +build {{.}}
+
+{{end}}package {{.PackageName}}
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ pathpkg "path"
+ "time"
+)
+
+{{comment .VariableComment}}
+var {{.VariableName}} = func() http.FileSystem {
+ fs := vfsgen۰FS{
+{{end}}
+
+
+
+{{define "CompressedFileInfo-Before"}} {{quote .Path}}: &vfsgen۰CompressedFileInfo{
+ name: {{quote .Name}},
+ modTime: {{template "Time" .ModTime}},
+ uncompressedSize: {{.UncompressedSize}},
+{{/* This blank line separating compressedContent is neccessary to prevent potential gofmt issues. See issue #19. */}}
+ compressedContent: []byte("{{end}}{{define "CompressedFileInfo-After"}}"),
+ },
+{{end}}
+
+
+
+{{define "FileInfo-Before"}} {{quote .Path}}: &vfsgen۰FileInfo{
+ name: {{quote .Name}},
+ modTime: {{template "Time" .ModTime}},
+ content: []byte("{{end}}{{define "FileInfo-After"}}"),
+ },
+{{end}}
+
+
+
+{{define "DirInfo"}} {{quote .Path}}: &vfsgen۰DirInfo{
+ name: {{quote .Name}},
+ modTime: {{template "Time" .ModTime}},
+ },
+{{end}}
+
+
+
+{{define "DirEntries"}} }
+{{range .}}{{if .Entries}} fs[{{quote .Path}}].(*vfsgen۰DirInfo).entries = []os.FileInfo{{"{"}}{{range .Entries}}
+ fs[{{quote .}}].(os.FileInfo),{{end}}
+ }
+{{end}}{{end}}
+ return fs
+}()
+{{end}}
+
+
+
+{{define "Trailer"}}
+type vfsgen۰FS map[string]interface{}
+
+func (fs vfsgen۰FS) Open(path string) (http.File, error) {
+ path = pathpkg.Clean("/" + path)
+ f, ok := fs[path]
+ if !ok {
+ return nil, &os.PathError{Op: "open", Path: path, Err: os.ErrNotExist}
+ }
+
+ switch f := f.(type) {{"{"}}{{if .HasCompressedFile}}
+ case *vfsgen۰CompressedFileInfo:
+ gr, err := gzip.NewReader(bytes.NewReader(f.compressedContent))
+ if err != nil {
+ // This should never happen because we generate the gzip bytes such that they are always valid.
+ panic("unexpected error reading own gzip compressed bytes: " + err.Error())
+ }
+ return &vfsgen۰CompressedFile{
+ vfsgen۰CompressedFileInfo: f,
+ gr: gr,
+ }, nil{{end}}{{if .HasFile}}
+ case *vfsgen۰FileInfo:
+ return &vfsgen۰File{
+ vfsgen۰FileInfo: f,
+ Reader: bytes.NewReader(f.content),
+ }, nil{{end}}
+ case *vfsgen۰DirInfo:
+ return &vfsgen۰Dir{
+ vfsgen۰DirInfo: f,
+ }, nil
+ default:
+ // This should never happen because we generate only the above types.
+ panic(fmt.Sprintf("unexpected type %T", f))
+ }
+}
+{{if .HasCompressedFile}}
+// vfsgen۰CompressedFileInfo is a static definition of a gzip compressed file.
+type vfsgen۰CompressedFileInfo struct {
+ name string
+ modTime time.Time
+ compressedContent []byte
+ uncompressedSize int64
+}
+
+func (f *vfsgen۰CompressedFileInfo) Readdir(count int) ([]os.FileInfo, error) {
+ return nil, fmt.Errorf("cannot Readdir from file %s", f.name)
+}
+func (f *vfsgen۰CompressedFileInfo) Stat() (os.FileInfo, error) { return f, nil }
+
+func (f *vfsgen۰CompressedFileInfo) GzipBytes() []byte {
+ return f.compressedContent
+}
+
+func (f *vfsgen۰CompressedFileInfo) Name() string { return f.name }
+func (f *vfsgen۰CompressedFileInfo) Size() int64 { return f.uncompressedSize }
+func (f *vfsgen۰CompressedFileInfo) Mode() os.FileMode { return 0444 }
+func (f *vfsgen۰CompressedFileInfo) ModTime() time.Time { return f.modTime }
+func (f *vfsgen۰CompressedFileInfo) IsDir() bool { return false }
+func (f *vfsgen۰CompressedFileInfo) Sys() interface{} { return nil }
+
+// vfsgen۰CompressedFile is an opened compressedFile instance.
+type vfsgen۰CompressedFile struct {
+ *vfsgen۰CompressedFileInfo
+ gr *gzip.Reader
+ grPos int64 // Actual gr uncompressed position.
+ seekPos int64 // Seek uncompressed position.
+}
+
+func (f *vfsgen۰CompressedFile) Read(p []byte) (n int, err error) {
+ if f.grPos > f.seekPos {
+ // Rewind to beginning.
+ err = f.gr.Reset(bytes.NewReader(f.compressedContent))
+ if err != nil {
+ return 0, err
+ }
+ f.grPos = 0
+ }
+ if f.grPos < f.seekPos {
+ // Fast-forward.
+ _, err = io.CopyN(ioutil.Discard, f.gr, f.seekPos-f.grPos)
+ if err != nil {
+ return 0, err
+ }
+ f.grPos = f.seekPos
+ }
+ n, err = f.gr.Read(p)
+ f.grPos += int64(n)
+ f.seekPos = f.grPos
+ return n, err
+}
+func (f *vfsgen۰CompressedFile) Seek(offset int64, whence int) (int64, error) {
+ switch whence {
+ case io.SeekStart:
+ f.seekPos = 0 + offset
+ case io.SeekCurrent:
+ f.seekPos += offset
+ case io.SeekEnd:
+ f.seekPos = f.uncompressedSize + offset
+ default:
+ panic(fmt.Errorf("invalid whence value: %v", whence))
+ }
+ return f.seekPos, nil
+}
+func (f *vfsgen۰CompressedFile) Close() error {
+ return f.gr.Close()
+}
+{{else}}
+// We already imported "compress/gzip" and "io/ioutil", but ended up not using them. Avoid unused import error.
+var _ = gzip.Reader{}
+var _ = ioutil.Discard
+{{end}}{{if .HasFile}}
+// vfsgen۰FileInfo is a static definition of an uncompressed file (because it's not worth gzip compressing).
+type vfsgen۰FileInfo struct {
+ name string
+ modTime time.Time
+ content []byte
+}
+
+func (f *vfsgen۰FileInfo) Readdir(count int) ([]os.FileInfo, error) {
+ return nil, fmt.Errorf("cannot Readdir from file %s", f.name)
+}
+func (f *vfsgen۰FileInfo) Stat() (os.FileInfo, error) { return f, nil }
+
+func (f *vfsgen۰FileInfo) NotWorthGzipCompressing() {}
+
+func (f *vfsgen۰FileInfo) Name() string { return f.name }
+func (f *vfsgen۰FileInfo) Size() int64 { return int64(len(f.content)) }
+func (f *vfsgen۰FileInfo) Mode() os.FileMode { return 0444 }
+func (f *vfsgen۰FileInfo) ModTime() time.Time { return f.modTime }
+func (f *vfsgen۰FileInfo) IsDir() bool { return false }
+func (f *vfsgen۰FileInfo) Sys() interface{} { return nil }
+
+// vfsgen۰File is an opened file instance.
+type vfsgen۰File struct {
+ *vfsgen۰FileInfo
+ *bytes.Reader
+}
+
+func (f *vfsgen۰File) Close() error {
+ return nil
+}
+{{else if not .HasCompressedFile}}
+// We already imported "bytes", but ended up not using it. Avoid unused import error.
+var _ = bytes.Reader{}
+{{end}}
+// vfsgen۰DirInfo is a static definition of a directory.
+type vfsgen۰DirInfo struct {
+ name string
+ modTime time.Time
+ entries []os.FileInfo
+}
+
+func (d *vfsgen۰DirInfo) Read([]byte) (int, error) {
+ return 0, fmt.Errorf("cannot Read from directory %s", d.name)
+}
+func (d *vfsgen۰DirInfo) Close() error { return nil }
+func (d *vfsgen۰DirInfo) Stat() (os.FileInfo, error) { return d, nil }
+
+func (d *vfsgen۰DirInfo) Name() string { return d.name }
+func (d *vfsgen۰DirInfo) Size() int64 { return 0 }
+func (d *vfsgen۰DirInfo) Mode() os.FileMode { return 0755 | os.ModeDir }
+func (d *vfsgen۰DirInfo) ModTime() time.Time { return d.modTime }
+func (d *vfsgen۰DirInfo) IsDir() bool { return true }
+func (d *vfsgen۰DirInfo) Sys() interface{} { return nil }
+
+// vfsgen۰Dir is an opened dir instance.
+type vfsgen۰Dir struct {
+ *vfsgen۰DirInfo
+ pos int // Position within entries for Seek and Readdir.
+}
+
+func (d *vfsgen۰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 *vfsgen۰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
+}
+{{end}}
+
+
+
+{{define "Time"}}
+{{- if .IsZero -}}
+ time.Time{}
+{{- else -}}
+ time.Date({{.Year}}, {{printf "%d" .Month}}, {{.Day}}, {{.Hour}}, {{.Minute}}, {{.Second}}, {{.Nanosecond}}, time.UTC)
+{{- end -}}
+{{end}}
+`))
diff --git a/vendor/github.com/shurcooL/vfsgen/options.go b/vendor/github.com/shurcooL/vfsgen/options.go
new file mode 100644
index 00000000..d10d348e
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/options.go
@@ -0,0 +1,45 @@
+package vfsgen
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Options for vfsgen code generation.
+type Options struct {
+ // Filename of the generated Go code output (including extension).
+ // If left empty, it defaults to "{{toLower .VariableName}}_vfsdata.go".
+ Filename string
+
+ // PackageName is the name of the package in the generated code.
+ // If left empty, it defaults to "main".
+ PackageName string
+
+ // BuildTags are the optional build tags in the generated code.
+ // The build tags syntax is specified by the go tool.
+ BuildTags string
+
+ // VariableName is the name of the http.FileSystem variable in the generated code.
+ // If left empty, it defaults to "assets".
+ VariableName string
+
+ // VariableComment is the comment of the http.FileSystem variable in the generated code.
+ // If left empty, it defaults to "{{.VariableName}} statically implements the virtual filesystem provided to vfsgen.".
+ VariableComment string
+}
+
+// fillMissing sets default values for mandatory options that are left empty.
+func (opt *Options) fillMissing() {
+ if opt.PackageName == "" {
+ opt.PackageName = "main"
+ }
+ if opt.VariableName == "" {
+ opt.VariableName = "assets"
+ }
+ if opt.Filename == "" {
+ opt.Filename = fmt.Sprintf("%s_vfsdata.go", strings.ToLower(opt.VariableName))
+ }
+ if opt.VariableComment == "" {
+ opt.VariableComment = fmt.Sprintf("%s statically implements the virtual filesystem provided to vfsgen.", opt.VariableName)
+ }
+}
diff --git a/vendor/github.com/shurcooL/vfsgen/stringwriter.go b/vendor/github.com/shurcooL/vfsgen/stringwriter.go
new file mode 100644
index 00000000..a781efdc
--- /dev/null
+++ b/vendor/github.com/shurcooL/vfsgen/stringwriter.go
@@ -0,0 +1,27 @@
+package vfsgen
+
+import (
+ "io"
+)
+
+// stringWriter writes given bytes to underlying io.Writer as a Go interpreted string literal value,
+// not including double quotes. It tracks the total number of bytes written.
+type stringWriter struct {
+ io.Writer
+ N int64 // Total bytes written.
+}
+
+func (sw *stringWriter) Write(p []byte) (n int, err error) {
+ const hex = "0123456789abcdef"
+ buf := []byte{'\\', 'x', 0, 0}
+ for _, b := range p {
+ buf[2], buf[3] = hex[b/16], hex[b%16]
+ _, err = sw.Writer.Write(buf)
+ if err != nil {
+ return n, err
+ }
+ n++
+ sw.N++
+ }
+ return n, nil
+}