diff options
author | Wim <wim@42.be> | 2017-02-18 23:00:46 +0100 |
---|---|---|
committer | Wim <wim@42.be> | 2017-02-18 23:11:48 +0100 |
commit | 930b639cc9cd2d2873302f30303378c0e53816a8 (patch) | |
tree | 8cd3f1d464fb5d4e5607fe16255c35a31a9d8b62 /vendor/github.com/GeertJohan | |
parent | 58483ea70c2c99a352592c5e50686fb03985650e (diff) | |
download | matterbridge-msglm-930b639cc9cd2d2873302f30303378c0e53816a8.tar.gz matterbridge-msglm-930b639cc9cd2d2873302f30303378c0e53816a8.tar.bz2 matterbridge-msglm-930b639cc9cd2d2873302f30303378c0e53816a8.zip |
Update vendor
Diffstat (limited to 'vendor/github.com/GeertJohan')
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 + +} |