summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/GeertJohan/go.rice
diff options
context:
space:
mode:
authorWim <wim@42.be>2017-02-18 23:00:46 +0100
committerWim <wim@42.be>2017-02-18 23:11:48 +0100
commit930b639cc9cd2d2873302f30303378c0e53816a8 (patch)
tree8cd3f1d464fb5d4e5607fe16255c35a31a9d8b62 /vendor/github.com/GeertJohan/go.rice
parent58483ea70c2c99a352592c5e50686fb03985650e (diff)
downloadmatterbridge-msglm-930b639cc9cd2d2873302f30303378c0e53816a8.tar.gz
matterbridge-msglm-930b639cc9cd2d2873302f30303378c0e53816a8.tar.bz2
matterbridge-msglm-930b639cc9cd2d2873302f30303378c0e53816a8.zip
Update vendor
Diffstat (limited to 'vendor/github.com/GeertJohan/go.rice')
-rw-r--r--vendor/github.com/GeertJohan/go.rice/LICENSE22
-rw-r--r--vendor/github.com/GeertJohan/go.rice/appended.go138
-rw-r--r--vendor/github.com/GeertJohan/go.rice/box.go337
-rw-r--r--vendor/github.com/GeertJohan/go.rice/config.go39
-rw-r--r--vendor/github.com/GeertJohan/go.rice/debug.go4
-rw-r--r--vendor/github.com/GeertJohan/go.rice/embedded.go90
-rw-r--r--vendor/github.com/GeertJohan/go.rice/embedded/embedded.go80
-rw-r--r--vendor/github.com/GeertJohan/go.rice/example/example.go69
-rw-r--r--vendor/github.com/GeertJohan/go.rice/file.go144
-rw-r--r--vendor/github.com/GeertJohan/go.rice/http.go21
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/append.go172
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/clean.go33
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/embed-go.go158
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/embed-syso.go204
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/find.go150
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/flags.go80
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/identifier.go14
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/main.go68
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/templates.go98
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/util.go22
-rw-r--r--vendor/github.com/GeertJohan/go.rice/rice/writecoff.go42
-rw-r--r--vendor/github.com/GeertJohan/go.rice/sort.go19
-rw-r--r--vendor/github.com/GeertJohan/go.rice/virtual.go252
-rw-r--r--vendor/github.com/GeertJohan/go.rice/walk.go122
24 files changed, 2378 insertions, 0 deletions
diff --git a/vendor/github.com/GeertJohan/go.rice/LICENSE b/vendor/github.com/GeertJohan/go.rice/LICENSE
new file mode 100644
index 00000000..8b4409d7
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2013, Geert-Johan Riemer
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/vendor/github.com/GeertJohan/go.rice/appended.go b/vendor/github.com/GeertJohan/go.rice/appended.go
new file mode 100644
index 00000000..a986a0c5
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/appended.go
@@ -0,0 +1,138 @@
+package rice
+
+import (
+ "archive/zip"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+
+ "github.com/daaku/go.zipexe"
+ "github.com/kardianos/osext"
+)
+
+// appendedBox defines an appended box
+type appendedBox struct {
+ Name string // box name
+ Files map[string]*appendedFile // appended files (*zip.File) by full path
+}
+
+type appendedFile struct {
+ zipFile *zip.File
+ dir bool
+ dirInfo *appendedDirInfo
+ children []*appendedFile
+ content []byte
+}
+
+// appendedBoxes is a public register of appendes boxes
+var appendedBoxes = make(map[string]*appendedBox)
+
+func init() {
+ // find if exec is appended
+ thisFile, err := osext.Executable()
+ if err != nil {
+ return // not appended or cant find self executable
+ }
+ closer, rd, err := zipexe.OpenCloser(thisFile)
+ if err != nil {
+ return // not appended
+ }
+ defer closer.Close()
+
+ for _, f := range rd.File {
+ // get box and file name from f.Name
+ fileParts := strings.SplitN(strings.TrimLeft(filepath.ToSlash(f.Name), "/"), "/", 2)
+ boxName := fileParts[0]
+ var fileName string
+ if len(fileParts) > 1 {
+ fileName = fileParts[1]
+ }
+
+ // find box or create new one if doesn't exist
+ box := appendedBoxes[boxName]
+ if box == nil {
+ box = &appendedBox{
+ Name: boxName,
+ Files: make(map[string]*appendedFile),
+ }
+ appendedBoxes[boxName] = box
+ }
+
+ // create and add file to box
+ af := &appendedFile{
+ zipFile: f,
+ }
+ if f.Comment == "dir" {
+ af.dir = true
+ af.dirInfo = &appendedDirInfo{
+ name: filepath.Base(af.zipFile.Name),
+ //++ TODO: use zip modtime when that is set correctly: af.zipFile.ModTime()
+ time: time.Now(),
+ }
+ } else {
+ // this is a file, we need it's contents so we can create a bytes.Reader when the file is opened
+ // make a new byteslice
+ af.content = make([]byte, af.zipFile.FileInfo().Size())
+ // ignore reading empty files from zip (empty file still is a valid file to be read though!)
+ if len(af.content) > 0 {
+ // open io.ReadCloser
+ rc, err := af.zipFile.Open()
+ if err != nil {
+ af.content = nil // this will cause an error when the file is being opened or seeked (which is good)
+ // TODO: it's quite blunt to just log this stuff. but this is in init, so rice.Debug can't be changed yet..
+ log.Printf("error opening appended file %s: %v", af.zipFile.Name, err)
+ } else {
+ _, err = rc.Read(af.content)
+ rc.Close()
+ if err != nil {
+ af.content = nil // this will cause an error when the file is being opened or seeked (which is good)
+ // TODO: it's quite blunt to just log this stuff. but this is in init, so rice.Debug can't be changed yet..
+ log.Printf("error reading data for appended file %s: %v", af.zipFile.Name, err)
+ }
+ }
+ }
+ }
+
+ // add appendedFile to box file list
+ box.Files[fileName] = af
+
+ // add to parent dir (if any)
+ dirName := filepath.Dir(fileName)
+ if dirName == "." {
+ dirName = ""
+ }
+ if fileName != "" { // don't make box root dir a child of itself
+ if dir := box.Files[dirName]; dir != nil {
+ dir.children = append(dir.children, af)
+ }
+ }
+ }
+}
+
+// implements os.FileInfo.
+// used for Readdir()
+type appendedDirInfo struct {
+ name string
+ time time.Time
+}
+
+func (adi *appendedDirInfo) Name() string {
+ return adi.name
+}
+func (adi *appendedDirInfo) Size() int64 {
+ return 0
+}
+func (adi *appendedDirInfo) Mode() os.FileMode {
+ return os.ModeDir
+}
+func (adi *appendedDirInfo) ModTime() time.Time {
+ return adi.time
+}
+func (adi *appendedDirInfo) IsDir() bool {
+ return true
+}
+func (adi *appendedDirInfo) Sys() interface{} {
+ return nil
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/box.go b/vendor/github.com/GeertJohan/go.rice/box.go
new file mode 100644
index 00000000..71482e24
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/box.go
@@ -0,0 +1,337 @@
+package rice
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ "github.com/GeertJohan/go.rice/embedded"
+)
+
+// Box abstracts a directory for resources/files.
+// It can either load files from disk, or from embedded code (when `rice --embed` was ran).
+type Box struct {
+ name string
+ absolutePath string
+ embed *embedded.EmbeddedBox
+ appendd *appendedBox
+}
+
+var defaultLocateOrder = []LocateMethod{LocateEmbedded, LocateAppended, LocateFS}
+
+func findBox(name string, order []LocateMethod) (*Box, error) {
+ b := &Box{name: name}
+
+ // no support for absolute paths since gopath can be different on different machines.
+ // therefore, required box must be located relative to package requiring it.
+ if filepath.IsAbs(name) {
+ return nil, errors.New("given name/path is absolute")
+ }
+
+ var err error
+ for _, method := range order {
+ switch method {
+ case LocateEmbedded:
+ if embed := embedded.EmbeddedBoxes[name]; embed != nil {
+ b.embed = embed
+ return b, nil
+ }
+
+ case LocateAppended:
+ appendedBoxName := strings.Replace(name, `/`, `-`, -1)
+ if appendd := appendedBoxes[appendedBoxName]; appendd != nil {
+ b.appendd = appendd
+ return b, nil
+ }
+
+ case LocateFS:
+ // resolve absolute directory path
+ err := b.resolveAbsolutePathFromCaller()
+ if err != nil {
+ continue
+ }
+ // check if absolutePath exists on filesystem
+ info, err := os.Stat(b.absolutePath)
+ if err != nil {
+ continue
+ }
+ // check if absolutePath is actually a directory
+ if !info.IsDir() {
+ err = errors.New("given name/path is not a directory")
+ continue
+ }
+ return b, nil
+ case LocateWorkingDirectory:
+ // resolve absolute directory path
+ err := b.resolveAbsolutePathFromWorkingDirectory()
+ if err != nil {
+ continue
+ }
+ // check if absolutePath exists on filesystem
+ info, err := os.Stat(b.absolutePath)
+ if err != nil {
+ continue
+ }
+ // check if absolutePath is actually a directory
+ if !info.IsDir() {
+ err = errors.New("given name/path is not a directory")
+ continue
+ }
+ return b, nil
+ }
+ }
+
+ if err == nil {
+ err = fmt.Errorf("could not locate box %q", name)
+ }
+
+ return nil, err
+}
+
+// FindBox returns a Box instance for given name.
+// When the given name is a relative path, it's base path will be the calling pkg/cmd's source root.
+// When the given name is absolute, it's absolute. derp.
+// Make sure the path doesn't contain any sensitive information as it might be placed into generated go source (embedded).
+func FindBox(name string) (*Box, error) {
+ return findBox(name, defaultLocateOrder)
+}
+
+// MustFindBox returns a Box instance for given name, like FindBox does.
+// It does not return an error, instead it panics when an error occurs.
+func MustFindBox(name string) *Box {
+ box, err := findBox(name, defaultLocateOrder)
+ if err != nil {
+ panic(err)
+ }
+ return box
+}
+
+// This is injected as a mutable function literal so that we can mock it out in
+// tests and return a fixed test file.
+var resolveAbsolutePathFromCaller = func(name string, nStackFrames int) (string, error) {
+ _, callingGoFile, _, ok := runtime.Caller(nStackFrames)
+ if !ok {
+ return "", errors.New("couldn't find caller on stack")
+ }
+
+ // resolve to proper path
+ pkgDir := filepath.Dir(callingGoFile)
+ // fix for go cover
+ const coverPath = "_test/_obj_test"
+ if !filepath.IsAbs(pkgDir) {
+ if i := strings.Index(pkgDir, coverPath); i >= 0 {
+ pkgDir = pkgDir[:i] + pkgDir[i+len(coverPath):] // remove coverPath
+ pkgDir = filepath.Join(os.Getenv("GOPATH"), "src", pkgDir) // make absolute
+ }
+ }
+ return filepath.Join(pkgDir, name), nil
+}
+
+func (b *Box) resolveAbsolutePathFromCaller() error {
+ path, err := resolveAbsolutePathFromCaller(b.name, 4)
+ if err != nil {
+ return err
+ }
+ b.absolutePath = path
+ return nil
+
+}
+
+func (b *Box) resolveAbsolutePathFromWorkingDirectory() error {
+ path, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+ b.absolutePath = filepath.Join(path, b.name)
+ return nil
+}
+
+// IsEmbedded indicates wether this box was embedded into the application
+func (b *Box) IsEmbedded() bool {
+ return b.embed != nil
+}
+
+// IsAppended indicates wether this box was appended to the application
+func (b *Box) IsAppended() bool {
+ return b.appendd != nil
+}
+
+// Time returns how actual the box is.
+// When the box is embedded, it's value is saved in the embedding code.
+// When the box is live, this methods returns time.Now()
+func (b *Box) Time() time.Time {
+ if b.IsEmbedded() {
+ return b.embed.Time
+ }
+
+ //++ TODO: return time for appended box
+
+ return time.Now()
+}
+
+// Open opens a File from the box
+// If there is an error, it will be of type *os.PathError.
+func (b *Box) Open(name string) (*File, error) {
+ if Debug {
+ fmt.Printf("Open(%s)\n", name)
+ }
+
+ if b.IsEmbedded() {
+ if Debug {
+ fmt.Println("Box is embedded")
+ }
+
+ // trim prefix (paths are relative to box)
+ name = strings.TrimLeft(name, "/")
+ if Debug {
+ fmt.Printf("Trying %s\n", name)
+ }
+
+ // search for file
+ ef := b.embed.Files[name]
+ if ef == nil {
+ if Debug {
+ fmt.Println("Didn't find file in embed")
+ }
+ // file not found, try dir
+ ed := b.embed.Dirs[name]
+ if ed == nil {
+ if Debug {
+ fmt.Println("Didn't find dir in embed")
+ }
+ // dir not found, error out
+ return nil, &os.PathError{
+ Op: "open",
+ Path: name,
+ Err: os.ErrNotExist,
+ }
+ }
+ if Debug {
+ fmt.Println("Found dir. Returning virtual dir")
+ }
+ vd := newVirtualDir(ed)
+ return &File{virtualD: vd}, nil
+ }
+
+ // box is embedded
+ if Debug {
+ fmt.Println("Found file. Returning virtual file")
+ }
+ vf := newVirtualFile(ef)
+ return &File{virtualF: vf}, nil
+ }
+
+ if b.IsAppended() {
+ // trim prefix (paths are relative to box)
+ name = strings.TrimLeft(name, "/")
+
+ // search for file
+ appendedFile := b.appendd.Files[name]
+ if appendedFile == nil {
+ return nil, &os.PathError{
+ Op: "open",
+ Path: name,
+ Err: os.ErrNotExist,
+ }
+ }
+
+ // create new file
+ f := &File{
+ appendedF: appendedFile,
+ }
+
+ // if this file is a directory, we want to be able to read and seek
+ if !appendedFile.dir {
+ // looks like malformed data in zip, error now
+ if appendedFile.content == nil {
+ return nil, &os.PathError{
+ Op: "open",
+ Path: "name",
+ Err: errors.New("error reading data from zip file"),
+ }
+ }
+ // create new bytes.Reader
+ f.appendedFileReader = bytes.NewReader(appendedFile.content)
+ }
+
+ // all done
+ return f, nil
+ }
+
+ // perform os open
+ if Debug {
+ fmt.Printf("Using os.Open(%s)", filepath.Join(b.absolutePath, name))
+ }
+ file, err := os.Open(filepath.Join(b.absolutePath, name))
+ if err != nil {
+ return nil, err
+ }
+ return &File{realF: file}, nil
+}
+
+// Bytes returns the content of the file with given name as []byte.
+func (b *Box) Bytes(name string) ([]byte, error) {
+ file, err := b.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ content, err := ioutil.ReadAll(file)
+ if err != nil {
+ return nil, err
+ }
+
+ return content, nil
+}
+
+// MustBytes returns the content of the file with given name as []byte.
+// panic's on error.
+func (b *Box) MustBytes(name string) []byte {
+ bts, err := b.Bytes(name)
+ if err != nil {
+ panic(err)
+ }
+ return bts
+}
+
+// String returns the content of the file with given name as string.
+func (b *Box) String(name string) (string, error) {
+ // check if box is embedded, optimized fast path
+ if b.IsEmbedded() {
+ // find file in embed
+ ef := b.embed.Files[name]
+ if ef == nil {
+ return "", os.ErrNotExist
+ }
+ // return as string
+ return ef.Content, nil
+ }
+
+ bts, err := b.Bytes(name)
+ if err != nil {
+ return "", err
+ }
+ return string(bts), nil
+}
+
+// MustString returns the content of the file with given name as string.
+// panic's on error.
+func (b *Box) MustString(name string) string {
+ str, err := b.String(name)
+ if err != nil {
+ panic(err)
+ }
+ return str
+}
+
+// Name returns the name of the box
+func (b *Box) Name() string {
+ return b.name
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/config.go b/vendor/github.com/GeertJohan/go.rice/config.go
new file mode 100644
index 00000000..45eb398f
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/config.go
@@ -0,0 +1,39 @@
+package rice
+
+// LocateMethod defines how a box is located.
+type LocateMethod int
+
+const (
+ LocateFS = LocateMethod(iota) // Locate on the filesystem according to package path.
+ LocateAppended // Locate boxes appended to the executable.
+ LocateEmbedded // Locate embedded boxes.
+ LocateWorkingDirectory // Locate on the binary working directory
+)
+
+// Config allows customizing the box lookup behavior.
+type Config struct {
+ // LocateOrder defines the priority order that boxes are searched for. By
+ // default, the package global FindBox searches for embedded boxes first,
+ // then appended boxes, and then finally boxes on the filesystem. That
+ // search order may be customized by provided the ordered list here. Leaving
+ // out a particular method will omit that from the search space. For
+ // example, []LocateMethod{LocateEmbedded, LocateAppended} will never search
+ // the filesystem for boxes.
+ LocateOrder []LocateMethod
+}
+
+// FindBox searches for boxes using the LocateOrder of the config.
+func (c *Config) FindBox(boxName string) (*Box, error) {
+ return findBox(boxName, c.LocateOrder)
+}
+
+// MustFindBox searches for boxes using the LocateOrder of the config, like
+// FindBox does. It does not return an error, instead it panics when an error
+// occurs.
+func (c *Config) MustFindBox(boxName string) *Box {
+ box, err := findBox(boxName, c.LocateOrder)
+ if err != nil {
+ panic(err)
+ }
+ return box
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/debug.go b/vendor/github.com/GeertJohan/go.rice/debug.go
new file mode 100644
index 00000000..2e68c842
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/debug.go
@@ -0,0 +1,4 @@
+package rice
+
+// Debug can be set to true to enable debugging.
+var Debug = false
diff --git a/vendor/github.com/GeertJohan/go.rice/embedded.go b/vendor/github.com/GeertJohan/go.rice/embedded.go
new file mode 100644
index 00000000..4f03fe1f
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/embedded.go
@@ -0,0 +1,90 @@
+package rice
+
+import (
+ "os"
+ "time"
+
+ "github.com/GeertJohan/go.rice/embedded"
+)
+
+// re-type to make exported methods invisible to user (godoc)
+// they're not required for the user
+// embeddedDirInfo implements os.FileInfo
+type embeddedDirInfo embedded.EmbeddedDir
+
+// Name returns the base name of the directory
+// (implementing os.FileInfo)
+func (ed *embeddedDirInfo) Name() string {
+ return ed.Filename
+}
+
+// Size always returns 0
+// (implementing os.FileInfo)
+func (ed *embeddedDirInfo) Size() int64 {
+ return 0
+}
+
+// Mode returns the file mode bits
+// (implementing os.FileInfo)
+func (ed *embeddedDirInfo) Mode() os.FileMode {
+ return os.FileMode(0555 | os.ModeDir) // dr-xr-xr-x
+}
+
+// ModTime returns the modification time
+// (implementing os.FileInfo)
+func (ed *embeddedDirInfo) ModTime() time.Time {
+ return ed.DirModTime
+}
+
+// IsDir returns the abbreviation for Mode().IsDir() (always true)
+// (implementing os.FileInfo)
+func (ed *embeddedDirInfo) IsDir() bool {
+ return true
+}
+
+// Sys returns the underlying data source (always nil)
+// (implementing os.FileInfo)
+func (ed *embeddedDirInfo) Sys() interface{} {
+ return nil
+}
+
+// re-type to make exported methods invisible to user (godoc)
+// they're not required for the user
+// embeddedFileInfo implements os.FileInfo
+type embeddedFileInfo embedded.EmbeddedFile
+
+// Name returns the base name of the file
+// (implementing os.FileInfo)
+func (ef *embeddedFileInfo) Name() string {
+ return ef.Filename
+}
+
+// Size returns the length in bytes for regular files; system-dependent for others
+// (implementing os.FileInfo)
+func (ef *embeddedFileInfo) Size() int64 {
+ return int64(len(ef.Content))
+}
+
+// Mode returns the file mode bits
+// (implementing os.FileInfo)
+func (ef *embeddedFileInfo) Mode() os.FileMode {
+ return os.FileMode(0555) // r-xr-xr-x
+}
+
+// ModTime returns the modification time
+// (implementing os.FileInfo)
+func (ef *embeddedFileInfo) ModTime() time.Time {
+ return ef.FileModTime
+}
+
+// IsDir returns the abbreviation for Mode().IsDir() (always false)
+// (implementing os.FileInfo)
+func (ef *embeddedFileInfo) IsDir() bool {
+ return false
+}
+
+// Sys returns the underlying data source (always nil)
+// (implementing os.FileInfo)
+func (ef *embeddedFileInfo) Sys() interface{} {
+ return nil
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/embedded/embedded.go b/vendor/github.com/GeertJohan/go.rice/embedded/embedded.go
new file mode 100644
index 00000000..bba8e588
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/embedded/embedded.go
@@ -0,0 +1,80 @@
+// Package embedded defines embedded data types that are shared between the go.rice package and generated code.
+package embedded
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+const (
+ EmbedTypeGo = 0
+ EmbedTypeSyso = 1
+)
+
+// EmbeddedBox defines an embedded box
+type EmbeddedBox struct {
+ Name string // box name
+ Time time.Time // embed time
+ EmbedType int // kind of embedding
+ Files map[string]*EmbeddedFile // ALL embedded files by full path
+ Dirs map[string]*EmbeddedDir // ALL embedded dirs by full path
+}
+
+// Link creates the ChildDirs and ChildFiles links in all EmbeddedDir's
+func (e *EmbeddedBox) Link() {
+ for path, ed := range e.Dirs {
+ fmt.Println(path)
+ ed.ChildDirs = make([]*EmbeddedDir, 0)
+ ed.ChildFiles = make([]*EmbeddedFile, 0)
+ }
+ for path, ed := range e.Dirs {
+ parentDirpath, _ := filepath.Split(path)
+ if strings.HasSuffix(parentDirpath, "/") {
+ parentDirpath = parentDirpath[:len(parentDirpath)-1]
+ }
+ parentDir := e.Dirs[parentDirpath]
+ if parentDir == nil {
+ panic("parentDir `" + parentDirpath + "` is missing in embedded box")
+ }
+ parentDir.ChildDirs = append(parentDir.ChildDirs, ed)
+ }
+ for path, ef := range e.Files {
+ dirpath, _ := filepath.Split(path)
+ if strings.HasSuffix(dirpath, "/") {
+ dirpath = dirpath[:len(dirpath)-1]
+ }
+ dir := e.Dirs[dirpath]
+ if dir == nil {
+ panic("dir `" + dirpath + "` is missing in embedded box")
+ }
+ dir.ChildFiles = append(dir.ChildFiles, ef)
+ }
+}
+
+// EmbeddedDir is instanced in the code generated by the rice tool and contains all necicary information about an embedded file
+type EmbeddedDir struct {
+ Filename string
+ DirModTime time.Time
+ ChildDirs []*EmbeddedDir // direct childs, as returned by virtualDir.Readdir()
+ ChildFiles []*EmbeddedFile // direct childs, as returned by virtualDir.Readdir()
+}
+
+// EmbeddedFile is instanced in the code generated by the rice tool and contains all necicary information about an embedded file
+type EmbeddedFile struct {
+ Filename string // filename
+ FileModTime time.Time
+ Content string
+}
+
+// EmbeddedBoxes is a public register of embedded boxes
+var EmbeddedBoxes = make(map[string]*EmbeddedBox)
+
+// RegisterEmbeddedBox registers an EmbeddedBox
+func RegisterEmbeddedBox(name string, box *EmbeddedBox) {
+ if _, exists := EmbeddedBoxes[name]; exists {
+ panic(fmt.Sprintf("EmbeddedBox with name `%s` exists already", name))
+ }
+ EmbeddedBoxes[name] = box
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/example/example.go b/vendor/github.com/GeertJohan/go.rice/example/example.go
new file mode 100644
index 00000000..68f189f3
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/example/example.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+ "encoding/hex"
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "text/template"
+
+ "github.com/GeertJohan/go.rice"
+ "github.com/davecgh/go-spew/spew"
+)
+
+func main() {
+ conf := rice.Config{
+ LocateOrder: []rice.LocateMethod{rice.LocateEmbedded, rice.LocateAppended, rice.LocateFS},
+ }
+ box, err := conf.FindBox("example-files")
+ if err != nil {
+ log.Fatalf("error opening rice.Box: %s\n", err)
+ }
+ // spew.Dump(box)
+
+ contentString, err := box.String("file.txt")
+ if err != nil {
+ log.Fatalf("could not read file contents as string: %s\n", err)
+ }
+ log.Printf("Read some file contents as string:\n%s\n", contentString)
+
+ contentBytes, err := box.Bytes("file.txt")
+ if err != nil {
+ log.Fatalf("could not read file contents as byteSlice: %s\n", err)
+ }
+ log.Printf("Read some file contents as byteSlice:\n%s\n", hex.Dump(contentBytes))
+
+ file, err := box.Open("file.txt")
+ if err != nil {
+ log.Fatalf("could not open file: %s\n", err)
+ }
+ spew.Dump(file)
+
+ // find/create a rice.Box
+ templateBox, err := rice.FindBox("example-templates")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // get file contents as string
+ templateString, err := templateBox.String("message.tmpl")
+ if err != nil {
+ log.Fatal(err)
+ }
+ // parse and execute the template
+ tmplMessage, err := template.New("message").Parse(templateString)
+ if err != nil {
+ log.Fatal(err)
+ }
+ tmplMessage.Execute(os.Stdout, map[string]string{"Message": "Hello, world!"})
+
+ http.Handle("/", http.FileServer(box.HTTPBox()))
+ go func() {
+ fmt.Println("Serving files on :8080, press ctrl-C to exit")
+ err := http.ListenAndServe(":8080", nil)
+ if err != nil {
+ log.Fatalf("error serving files: %v", err)
+ }
+ }()
+ select {}
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/file.go b/vendor/github.com/GeertJohan/go.rice/file.go
new file mode 100644
index 00000000..606a1885
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/file.go
@@ -0,0 +1,144 @@
+package rice
+
+import (
+ "bytes"
+ "errors"
+ "os"
+ "path/filepath"
+)
+
+// File implements the io.Reader, io.Seeker, io.Closer and http.File interfaces
+type File struct {
+ // File abstracts file methods so the user doesn't see the difference between rice.virtualFile, rice.virtualDir and os.File
+ // TODO: maybe use internal File interface and four implementations: *os.File, appendedFile, virtualFile, virtualDir
+
+ // real file on disk
+ realF *os.File
+
+ // when embedded (go)
+ virtualF *virtualFile
+ virtualD *virtualDir
+
+ // when appended (zip)
+ appendedF *appendedFile
+ appendedFileReader *bytes.Reader
+ // TODO: is appendedFileReader subject of races? Might need a lock here..
+}
+
+// Close is like (*os.File).Close()
+// Visit http://golang.org/pkg/os/#File.Close for more information
+func (f *File) Close() error {
+ if f.appendedF != nil {
+ if f.appendedFileReader == nil {
+ return errors.New("already closed")
+ }
+ f.appendedFileReader = nil
+ return nil
+ }
+ if f.virtualF != nil {
+ return f.virtualF.close()
+ }
+ if f.virtualD != nil {
+ return f.virtualD.close()
+ }
+ return f.realF.Close()
+}
+
+// Stat is like (*os.File).Stat()
+// Visit http://golang.org/pkg/os/#File.Stat for more information
+func (f *File) Stat() (os.FileInfo, error) {
+ if f.appendedF != nil {
+ if f.appendedF.dir {
+ return f.appendedF.dirInfo, nil
+ }
+ if f.appendedFileReader == nil {
+ return nil, errors.New("file is closed")
+ }
+ return f.appendedF.zipFile.FileInfo(), nil
+ }
+ if f.virtualF != nil {
+ return f.virtualF.stat()
+ }
+ if f.virtualD != nil {
+ return f.virtualD.stat()
+ }
+ return f.realF.Stat()
+}
+
+// Readdir is like (*os.File).Readdir()
+// Visit http://golang.org/pkg/os/#File.Readdir for more information
+func (f *File) Readdir(count int) ([]os.FileInfo, error) {
+ if f.appendedF != nil {
+ if f.appendedF.dir {
+ fi := make([]os.FileInfo, 0, len(f.appendedF.children))
+ for _, childAppendedFile := range f.appendedF.children {
+ if childAppendedFile.dir {
+ fi = append(fi, childAppendedFile.dirInfo)
+ } else {
+ fi = append(fi, childAppendedFile.zipFile.FileInfo())
+ }
+ }
+ return fi, nil
+ }
+ //++ TODO: is os.ErrInvalid the correct error for Readdir on file?
+ return nil, os.ErrInvalid
+ }
+ if f.virtualF != nil {
+ return f.virtualF.readdir(count)
+ }
+ if f.virtualD != nil {
+ return f.virtualD.readdir(count)
+ }
+ return f.realF.Readdir(count)
+}
+
+// Read is like (*os.File).Read()
+// Visit http://golang.org/pkg/os/#File.Read for more information
+func (f *File) Read(bts []byte) (int, error) {
+ if f.appendedF != nil {
+ if f.appendedFileReader == nil {
+ return 0, &os.PathError{
+ Op: "read",
+ Path: filepath.Base(f.appendedF.zipFile.Name),
+ Err: errors.New("file is closed"),
+ }
+ }
+ if f.appendedF.dir {
+ return 0, &os.PathError{
+ Op: "read",
+ Path: filepath.Base(f.appendedF.zipFile.Name),
+ Err: errors.New("is a directory"),
+ }
+ }
+ return f.appendedFileReader.Read(bts)
+ }
+ if f.virtualF != nil {
+ return f.virtualF.read(bts)
+ }
+ if f.virtualD != nil {
+ return f.virtualD.read(bts)
+ }
+ return f.realF.Read(bts)
+}
+
+// Seek is like (*os.File).Seek()
+// Visit http://golang.org/pkg/os/#File.Seek for more information
+func (f *File) Seek(offset int64, whence int) (int64, error) {
+ if f.appendedF != nil {
+ if f.appendedFileReader == nil {
+ return 0, &os.PathError{
+ Op: "seek",
+ Path: filepath.Base(f.appendedF.zipFile.Name),
+ Err: errors.New("file is closed"),
+ }
+ }
+ return f.appendedFileReader.Seek(offset, whence)
+ }
+ if f.virtualF != nil {
+ return f.virtualF.seek(offset, whence)
+ }
+ if f.virtualD != nil {
+ return f.virtualD.seek(offset, whence)
+ }
+ return f.realF.Seek(offset, whence)
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/http.go b/vendor/github.com/GeertJohan/go.rice/http.go
new file mode 100644
index 00000000..3a61f0e1
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/http.go
@@ -0,0 +1,21 @@
+package rice
+
+import (
+ "net/http"
+)
+
+// HTTPBox implements http.FileSystem which allows the use of Box with a http.FileServer.
+// e.g.: http.Handle("/", http.FileServer(rice.MustFindBox("http-files").HTTPBox()))
+type HTTPBox struct {
+ *Box
+}
+
+// HTTPBox creates a new HTTPBox from an existing Box
+func (b *Box) HTTPBox() *HTTPBox {
+ return &HTTPBox{b}
+}
+
+// Open returns a File using the http.File interface
+func (hb *HTTPBox) Open(name string) (http.File, error) {
+ return hb.Box.Open(name)
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/append.go b/vendor/github.com/GeertJohan/go.rice/rice/append.go
new file mode 100644
index 00000000..ae3d95fd
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/append.go
@@ -0,0 +1,172 @@
+package main
+
+import (
+ "archive/zip"
+ "fmt"
+ "go/build"
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ "github.com/daaku/go.zipexe"
+)
+
+func operationAppend(pkgs []*build.Package) {
+ if runtime.GOOS == "windows" {
+ _, err := exec.LookPath("zip")
+ if err != nil {
+ fmt.Println("#### WARNING ! ####")
+ fmt.Println("`rice append` is known not to work under windows because the `zip` command is not available. Please let me know if you got this to work (and how).")
+ }
+ }
+
+ // MARKED FOR DELETION
+ // This is actually not required, the append command now has the option --exec required.
+ // // check if package is a command
+ // if !pkg.IsCommand() {
+ // fmt.Println("Error: can not append to non-main package. Please follow instructions at github.com/GeertJohan/go.rice")
+ // os.Exit(1)
+ // }
+
+ // create tmp zipfile
+ tmpZipfileName := filepath.Join(os.TempDir(), fmt.Sprintf("ricebox-%d-%s.zip", time.Now().Unix(), randomString(10)))
+ verbosef("Will create tmp zipfile: %s\n", tmpZipfileName)
+ tmpZipfile, err := os.Create(tmpZipfileName)
+ if err != nil {
+ fmt.Printf("Error creating tmp zipfile: %s\n", err)
+ os.Exit(1)
+ }
+ defer func() {
+ tmpZipfile.Close()
+ os.Remove(tmpZipfileName)
+ }()
+
+ // find abs path for binary file
+ binfileName, err := filepath.Abs(flags.Append.Executable)
+ if err != nil {
+ fmt.Printf("Error finding absolute path for executable to append: %s\n", err)
+ os.Exit(1)
+ }
+ verbosef("Will append to file: %s\n", binfileName)
+
+ // check that command doesn't already have zip appended
+ if rd, _ := zipexe.Open(binfileName); rd != nil {
+ fmt.Printf("Cannot append to already appended executable. Please remove %s and build a fresh one.\n", binfileName)
+ os.Exit(1)
+ }
+
+ // open binfile
+ binfile, err := os.OpenFile(binfileName, os.O_WRONLY, os.ModeAppend)
+ if err != nil {
+ fmt.Printf("Error: unable to open executable file: %s\n", err)
+ os.Exit(1)
+ }
+
+ // create zip.Writer
+ zipWriter := zip.NewWriter(tmpZipfile)
+
+ for _, pkg := range pkgs {
+ // find boxes for this command
+ boxMap := findBoxes(pkg)
+
+ // notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
+ if len(boxMap) == 0 {
+ fmt.Printf("no calls to rice.FindBox() or rice.MustFindBox() found in import path `%s`\n", pkg.ImportPath)
+ continue
+ }
+
+ verbosef("\n")
+
+ for boxname := range boxMap {
+ appendedBoxName := strings.Replace(boxname, `/`, `-`, -1)
+
+ // walk box path's and insert files
+ boxPath := filepath.Clean(filepath.Join(pkg.Dir, boxname))
+ filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
+ if info == nil {
+ fmt.Printf("Error: box \"%s\" not found on disk\n", path)
+ os.Exit(1)
+ }
+ // create zipFilename
+ zipFileName := filepath.Join(appendedBoxName, strings.TrimPrefix(path, boxPath))
+ // write directories as empty file with comment "dir"
+ if info.IsDir() {
+ _, err := zipWriter.CreateHeader(&zip.FileHeader{
+ Name: zipFileName,
+ Comment: "dir",
+ })
+ if err != nil {
+ fmt.Printf("Error creating dir in tmp zip: %s\n", err)
+ os.Exit(1)
+ }
+ return nil
+ }
+
+ // create zipFileWriter
+ zipFileHeader, err := zip.FileInfoHeader(info)
+ if err != nil {
+ fmt.Printf("Error creating zip FileHeader: %v\n", err)
+ os.Exit(1)
+ }
+ zipFileHeader.Name = zipFileName
+ zipFileWriter, err := zipWriter.CreateHeader(zipFileHeader)
+ if err != nil {
+ fmt.Printf("Error creating file in tmp zip: %s\n", err)
+ os.Exit(1)
+ }
+ srcFile, err := os.Open(path)
+ if err != nil {
+ fmt.Printf("Error opening file to append: %s\n", err)
+ os.Exit(1)
+ }
+ _, err = io.Copy(zipFileWriter, srcFile)
+ if err != nil {
+ fmt.Printf("Error copying file contents to zip: %s\n", err)
+ os.Exit(1)
+ }
+ srcFile.Close()
+
+ return nil
+ })
+ }
+ }
+
+ err = zipWriter.Close()
+ if err != nil {
+ fmt.Printf("Error closing tmp zipfile: %s\n", err)
+ os.Exit(1)
+ }
+
+ err = tmpZipfile.Sync()
+ if err != nil {
+ fmt.Printf("Error syncing tmp zipfile: %s\n", err)
+ os.Exit(1)
+ }
+ _, err = tmpZipfile.Seek(0, 0)
+ if err != nil {
+ fmt.Printf("Error seeking tmp zipfile: %s\n", err)
+ os.Exit(1)
+ }
+ _, err = binfile.Seek(0, 2)
+ if err != nil {
+ fmt.Printf("Error seeking bin file: %s\n", err)
+ os.Exit(1)
+ }
+
+ _, err = io.Copy(binfile, tmpZipfile)
+ if err != nil {
+ fmt.Printf("Error appending zipfile to executable: %s\n", err)
+ os.Exit(1)
+ }
+
+ zipA := exec.Command("zip", "-A", binfileName)
+ err = zipA.Run()
+ if err != nil {
+ fmt.Printf("Error setting zip offset: %s\n", err)
+ os.Exit(1)
+ }
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/clean.go b/vendor/github.com/GeertJohan/go.rice/rice/clean.go
new file mode 100644
index 00000000..6155c064
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/clean.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func operationClean(pkg *build.Package) {
+ filepath.Walk(pkg.Dir, func(filename string, info os.FileInfo, err error) error {
+ if err != nil {
+ fmt.Printf("error walking pkg dir to clean files: %v\n", err)
+ os.Exit(1)
+ }
+ if info.IsDir() {
+ return nil
+ }
+ verbosef("checking file '%s'\n", filename)
+ if filepath.Base(filename) == "rice-box.go" ||
+ strings.HasSuffix(filename, ".rice-box.go") ||
+ strings.HasSuffix(filename, ".rice-box.syso") {
+ err := os.Remove(filename)
+ if err != nil {
+ fmt.Printf("error removing file (%s): %s\n", filename, err)
+ os.Exit(-1)
+ }
+ verbosef("removed file '%s'\n", filename)
+ }
+ return nil
+ })
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/embed-go.go b/vendor/github.com/GeertJohan/go.rice/rice/embed-go.go
new file mode 100644
index 00000000..c5a0e9e8
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/embed-go.go
@@ -0,0 +1,158 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "go/build"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+const boxFilename = "rice-box.go"
+
+func operationEmbedGo(pkg *build.Package) {
+
+ boxMap := findBoxes(pkg)
+
+ // notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
+ if len(boxMap) == 0 {
+ fmt.Println("no calls to rice.FindBox() found")
+ return
+ }
+
+ verbosef("\n")
+ var boxes []*boxDataType
+
+ for boxname := range boxMap {
+ // find path and filename for this box
+ boxPath := filepath.Join(pkg.Dir, boxname)
+
+ // Check to see if the path for the box is a symbolic link. If so, simply
+ // box what the symbolic link points to. Note: the filepath.Walk function
+ // will NOT follow any nested symbolic links. This only handles the case
+ // where the root of the box is a symbolic link.
+ symPath, serr := os.Readlink(boxPath)
+ if serr == nil {
+ boxPath = symPath
+ }
+
+ // verbose info
+ verbosef("embedding box '%s' to '%s'\n", boxname, boxFilename)
+
+ // read box metadata
+ boxInfo, ierr := os.Stat(boxPath)
+ if ierr != nil {
+ fmt.Printf("Error: unable to access box at %s\n", boxPath)
+ os.Exit(1)
+ }
+
+ // create box datastructure (used by template)
+ box := &boxDataType{
+ BoxName: boxname,
+ UnixNow: boxInfo.ModTime().Unix(),
+ Files: make([]*fileDataType, 0),
+ Dirs: make(map[string]*dirDataType),
+ }
+
+ if !boxInfo.IsDir() {
+ fmt.Printf("Error: Box %s must point to a directory but points to %s instead\n",
+ boxname, boxPath)
+ os.Exit(1)
+ }
+
+ // fill box datastructure with file data
+ filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ fmt.Printf("error walking box: %s\n", err)
+ os.Exit(1)
+ }
+
+ filename := strings.TrimPrefix(path, boxPath)
+ filename = strings.Replace(filename, "\\", "/", -1)
+ filename = strings.TrimPrefix(filename, "/")
+ if info.IsDir() {
+ dirData := &dirDataType{
+ Identifier: "dir" + nextIdentifier(),
+ FileName: filename,
+ ModTime: info.ModTime().Unix(),
+ ChildFiles: make([]*fileDataType, 0),
+ ChildDirs: make([]*dirDataType, 0),
+ }
+ verbosef("\tincludes dir: '%s'\n", dirData.FileName)
+ box.Dirs[dirData.FileName] = dirData
+
+ // add tree entry (skip for root, it'll create a recursion)
+ if dirData.FileName != "" {
+ pathParts := strings.Split(dirData.FileName, "/")
+ parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
+ parentDir.ChildDirs = append(parentDir.ChildDirs, dirData)
+ }
+ } else {
+ fileData := &fileDataType{
+ Identifier: "file" + nextIdentifier(),
+ FileName: filename,
+ ModTime: info.ModTime().Unix(),
+ }
+ verbosef("\tincludes file: '%s'\n", fileData.FileName)
+ fileData.Content, err = ioutil.ReadFile(path)
+ if err != nil {
+ fmt.Printf("error reading file content while walking box: %s\n", err)
+ os.Exit(1)
+ }
+ box.Files = append(box.Files, fileData)
+
+ // add tree entry
+ pathParts := strings.Split(fileData.FileName, "/")
+ parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
+ if parentDir == nil {
+ fmt.Printf("Error: parent of %s is not within the box\n", path)
+ os.Exit(1)
+ }
+ parentDir.ChildFiles = append(parentDir.ChildFiles, fileData)
+ }
+ return nil
+ })
+ boxes = append(boxes, box)
+
+ }
+
+ embedSourceUnformated := bytes.NewBuffer(make([]byte, 0))
+
+ // execute template to buffer
+ err := tmplEmbeddedBox.Execute(
+ embedSourceUnformated,
+ embedFileDataType{pkg.Name, boxes},
+ )
+ if err != nil {
+ log.Printf("error writing embedded box to file (template execute): %s\n", err)
+ os.Exit(1)
+ }
+
+ // format the source code
+ embedSource, err := format.Source(embedSourceUnformated.Bytes())
+ if err != nil {
+ log.Printf("error formatting embedSource: %s\n", err)
+ os.Exit(1)
+ }
+
+ // create go file for box
+ boxFile, err := os.Create(filepath.Join(pkg.Dir, boxFilename))
+ if err != nil {
+ log.Printf("error creating embedded box file: %s\n", err)
+ os.Exit(1)
+ }
+ defer boxFile.Close()
+
+ // write source to file
+ _, err = io.Copy(boxFile, bytes.NewBuffer(embedSource))
+ if err != nil {
+ log.Printf("error writing embedSource to file: %s\n", err)
+ os.Exit(1)
+ }
+
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/embed-syso.go b/vendor/github.com/GeertJohan/go.rice/rice/embed-syso.go
new file mode 100644
index 00000000..beef3ea7
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/embed-syso.go
@@ -0,0 +1,204 @@
+package main
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ "go/build"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "text/template"
+
+ "github.com/GeertJohan/go.rice/embedded"
+ "github.com/akavel/rsrc/coff"
+)
+
+type sizedReader struct {
+ *bytes.Reader
+}
+
+func (s sizedReader) Size() int64 {
+ return int64(s.Len())
+}
+
+var tmplEmbeddedSysoHelper *template.Template
+
+func init() {
+ var err error
+ tmplEmbeddedSysoHelper, err = template.New("embeddedSysoHelper").Parse(`package {{.Package}}
+// ############# GENERATED CODE #####################
+// ## This file was generated by the rice tool.
+// ## Do not edit unless you know what you're doing.
+// ##################################################
+
+// extern char _bricebox_{{.Symname}}[], _ericebox_{{.Symname}};
+// int get_{{.Symname}}_length() {
+// return &_ericebox_{{.Symname}} - _bricebox_{{.Symname}};
+// }
+import "C"
+import (
+ "bytes"
+ "encoding/gob"
+ "github.com/GeertJohan/go.rice/embedded"
+ "unsafe"
+)
+
+func init() {
+ ptr := unsafe.Pointer(&C._bricebox_{{.Symname}})
+ bts := C.GoBytes(ptr, C.get_{{.Symname}}_length())
+ embeddedBox := &embedded.EmbeddedBox{}
+ err := gob.NewDecoder(bytes.NewReader(bts)).Decode(embeddedBox)
+ if err != nil {
+ panic("error decoding embedded box: "+err.Error())
+ }
+ embeddedBox.Link()
+ embedded.RegisterEmbeddedBox(embeddedBox.Name, embeddedBox)
+}`)
+ if err != nil {
+ panic("could not parse template embeddedSysoHelper: " + err.Error())
+ }
+}
+
+type embeddedSysoHelperData struct {
+ Package string
+ Symname string
+}
+
+func operationEmbedSyso(pkg *build.Package) {
+
+ regexpSynameReplacer := regexp.MustCompile(`[^a-z0-9_]`)
+
+ boxMap := findBoxes(pkg)
+
+ // notify user when no calls to rice.FindBox are made (is this an error and therefore os.Exit(1) ?
+ if len(boxMap) == 0 {
+ fmt.Println("no calls to rice.FindBox() found")
+ return
+ }
+
+ verbosef("\n")
+
+ for boxname := range boxMap {
+ // find path and filename for this box
+ boxPath := filepath.Join(pkg.Dir, boxname)
+ boxFilename := strings.Replace(boxname, "/", "-", -1)
+ boxFilename = strings.Replace(boxFilename, "..", "back", -1)
+ boxFilename = strings.Replace(boxFilename, ".", "-", -1)
+
+ // verbose info
+ verbosef("embedding box '%s'\n", boxname)
+ verbosef("\tto file %s\n", boxFilename)
+
+ // read box metadata
+ boxInfo, ierr := os.Stat(boxPath)
+ if ierr != nil {
+ fmt.Printf("Error: unable to access box at %s\n", boxPath)
+ os.Exit(1)
+ }
+
+ // create box datastructure (used by template)
+ box := &embedded.EmbeddedBox{
+ Name: boxname,
+ Time: boxInfo.ModTime(),
+ EmbedType: embedded.EmbedTypeSyso,
+ Files: make(map[string]*embedded.EmbeddedFile),
+ Dirs: make(map[string]*embedded.EmbeddedDir),
+ }
+
+ // fill box datastructure with file data
+ filepath.Walk(boxPath, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ fmt.Printf("error walking box: %s\n", err)
+ os.Exit(1)
+ }
+
+ filename := strings.TrimPrefix(path, boxPath)
+ filename = strings.Replace(filename, "\\", "/", -1)
+ filename = strings.TrimPrefix(filename, "/")
+ if info.IsDir() {
+ embeddedDir := &embedded.EmbeddedDir{
+ Filename: filename,
+ DirModTime: info.ModTime(),
+ }
+ verbosef("\tincludes dir: '%s'\n", embeddedDir.Filename)
+ box.Dirs[embeddedDir.Filename] = embeddedDir
+
+ // add tree entry (skip for root, it'll create a recursion)
+ if embeddedDir.Filename != "" {
+ pathParts := strings.Split(embeddedDir.Filename, "/")
+ parentDir := box.Dirs[strings.Join(pathParts[:len(pathParts)-1], "/")]
+ parentDir.ChildDirs = append(parentDir.ChildDirs, embeddedDir)
+ }
+ } else {
+ embeddedFile := &embedded.EmbeddedFile{
+ Filename: filename,
+ FileModTime: info.ModTime(),
+ Content: "",
+ }
+ verbosef("\tincludes file: '%s'\n", embeddedFile.Filename)
+ contentBytes, err := ioutil.ReadFile(path)
+ if err != nil {
+ fmt.Printf("error reading file content while walking box: %s\n", err)
+ os.Exit(1)
+ }
+ embeddedFile.Content = string(contentBytes)
+ box.Files[embeddedFile.Filename] = embeddedFile
+ }
+ return nil
+ })
+
+ // encode embedded box to gob file
+ boxGobBuf := &bytes.Buffer{}
+ err := gob.NewEncoder(boxGobBuf).Encode(box)
+ if err != nil {
+ fmt.Printf("error encoding box to gob: %v\n", err)
+ os.Exit(1)
+ }
+
+ verbosef("gob-encoded embeddedBox is %d bytes large\n", boxGobBuf.Len())
+
+ // write coff
+ symname := regexpSynameReplacer.ReplaceAllString(boxname, "_")
+ createCoffSyso(boxname, symname, "386", boxGobBuf.Bytes())
+ createCoffSyso(boxname, symname, "amd64", boxGobBuf.Bytes())
+
+ // write go
+ sysoHelperData := embeddedSysoHelperData{
+ Package: pkg.Name,
+ Symname: symname,
+ }
+ fileSysoHelper, err := os.Create(boxFilename + ".rice-box.go")
+ if err != nil {
+ fmt.Printf("error creating syso helper: %v\n", err)
+ os.Exit(1)
+ }
+ err = tmplEmbeddedSysoHelper.Execute(fileSysoHelper, sysoHelperData)
+ if err != nil {
+ fmt.Printf("error executing tmplEmbeddedSysoHelper: %v\n", err)
+ os.Exit(1)
+ }
+ }
+}
+
+func createCoffSyso(boxFilename string, symname string, arch string, data []byte) {
+ boxCoff := coff.NewRDATA()
+ switch arch {
+ case "386":
+ case "amd64":
+ boxCoff.FileHeader.Machine = 0x8664
+ default:
+ panic("invalid arch")
+ }
+ boxCoff.AddData("_bricebox_"+symname, sizedReader{bytes.NewReader(data)})
+ boxCoff.AddData("_ericebox_"+symname, io.NewSectionReader(strings.NewReader("\000\000"), 0, 2)) // TODO: why? copied from rsrc, which copied it from as-generated
+ boxCoff.Freeze()
+ err := writeCoff(boxCoff, boxFilename+"_"+arch+".rice-box.syso")
+ if err != nil {
+ fmt.Printf("error writing %s coff/.syso: %v\n", arch, err)
+ os.Exit(1)
+ }
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/find.go b/vendor/github.com/GeertJohan/go.rice/rice/find.go
new file mode 100644
index 00000000..6d78eeaa
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/find.go
@@ -0,0 +1,150 @@
+package main
+
+import (
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/parser"
+ "go/token"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+func badArgument(fileset *token.FileSet, p token.Pos) {
+ pos := fileset.Position(p)
+ filename := pos.Filename
+ base, err := os.Getwd()
+ if err == nil {
+ rpath, perr := filepath.Rel(base, pos.Filename)
+ if perr == nil {
+ filename = rpath
+ }
+ }
+ msg := fmt.Sprintf("%s:%d: Error: found call to rice.FindBox, "+
+ "but argument must be a string literal.\n", filename, pos.Line)
+ fmt.Println(msg)
+ os.Exit(1)
+}
+
+func findBoxes(pkg *build.Package) map[string]bool {
+ // create map of boxes to embed
+ var boxMap = make(map[string]bool)
+
+ // create one list of files for this package
+ filenames := make([]string, 0, len(pkg.GoFiles)+len(pkg.CgoFiles))
+ filenames = append(filenames, pkg.GoFiles...)
+ filenames = append(filenames, pkg.CgoFiles...)
+
+ // loop over files, search for rice.FindBox(..) calls
+ for _, filename := range filenames {
+ // find full filepath
+ fullpath := filepath.Join(pkg.Dir, filename)
+ if strings.HasSuffix(filename, "rice-box.go") {
+ // Ignore *.rice-box.go files
+ verbosef("skipping file %q\n", fullpath)
+ continue
+ }
+ verbosef("scanning file %q\n", fullpath)
+
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, fullpath, nil, 0)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+
+ var riceIsImported bool
+ ricePkgName := "rice"
+ for _, imp := range f.Imports {
+ if strings.HasSuffix(imp.Path.Value, "go.rice\"") {
+ if imp.Name != nil {
+ ricePkgName = imp.Name.Name
+ }
+ riceIsImported = true
+ break
+ }
+ }
+ if !riceIsImported {
+ // Rice wasn't imported, so we won't find a box.
+ continue
+ }
+ if ricePkgName == "_" {
+ // Rice pkg is unnamed, so we won't find a box.
+ continue
+ }
+
+ // Inspect AST, looking for calls to (Must)?FindBox.
+ // First parameter of the func must be a basic literal.
+ // Identifiers won't be resolved.
+ var nextIdentIsBoxFunc bool
+ var nextBasicLitParamIsBoxName bool
+ var boxCall token.Pos
+ var variableToRemember string
+ var validVariablesForBoxes map[string]bool = make(map[string]bool)
+
+ ast.Inspect(f, func(node ast.Node) bool {
+ if node == nil {
+ return false
+ }
+ switch x := node.(type) {
+ // this case fixes the var := func() style assignments, not assignments to vars declared separately from the assignment.
+ case *ast.AssignStmt:
+ var assign = node.(*ast.AssignStmt)
+ name, found := assign.Lhs[0].(*ast.Ident)
+ if found {
+ variableToRemember = name.Name
+ composite, first := assign.Rhs[0].(*ast.CompositeLit)
+ if first {
+ riceSelector, second := composite.Type.(*ast.SelectorExpr)
+
+ if second {
+ callCorrect := riceSelector.Sel.Name == "Config"
+ packageName, third := riceSelector.X.(*ast.Ident)
+
+ if third && callCorrect && packageName.Name == ricePkgName {
+ validVariablesForBoxes[name.Name] = true
+ verbosef("\tfound variable, saving to scan for boxes: %q\n", name.Name)
+ }
+ }
+ }
+ }
+ case *ast.Ident:
+ if nextIdentIsBoxFunc || ricePkgName == "." {
+ nextIdentIsBoxFunc = false
+ if x.Name == "FindBox" || x.Name == "MustFindBox" {
+ nextBasicLitParamIsBoxName = true
+ boxCall = x.Pos()
+ }
+ } else {
+ if x.Name == ricePkgName || validVariablesForBoxes[x.Name] {
+ nextIdentIsBoxFunc = true
+ }
+ }
+ case *ast.BasicLit:
+ if nextBasicLitParamIsBoxName {
+ if x.Kind == token.STRING {
+ nextBasicLitParamIsBoxName = false
+ // trim "" or ``
+ name := x.Value[1 : len(x.Value)-1]
+ boxMap[name] = true
+ verbosef("\tfound box %q\n", name)
+ } else {
+ badArgument(fset, boxCall)
+ }
+ }
+
+ default:
+ if nextIdentIsBoxFunc {
+ nextIdentIsBoxFunc = false
+ }
+ if nextBasicLitParamIsBoxName {
+ badArgument(fset, boxCall)
+ }
+ }
+ return true
+ })
+ }
+
+ return boxMap
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/flags.go b/vendor/github.com/GeertJohan/go.rice/rice/flags.go
new file mode 100644
index 00000000..167fea80
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/flags.go
@@ -0,0 +1,80 @@
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "os"
+
+ goflags "github.com/jessevdk/go-flags" // rename import to `goflags` (file scope) so we can use `var flags` (package scope)
+)
+
+// flags
+var flags struct {
+ Verbose bool `long:"verbose" short:"v" description:"Show verbose debug information"`
+ ImportPaths []string `long:"import-path" short:"i" description:"Import path(s) to use. Using PWD when left empty. Specify multiple times for more import paths to append"`
+
+ Append struct {
+ Executable string `long:"exec" description:"Executable to append" required:"true"`
+ } `command:"append"`
+
+ EmbedGo struct{} `command:"embed-go" alias:"embed"`
+ EmbedSyso struct{} `command:"embed-syso"`
+ Clean struct{} `command:"clean"`
+}
+
+// flags parser
+var flagsParser *goflags.Parser
+
+// initFlags parses the given flags.
+// when the user asks for help (-h or --help): the application exists with status 0
+// when unexpected flags is given: the application exits with status 1
+func parseArguments() {
+ // create flags parser in global var, for flagsParser.Active.Name (operation)
+ flagsParser = goflags.NewParser(&flags, goflags.Default)
+
+ // parse flags
+ args, err := flagsParser.Parse()
+ if err != nil {
+ // assert the err to be a flags.Error
+ flagError := err.(*goflags.Error)
+ if flagError.Type == goflags.ErrHelp {
+ // user asked for help on flags.
+ // program can exit successfully
+ os.Exit(0)
+ }
+ if flagError.Type == goflags.ErrUnknownFlag {
+ fmt.Println("Use --help to view available options.")
+ os.Exit(1)
+ }
+ if flagError.Type == goflags.ErrRequired {
+ os.Exit(1)
+ }
+ fmt.Printf("Error parsing flags: %s\n", err)
+ os.Exit(1)
+ }
+
+ // error on left-over arguments
+ if len(args) > 0 {
+ fmt.Printf("Unexpected arguments: %s\nUse --help to view available options.", args)
+ os.Exit(1)
+ }
+
+ // default ImportPath to pwd when not set
+ if len(flags.ImportPaths) == 0 {
+ pwd, err := os.Getwd()
+ if err != nil {
+ fmt.Printf("error getting pwd: %s\n", err)
+ os.Exit(1)
+ }
+ verbosef("using pwd as import path\n")
+ // find non-absolute path for this pwd
+ pkg, err := build.ImportDir(pwd, build.FindOnly)
+ if err != nil {
+ fmt.Printf("error using current directory as import path: %s\n", err)
+ os.Exit(1)
+ }
+ flags.ImportPaths = append(flags.ImportPaths, pkg.ImportPath)
+ verbosef("using import paths: %s\n", flags.ImportPaths)
+ return
+ }
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/identifier.go b/vendor/github.com/GeertJohan/go.rice/rice/identifier.go
new file mode 100644
index 00000000..445ee7da
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/identifier.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "strconv"
+
+ "github.com/GeertJohan/go.incremental"
+)
+
+var identifierCount incremental.Uint64
+
+func nextIdentifier() string {
+ num := identifierCount.Next()
+ return strconv.FormatUint(num, 36) // 0123456789abcdefghijklmnopqrstuvwxyz
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/main.go b/vendor/github.com/GeertJohan/go.rice/rice/main.go
new file mode 100644
index 00000000..7bac5fa3
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/main.go
@@ -0,0 +1,68 @@
+package main
+
+import (
+ "fmt"
+ "go/build"
+ "log"
+ "os"
+)
+
+func main() {
+ // parser arguments
+ parseArguments()
+
+ // find package for path
+ var pkgs []*build.Package
+ for _, importPath := range flags.ImportPaths {
+ pkg := pkgForPath(importPath)
+ pkgs = append(pkgs, pkg)
+ }
+
+ // switch on the operation to perform
+ switch flagsParser.Active.Name {
+ case "embed", "embed-go":
+ for _, pkg := range pkgs {
+ operationEmbedGo(pkg)
+ }
+ case "embed-syso":
+ log.Println("WARNING: embedding .syso is experimental..")
+ for _, pkg := range pkgs {
+ operationEmbedSyso(pkg)
+ }
+ case "append":
+ operationAppend(pkgs)
+ case "clean":
+ for _, pkg := range pkgs {
+ operationClean(pkg)
+ }
+ }
+
+ // all done
+ verbosef("\n")
+ verbosef("rice finished successfully\n")
+}
+
+// helper function to get *build.Package for given path
+func pkgForPath(path string) *build.Package {
+ // get pwd for relative imports
+ pwd, err := os.Getwd()
+ if err != nil {
+ fmt.Printf("error getting pwd (required for relative imports): %s\n", err)
+ os.Exit(1)
+ }
+
+ // read full package information
+ pkg, err := build.Import(path, pwd, 0)
+ if err != nil {
+ fmt.Printf("error reading package: %s\n", err)
+ os.Exit(1)
+ }
+
+ return pkg
+}
+
+func verbosef(format string, stuff ...interface{}) {
+ if flags.Verbose {
+ log.Printf(format, stuff...)
+ }
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/templates.go b/vendor/github.com/GeertJohan/go.rice/rice/templates.go
new file mode 100644
index 00000000..02561ca0
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/templates.go
@@ -0,0 +1,98 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "text/template"
+)
+
+var tmplEmbeddedBox *template.Template
+
+func init() {
+ var err error
+
+ // parse embedded box template
+ tmplEmbeddedBox, err = template.New("embeddedBox").Parse(`package {{.Package}}
+
+import (
+ "github.com/GeertJohan/go.rice/embedded"
+ "time"
+)
+
+{{range .Boxes}}
+func init() {
+
+ // define files
+ {{range .Files}}{{.Identifier}} := &embedded.EmbeddedFile{
+ Filename: ` + "`" + `{{.FileName}}` + "`" + `,
+ FileModTime: time.Unix({{.ModTime}}, 0),
+ Content: string({{.Content | printf "%q"}}),
+ }
+ {{end}}
+
+ // define dirs
+ {{range .Dirs}}{{.Identifier}} := &embedded.EmbeddedDir{
+ Filename: ` + "`" + `{{.FileName}}` + "`" + `,
+ DirModTime: time.Unix({{.ModTime}}, 0),
+ ChildFiles: []*embedded.EmbeddedFile{
+ {{range .ChildFiles}}{{.Identifier}}, // {{.FileName}}
+ {{end}}
+ },
+ }
+ {{end}}
+
+ // link ChildDirs
+ {{range .Dirs}}{{.Identifier}}.ChildDirs = []*embedded.EmbeddedDir{
+ {{range .ChildDirs}}{{.Identifier}}, // {{.FileName}}
+ {{end}}
+ }
+ {{end}}
+
+ // register embeddedBox
+ embedded.RegisterEmbeddedBox(` + "`" + `{{.BoxName}}` + "`" + `, &embedded.EmbeddedBox{
+ Name: ` + "`" + `{{.BoxName}}` + "`" + `,
+ Time: time.Unix({{.UnixNow}}, 0),
+ Dirs: map[string]*embedded.EmbeddedDir{
+ {{range .Dirs}}"{{.FileName}}": {{.Identifier}},
+ {{end}}
+ },
+ Files: map[string]*embedded.EmbeddedFile{
+ {{range .Files}}"{{.FileName}}": {{.Identifier}},
+ {{end}}
+ },
+ })
+}
+{{end}}`)
+ if err != nil {
+ fmt.Printf("error parsing embedded box template: %s\n", err)
+ os.Exit(-1)
+ }
+}
+
+type embedFileDataType struct {
+ Package string
+ Boxes []*boxDataType
+}
+
+type boxDataType struct {
+ BoxName string
+ UnixNow int64
+ Files []*fileDataType
+ Dirs map[string]*dirDataType
+}
+
+type fileDataType struct {
+ Identifier string
+ FileName string
+ Content []byte
+ ModTime int64
+}
+
+type dirDataType struct {
+ Identifier string
+ FileName string
+ Content []byte
+ ModTime int64
+ ChildDirs []*dirDataType
+ ChildFiles []*fileDataType
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/util.go b/vendor/github.com/GeertJohan/go.rice/rice/util.go
new file mode 100644
index 00000000..c9ed4b0a
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/util.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "math/rand"
+ "time"
+)
+
+// randomString generates a pseudo-random alpha-numeric string with given length.
+func randomString(length int) string {
+ rand.Seed(time.Now().UnixNano())
+ k := make([]rune, length)
+ for i := 0; i < length; i++ {
+ c := rand.Intn(35)
+ if c < 10 {
+ c += 48 // numbers (0-9) (0+48 == 48 == '0', 9+48 == 57 == '9')
+ } else {
+ c += 87 // lower case alphabets (a-z) (10+87 == 97 == 'a', 35+87 == 122 = 'z')
+ }
+ k[i] = rune(c)
+ }
+ return string(k)
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/rice/writecoff.go b/vendor/github.com/GeertJohan/go.rice/rice/writecoff.go
new file mode 100644
index 00000000..0c12c0ff
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/rice/writecoff.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+
+ "github.com/akavel/rsrc/binutil"
+ "github.com/akavel/rsrc/coff"
+)
+
+// copied from github.com/akavel/rsrc
+// LICENSE: MIT
+// Copyright 2013-2014 The rsrc Authors. (https://github.com/akavel/rsrc/blob/master/AUTHORS)
+func writeCoff(coff *coff.Coff, fnameout string) error {
+ out, err := os.Create(fnameout)
+ if err != nil {
+ return err
+ }
+ defer out.Close()
+ w := binutil.Writer{W: out}
+
+ // write the resulting file to disk
+ binutil.Walk(coff, func(v reflect.Value, path string) error {
+ if binutil.Plain(v.Kind()) {
+ w.WriteLE(v.Interface())
+ return nil
+ }
+ vv, ok := v.Interface().(binutil.SizedReader)
+ if ok {
+ w.WriteFromSized(vv)
+ return binutil.WALK_SKIP
+ }
+ return nil
+ })
+
+ if w.Err != nil {
+ return fmt.Errorf("Error writing output file: %s", w.Err)
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/sort.go b/vendor/github.com/GeertJohan/go.rice/sort.go
new file mode 100644
index 00000000..cd83c658
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/sort.go
@@ -0,0 +1,19 @@
+package rice
+
+import "os"
+
+// SortByName allows an array of os.FileInfo objects
+// to be easily sorted by filename using sort.Sort(SortByName(array))
+type SortByName []os.FileInfo
+
+func (f SortByName) Len() int { return len(f) }
+func (f SortByName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
+func (f SortByName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
+
+// SortByModified allows an array of os.FileInfo objects
+// to be easily sorted by modified date using sort.Sort(SortByModified(array))
+type SortByModified []os.FileInfo
+
+func (f SortByModified) Len() int { return len(f) }
+func (f SortByModified) Less(i, j int) bool { return f[i].ModTime().Unix() > f[j].ModTime().Unix() }
+func (f SortByModified) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
diff --git a/vendor/github.com/GeertJohan/go.rice/virtual.go b/vendor/github.com/GeertJohan/go.rice/virtual.go
new file mode 100644
index 00000000..50bff167
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/virtual.go
@@ -0,0 +1,252 @@
+package rice
+
+import (
+ "errors"
+ "io"
+ "os"
+ "path/filepath"
+ "sort"
+
+ "github.com/GeertJohan/go.rice/embedded"
+)
+
+//++ TODO: IDEA: merge virtualFile and virtualDir, this decreases work done by rice.File
+
+// Error indicating some function is not implemented yet (but available to satisfy an interface)
+var ErrNotImplemented = errors.New("not implemented yet")
+
+// virtualFile is a 'stateful' virtual file.
+// virtualFile wraps an *EmbeddedFile for a call to Box.Open() and virtualizes 'read cursor' (offset) and 'closing'.
+// virtualFile is only internally visible and should be exposed through rice.File
+type virtualFile struct {
+ *embedded.EmbeddedFile // the actual embedded file, embedded to obtain methods
+ offset int64 // read position on the virtual file
+ closed bool // closed when true
+}
+
+// create a new virtualFile for given EmbeddedFile
+func newVirtualFile(ef *embedded.EmbeddedFile) *virtualFile {
+ vf := &virtualFile{
+ EmbeddedFile: ef,
+ offset: 0,
+ closed: false,
+ }
+ return vf
+}
+
+//++ TODO check for nil pointers in all these methods. When so: return os.PathError with Err: os.ErrInvalid
+
+func (vf *virtualFile) close() error {
+ if vf.closed {
+ return &os.PathError{
+ Op: "close",
+ Path: vf.EmbeddedFile.Filename,
+ Err: errors.New("already closed"),
+ }
+ }
+ vf.EmbeddedFile = nil
+ vf.closed = true
+ return nil
+}
+
+func (vf *virtualFile) stat() (os.FileInfo, error) {
+ if vf.closed {
+ return nil, &os.PathError{
+ Op: "stat",
+ Path: vf.EmbeddedFile.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+ return (*embeddedFileInfo)(vf.EmbeddedFile), nil
+}
+
+func (vf *virtualFile) readdir(count int) ([]os.FileInfo, error) {
+ if vf.closed {
+ return nil, &os.PathError{
+ Op: "readdir",
+ Path: vf.EmbeddedFile.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+ //TODO: return proper error for a readdir() call on a file
+ return nil, ErrNotImplemented
+}
+
+func (vf *virtualFile) read(bts []byte) (int, error) {
+ if vf.closed {
+ return 0, &os.PathError{
+ Op: "read",
+ Path: vf.EmbeddedFile.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+
+ end := vf.offset + int64(len(bts))
+
+ if end >= int64(len(vf.Content)) {
+ // end of file, so return what we have + EOF
+ n := copy(bts, vf.Content[vf.offset:])
+ vf.offset = 0
+ return n, io.EOF
+ }
+
+ n := copy(bts, vf.Content[vf.offset:end])
+ vf.offset += int64(n)
+ return n, nil
+
+}
+
+func (vf *virtualFile) seek(offset int64, whence int) (int64, error) {
+ if vf.closed {
+ return 0, &os.PathError{
+ Op: "seek",
+ Path: vf.EmbeddedFile.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+ var e error
+
+ //++ TODO: check if this is correct implementation for seek
+ switch whence {
+ case os.SEEK_SET:
+ //++ check if new offset isn't out of bounds, set e when it is, then break out of switch
+ vf.offset = offset
+ case os.SEEK_CUR:
+ //++ check if new offset isn't out of bounds, set e when it is, then break out of switch
+ vf.offset += offset
+ case os.SEEK_END:
+ //++ check if new offset isn't out of bounds, set e when it is, then break out of switch
+ vf.offset = int64(len(vf.EmbeddedFile.Content)) - offset
+ }
+
+ if e != nil {
+ return 0, &os.PathError{
+ Op: "seek",
+ Path: vf.Filename,
+ Err: e,
+ }
+ }
+
+ return vf.offset, nil
+}
+
+// virtualDir is a 'stateful' virtual directory.
+// virtualDir wraps an *EmbeddedDir for a call to Box.Open() and virtualizes 'closing'.
+// virtualDir is only internally visible and should be exposed through rice.File
+type virtualDir struct {
+ *embedded.EmbeddedDir
+ offset int // readdir position on the directory
+ closed bool
+}
+
+// create a new virtualDir for given EmbeddedDir
+func newVirtualDir(ed *embedded.EmbeddedDir) *virtualDir {
+ vd := &virtualDir{
+ EmbeddedDir: ed,
+ offset: 0,
+ closed: false,
+ }
+ return vd
+}
+
+func (vd *virtualDir) close() error {
+ //++ TODO: needs sync mutex?
+ if vd.closed {
+ return &os.PathError{
+ Op: "close",
+ Path: vd.EmbeddedDir.Filename,
+ Err: errors.New("already closed"),
+ }
+ }
+ vd.closed = true
+ return nil
+}
+
+func (vd *virtualDir) stat() (os.FileInfo, error) {
+ if vd.closed {
+ return nil, &os.PathError{
+ Op: "stat",
+ Path: vd.EmbeddedDir.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+ return (*embeddedDirInfo)(vd.EmbeddedDir), nil
+}
+
+func (vd *virtualDir) readdir(n int) (fi []os.FileInfo, err error) {
+
+ if vd.closed {
+ return nil, &os.PathError{
+ Op: "readdir",
+ Path: vd.EmbeddedDir.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+
+ // Build up the array of our contents
+ var files []os.FileInfo
+
+ // Add the child directories
+ for _, child := range vd.ChildDirs {
+ child.Filename = filepath.Base(child.Filename)
+ files = append(files, (*embeddedDirInfo)(child))
+ }
+
+ // Add the child files
+ for _, child := range vd.ChildFiles {
+ child.Filename = filepath.Base(child.Filename)
+ files = append(files, (*embeddedFileInfo)(child))
+ }
+
+ // Sort it by filename (lexical order)
+ sort.Sort(SortByName(files))
+
+ // Return all contents if that's what is requested
+ if n <= 0 {
+ vd.offset = 0
+ return files, nil
+ }
+
+ // If user has requested past the end of our list
+ // return what we can and send an EOF
+ if vd.offset+n >= len(files) {
+ offset := vd.offset
+ vd.offset = 0
+ return files[offset:], io.EOF
+ }
+
+ offset := vd.offset
+ vd.offset += n
+ return files[offset : offset+n], nil
+
+}
+
+func (vd *virtualDir) read(bts []byte) (int, error) {
+ if vd.closed {
+ return 0, &os.PathError{
+ Op: "read",
+ Path: vd.EmbeddedDir.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+ return 0, &os.PathError{
+ Op: "read",
+ Path: vd.EmbeddedDir.Filename,
+ Err: errors.New("is a directory"),
+ }
+}
+
+func (vd *virtualDir) seek(offset int64, whence int) (int64, error) {
+ if vd.closed {
+ return 0, &os.PathError{
+ Op: "seek",
+ Path: vd.EmbeddedDir.Filename,
+ Err: errors.New("bad file descriptor"),
+ }
+ }
+ return 0, &os.PathError{
+ Op: "seek",
+ Path: vd.Filename,
+ Err: errors.New("is a directory"),
+ }
+}
diff --git a/vendor/github.com/GeertJohan/go.rice/walk.go b/vendor/github.com/GeertJohan/go.rice/walk.go
new file mode 100644
index 00000000..3042aeab
--- /dev/null
+++ b/vendor/github.com/GeertJohan/go.rice/walk.go
@@ -0,0 +1,122 @@
+package rice
+
+import (
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+)
+
+// Walk is like filepath.Walk()
+// Visit http://golang.org/pkg/path/filepath/#Walk for more information
+func (b *Box) Walk(path string, walkFn filepath.WalkFunc) error {
+
+ pathFile, err := b.Open(path)
+ if err != nil {
+ return err
+ }
+ defer pathFile.Close()
+
+ pathInfo, err := pathFile.Stat()
+ if err != nil {
+ return err
+ }
+
+ if b.IsAppended() || b.IsEmbedded() {
+ return b.walk(path, pathInfo, walkFn)
+ }
+
+ // We don't have any embedded or appended box so use live filesystem mode
+ return filepath.Walk(b.absolutePath+string(os.PathSeparator)+path, func(path string, info os.FileInfo, err error) error {
+
+ // Strip out the box name from the returned paths
+ path = strings.TrimPrefix(path, b.absolutePath+string(os.PathSeparator))
+ return walkFn(path, info, err)
+
+ })
+
+}
+
+// walk recursively descends path.
+// See walk() in $GOROOT/src/pkg/path/filepath/path.go
+func (b *Box) walk(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 := b.readDirNames(path)
+ if err != nil {
+ return walkFn(path, info, err)
+ }
+
+ for _, name := range names {
+
+ filename := filepath.Join(path, name)
+ fileObject, err := b.Open(filename)
+ if err != nil {
+ return err
+ }
+ defer fileObject.Close()
+
+ fileInfo, err := fileObject.Stat()
+ if err != nil {
+ if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
+ return err
+ }
+ } else {
+ err = b.walk(filename, fileInfo, walkFn)
+ if err != nil {
+ if !fileInfo.IsDir() || err != filepath.SkipDir {
+ return err
+ }
+ }
+ }
+ }
+
+ return nil
+
+}
+
+// readDirNames reads the directory named by path and returns a sorted list of directory entries.
+// See readDirNames() in $GOROOT/pkg/path/filepath/path.go
+func (b *Box) readDirNames(path string) ([]string, error) {
+
+ f, err := b.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ stat, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+
+ if !stat.IsDir() {
+ return nil, nil
+ }
+
+ infos, err := f.Readdir(0)
+ if err != nil {
+ return nil, err
+ }
+
+ var names []string
+
+ for _, info := range infos {
+ names = append(names, info.Name())
+ }
+
+ sort.Strings(names)
+ return names, nil
+
+}