From 9cbb20aea2d6b1979a47af9956dbcc8dbe2a2e08 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Sat, 20 May 2017 15:43:42 -0700 Subject: add vendor dependencies --- vendor/github.com/GeertJohan/go.rice/appended.go | 138 ++ vendor/github.com/GeertJohan/go.rice/box.go | 337 +++++ vendor/github.com/GeertJohan/go.rice/config.go | 39 + vendor/github.com/GeertJohan/go.rice/debug.go | 4 + vendor/github.com/GeertJohan/go.rice/embedded.go | 90 ++ .../GeertJohan/go.rice/embedded/embedded.go | 80 ++ vendor/github.com/GeertJohan/go.rice/file.go | 144 ++ vendor/github.com/GeertJohan/go.rice/http.go | 21 + vendor/github.com/GeertJohan/go.rice/sort.go | 19 + vendor/github.com/GeertJohan/go.rice/virtual.go | 252 ++++ vendor/github.com/GeertJohan/go.rice/walk.go | 122 ++ vendor/github.com/Xe/gopreload/doc.go | 7 + vendor/github.com/Xe/gopreload/preload.go | 26 + vendor/github.com/Xe/jsonfeed/jsonfeed.go | 242 ++++ vendor/github.com/Xe/ln/filter.go | 66 + vendor/github.com/Xe/ln/formatter.go | 110 ++ vendor/github.com/Xe/ln/logger.go | 141 ++ vendor/github.com/Xe/ln/stack.go | 44 + vendor/github.com/daaku/go.zipexe/zipexe.go | 142 ++ vendor/github.com/google/gops/agent/agent.go | 237 ++++ vendor/github.com/google/gops/internal/internal.go | 52 + vendor/github.com/google/gops/signal/signal.go | 35 + vendor/github.com/gorilla/feeds/atom.go | 163 +++ vendor/github.com/gorilla/feeds/doc.go | 70 + vendor/github.com/gorilla/feeds/feed.go | 106 ++ vendor/github.com/gorilla/feeds/rss.go | 146 ++ vendor/github.com/gorilla/feeds/uuid.go | 27 + vendor/github.com/kardianos/osext/osext.go | 33 + vendor/github.com/kardianos/osext/osext_plan9.go | 20 + vendor/github.com/kardianos/osext/osext_procfs.go | 36 + vendor/github.com/kardianos/osext/osext_sysctl.go | 126 ++ vendor/github.com/kardianos/osext/osext_windows.go | 34 + vendor/github.com/pkg/errors/errors.go | 269 ++++ vendor/github.com/pkg/errors/stack.go | 178 +++ vendor/github.com/russross/blackfriday/block.go | 1450 ++++++++++++++++++++ vendor/github.com/russross/blackfriday/doc.go | 32 + vendor/github.com/russross/blackfriday/html.go | 949 +++++++++++++ vendor/github.com/russross/blackfriday/inline.go | 1152 ++++++++++++++++ vendor/github.com/russross/blackfriday/latex.go | 332 +++++ vendor/github.com/russross/blackfriday/markdown.go | 924 +++++++++++++ .../github.com/russross/blackfriday/smartypants.go | 400 ++++++ vendor/github.com/tj/front/front.go | 24 + 42 files changed, 8819 insertions(+) create mode 100644 vendor/github.com/GeertJohan/go.rice/appended.go create mode 100644 vendor/github.com/GeertJohan/go.rice/box.go create mode 100644 vendor/github.com/GeertJohan/go.rice/config.go create mode 100644 vendor/github.com/GeertJohan/go.rice/debug.go create mode 100644 vendor/github.com/GeertJohan/go.rice/embedded.go create mode 100644 vendor/github.com/GeertJohan/go.rice/embedded/embedded.go create mode 100644 vendor/github.com/GeertJohan/go.rice/file.go create mode 100644 vendor/github.com/GeertJohan/go.rice/http.go create mode 100644 vendor/github.com/GeertJohan/go.rice/sort.go create mode 100644 vendor/github.com/GeertJohan/go.rice/virtual.go create mode 100644 vendor/github.com/GeertJohan/go.rice/walk.go create mode 100644 vendor/github.com/Xe/gopreload/doc.go create mode 100644 vendor/github.com/Xe/gopreload/preload.go create mode 100644 vendor/github.com/Xe/jsonfeed/jsonfeed.go create mode 100644 vendor/github.com/Xe/ln/filter.go create mode 100644 vendor/github.com/Xe/ln/formatter.go create mode 100644 vendor/github.com/Xe/ln/logger.go create mode 100644 vendor/github.com/Xe/ln/stack.go create mode 100644 vendor/github.com/daaku/go.zipexe/zipexe.go create mode 100644 vendor/github.com/google/gops/agent/agent.go create mode 100644 vendor/github.com/google/gops/internal/internal.go create mode 100644 vendor/github.com/google/gops/signal/signal.go create mode 100644 vendor/github.com/gorilla/feeds/atom.go create mode 100644 vendor/github.com/gorilla/feeds/doc.go create mode 100644 vendor/github.com/gorilla/feeds/feed.go create mode 100644 vendor/github.com/gorilla/feeds/rss.go create mode 100644 vendor/github.com/gorilla/feeds/uuid.go create mode 100644 vendor/github.com/kardianos/osext/osext.go create mode 100644 vendor/github.com/kardianos/osext/osext_plan9.go create mode 100644 vendor/github.com/kardianos/osext/osext_procfs.go create mode 100644 vendor/github.com/kardianos/osext/osext_sysctl.go create mode 100644 vendor/github.com/kardianos/osext/osext_windows.go create mode 100644 vendor/github.com/pkg/errors/errors.go create mode 100644 vendor/github.com/pkg/errors/stack.go create mode 100644 vendor/github.com/russross/blackfriday/block.go create mode 100644 vendor/github.com/russross/blackfriday/doc.go create mode 100644 vendor/github.com/russross/blackfriday/html.go create mode 100644 vendor/github.com/russross/blackfriday/inline.go create mode 100644 vendor/github.com/russross/blackfriday/latex.go create mode 100644 vendor/github.com/russross/blackfriday/markdown.go create mode 100644 vendor/github.com/russross/blackfriday/smartypants.go create mode 100644 vendor/github.com/tj/front/front.go (limited to 'vendor/github.com') 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 0000000..a986a0c --- /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 0000000..71482e2 --- /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 0000000..45eb398 --- /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 0000000..2e68c84 --- /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 0000000..4f03fe1 --- /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 0000000..bba8e58 --- /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/file.go b/vendor/github.com/GeertJohan/go.rice/file.go new file mode 100644 index 0000000..606a188 --- /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 0000000..3a61f0e --- /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/sort.go b/vendor/github.com/GeertJohan/go.rice/sort.go new file mode 100644 index 0000000..cd83c65 --- /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 0000000..50bff16 --- /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 0000000..3042aea --- /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 + +} diff --git a/vendor/github.com/Xe/gopreload/doc.go b/vendor/github.com/Xe/gopreload/doc.go new file mode 100644 index 0000000..720c5c1 --- /dev/null +++ b/vendor/github.com/Xe/gopreload/doc.go @@ -0,0 +1,7 @@ +/* +Package gopreload is a bit of a hack to emulate the behavior of LD_PRELOAD [ld-preload]. +This allows you to have automatically starting instrumentation, etc. + +[ld-preload]: http://man7.org/linux/man-pages/man8/ld.so.8.html (see LD_PRELOAD section) +*/ +package gopreload diff --git a/vendor/github.com/Xe/gopreload/preload.go b/vendor/github.com/Xe/gopreload/preload.go new file mode 100644 index 0000000..1b5a0c9 --- /dev/null +++ b/vendor/github.com/Xe/gopreload/preload.go @@ -0,0 +1,26 @@ +//+build linux,go1.8 + +package gopreload + +import ( + "log" + "os" + "plugin" + "strings" +) + +func init() { + gpv := os.Getenv("GO_PRELOAD") + if gpv == "" { + return + } + + for _, elem := range strings.Split(gpv, ",") { + log.Printf("gopreload: trying to open: %s", elem) + _, err := plugin.Open(elem) + if err != nil { + log.Printf("%v from GO_PRELOAD cannot be loaded: %v", elem, err) + continue + } + } +} diff --git a/vendor/github.com/Xe/jsonfeed/jsonfeed.go b/vendor/github.com/Xe/jsonfeed/jsonfeed.go new file mode 100644 index 0000000..e9fa0f2 --- /dev/null +++ b/vendor/github.com/Xe/jsonfeed/jsonfeed.go @@ -0,0 +1,242 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +/* +Package jsonfeed is a set of types and convenience functions for reading and +parsing JSON Feed version 1 as defined here: https://jsonfeed.org/version/1 +*/ +package jsonfeed + +import ( + "encoding/json" + "io" + "time" +) + +// CurrentVersion will point to the current specification of JSON feed +// that this package implements. +const CurrentVersion = "https://jsonfeed.org/version/1" + +// Item is a single article or link in a JSON Feed. +type Item struct { + // ID is unique for that item for that feed over time. If an item + // is ever updated, the id should be unchanged. New items should + // never use a previously-used id. If an id is presented as a number + // or other type, a JSON Feed reader must coerce it to a string. + // Ideally, the id is the full URL of the resource described by the + // item, since URLs make great unique identifiers. + ID string `json:"id"` + + // URL is the URL of the resource described by the item. It’s the + // permalink. This may be the same as the id — but should be present + // regardless. + URL string `json:"url,omitempty"` + + // ExternalURL is the URL of a page elsewhere. This is especially + // useful for linkblogs. If url links to where you’re talking about + // a thing, then this links to the thing you’re talking about. + ExternalURL string `json:"external_url,omitempty"` + + // Title (optional, string) is plain text. Microblog items in + // particular may omit titles. + Title string `json:"title,omitempty"` + + // ContentHTML and ContentText are each optional strings — but one + // or both must be present. This is the HTML or plain text of the + // item. Important: the only place HTML is allowed in this format + // is in content_html. A Twitter-like service might use content_text, + // while a blog might use content_html. Use whichever makes sense + // for your resource. (It doesn’t even have to be the same for each + // item in a feed.) + ContentHTML string `json:"content_html,omitempty"` + ContentText string `json:"content_text,omitempty"` + + // Summary is a plain text sentence or two describing the item. + // This might be presented in a timeline, for instance, where a + // detail view would display all of ContentHTML or ContentText. + Summary string `json:"summary,omitempty"` + + // Image is the URL of the main image for the item. This image + // may also appear in the content_html — if so, it’s a hint to + // the feed reader that this is the main, featured image. Feed + // readers may use the image as a preview (probably resized as + // a thumbnail and placed in a timeline). + Image string `json:"image,omitempty"` + + // BannerImage is the URL of an image to use as a banner. Some + // blogging systems (such as Medium) display a different banner + // image chosen to go with each post, but that image wouldn’t + // otherwise appear in the content_html. A feed reader with a + // detail view may choose to show this banner image at the top + // of the detail view, possibly with the title overlaid. + BannerImage string `json:"banner_image,omitempty"` + + // DatePublished specifies the date of this Item's publication. + DatePublished time.Time `json:"date_published,omitempty"` + + // DateModified specifies the date of this Item's last modification + // (if applicable) + DateModified time.Time `json:"date_modified,omitempty"` + + // Author has the same structure as the top-level author. If not + // specified in an item, then the top-level author, if present, + // is the author of the item. + Author *Author `json:"author,omitempty"` + + // Tags can have any plain text values you want. Tags tend to be + // just one word, but they may be anything. Note: they are not + // the equivalent of Twitter hashtags. Some blogging systems and + // other feed formats call these categories. + Tags []string `json:"tags,omitempty"` + + // Attachments (optional, array) lists related resources. Podcasts, + // for instance, would include an attachment that’s an audio or + // video file. + Attachments []Attachment `json:"attachments,omitempty"` +} + +// Author specifies the feed author. The author object has several members. +// These are all optional, but if you provide an author object, then at +// least one is required. +type Author struct { + // Name is the author's name. + Name string `json:"name,omitempty"` + + // URL is the URL of a site owned by the author. It could be a + // blog, micro-blog, Twitter account, and so on. Ideally the linked-to + // page provides a way to contact the author, but that’s not + // required. The URL could be a mailto: link, though we suspect + // that will be rare. + URL string `json:"url,omitempty"` + + // Avatar is the URL for an image for the author. As with icon, + // it should be square and relatively large — such as 512 x 512 — + // and should use transparency where appropriate, since it may + // be rendered on a non-white background. + Avatar string `json:"avatar,omitempty"` +} + +// Hub describes endpoints that can be used to subscribe to real-time +// notifications from the publisher of this feed. Each object has a type +// and url, both of which are required. +type Hub struct { + Type string `json:"type"` + URL string `json:"url"` +} + +// Attachment is a related resource to an Item. If the Feed describes a +// podcast, this would refer to the episodes of said podcast. +type Attachment struct { + // URL specifies the location of the attachment. + URL string `json:"url"` + + // MIMEType specifies the type of the attachment, such as "audio/mpeg". + MIMEType string `json:"mime_type"` + + // Title is a name for the attachment. Important: if there are multiple + // attachments, and two or more have the exact same title (when title + // is present), then they are considered as alternate representations + // of the same thing. In this way a podcaster, for instance, might + // provide an audio recording in different formats. + Title string `json:"title,omitifempty"` + + // SizeInBytes specifies the attachment filesize in bytes. + SizeInBytes int64 `json:"size_in_bytes,omitempty"` + + // DurationInSeconds specifies how long the attachment takes to listen + // to or watch. + DurationInSeconds int64 `json:"duration_in_seconds,omitempty"` +} + +// Feed is a list that may change over time, and the individual items in the +// list may change. +// +// Think of a blog or microblog, Twitter or Facebook timeline, set of commits +// to a repository, or even a server log. These are all lists, and each could +// be described by a Feed. +// +// A JSON Feed starts with some info at the top: it says where the Feed comes +// from, and may say who created it and so on. +type Feed struct { + // Version is the URL of the version of the format the Feed uses. + Version string `json:"version"` + + // Title is the name of the Feed, which will often correspond to the + // name of the website (blog, for instance), though not necessarily. + Title string `json:"title"` + + // HomePageURL is the URL of the resource that the Feed describes. + // This resource may or may not actually be a “home” page, but it + // should be an HTML page. If a Feed is published on the public web, + // this should be considered as required. But it may not make sense + // in the case of a file created on a desktop computer, when that + // file is not shared or is shared only privately. + // + // This field is strongly reccomended, but not required. + HomePageURL string `json:"home_page_url,omitempty"` + + // FeedURL is the URL of the Feed, and serves as the unique identifier + // for the Feed. As with home_page_url, this should be considered + // required for Feeds on the public web. + // + // This field is strongly reccomended, but not required. + FeedURL string `json:"Feed_url,omitempty"` + + // Description provides more detail, beyond the title, on what the Feed + // is about. A Feed reader may display this text. + Description string `json:"description,omitempty"` + + // UserComment is a description of the purpose of the Feed. This is for + // the use of people looking at the raw JSON, and should be ignored by + // Feed readers. + UserComment string `json:"user_comment,omitempty"` + + // NextURL is the URL of a Feed that provides the next n items, where + // n is determined by the publisher. This allows for pagination, but + // with the expectation that reader software is not required to use it + // and probably won’t use it very often. next_url must not be the same + // as Feed_url, and it must not be the same as a previous next_url + // (to avoid infinite loops). + NextURL string `json:"next_url,omitempty"` + + // Icon is the URL of an image for the Feed suitable to be used in a + // timeline, much the way an avatar might be used. It should be square + // and relatively large — such as 512 x 512 — so that it can be scaled-down + // and so that it can look good on retina displays. It should use transparency + // where appropriate, since it may be rendered on a non-white background. + Icon string `json:"icon,omitempty"` + + // Favicon is the URL of an image for the Feed suitable to be used in a + // source list. It should be square and relatively small, but not smaller + // than 64 x 64 (so that it can look good on retina displays). As with icon, + // this image should use transparency where appropriate, since it may be + // rendered on a non-white background. + Favicon string `json:"favicon,omitempty"` + + // Author specifies the Feed author. + Author Author `json:"author,omitempty"` + + // Expired specifies if the Feed will never update again. A Feed for a + // temporary event, such as an instance of the Olympics, could expire. + // If the value is true, then it’s expired. Any other value, or the + // absence of expired, means the Feed may continue to update. + Expired bool `json:"expired,omitempty"` + + // Hubs describes endpoints that can be used to subscribe to real-time + // notifications from the publisher of this Feed. + Hubs []Hub `json:"hubs,omitempty"` + + // Items is the list of Items in this Feed. + Items []Item `json:"items"` +} + +// Parse reads a JSON feed object out of a reader. +func Parse(r io.Reader) (Feed, error) { + var feed Feed + decoder := json.NewDecoder(r) + if err := decoder.Decode(&feed); err != nil { + return Feed{}, err + } + return feed, nil +} diff --git a/vendor/github.com/Xe/ln/filter.go b/vendor/github.com/Xe/ln/filter.go new file mode 100644 index 0000000..586efef --- /dev/null +++ b/vendor/github.com/Xe/ln/filter.go @@ -0,0 +1,66 @@ +package ln + +import ( + "io" + "sync" +) + +// Filter interface for defining chain filters +type Filter interface { + Apply(Event) bool + Run() + Close() +} + +// FilterFunc allows simple functions to implement the Filter interface +type FilterFunc func(e Event) bool + +// Apply implements the Filter interface +func (ff FilterFunc) Apply(e Event) bool { + return ff(e) +} + +// Run implements the Filter interface +func (ff FilterFunc) Run() {} + +// Close implements the Filter interface +func (ff FilterFunc) Close() {} + +// WriterFilter implements a filter, which arbitrarily writes to an io.Writer +type WriterFilter struct { + sync.Mutex + Out io.Writer + Formatter Formatter +} + +// NewWriterFilter creates a filter to add to the chain +func NewWriterFilter(out io.Writer, format Formatter) *WriterFilter { + if format == nil { + format = DefaultFormatter + } + return &WriterFilter{ + Out: out, + Formatter: format, + } +} + +// Apply implements the Filter interface +func (w *WriterFilter) Apply(e Event) bool { + output, err := w.Formatter.Format(e) + if err == nil { + w.Lock() + w.Out.Write(output) + w.Unlock() + } + + return true +} + +// Run implements the Filter interface +func (w *WriterFilter) Run() {} + +// Close implements the Filter interface +func (w *WriterFilter) Close() {} + +// NilFilter is safe to return as a Filter, but does nothing +var NilFilter = FilterFunc(func(e Event) bool { return true }) diff --git a/vendor/github.com/Xe/ln/formatter.go b/vendor/github.com/Xe/ln/formatter.go new file mode 100644 index 0000000..ecd4743 --- /dev/null +++ b/vendor/github.com/Xe/ln/formatter.go @@ -0,0 +1,110 @@ +package ln + +import ( + "bytes" + "fmt" + "time" +) + +var ( + // DefaultTimeFormat represents the way in which time will be formatted by default + DefaultTimeFormat = time.RFC3339 +) + +// Formatter defines the formatting of events +type Formatter interface { + Format(Event) ([]byte, error) +} + +// DefaultFormatter is the default way in which to format events +var DefaultFormatter Formatter + +func init() { + DefaultFormatter = NewTextFormatter() +} + +// TextFormatter formats events as key value pairs. +// Any remaining text not wrapped in an instance of `F` will be +// placed at the end. +type TextFormatter struct { + TimeFormat string +} + +// NewTextFormatter returns a Formatter that outputs as text. +func NewTextFormatter() Formatter { + return &TextFormatter{TimeFormat: DefaultTimeFormat} +} + +// Format implements the Formatter interface +func (t *TextFormatter) Format(e Event) ([]byte, error) { + var writer bytes.Buffer + + writer.WriteString("time=\"") + writer.WriteString(e.Time.Format(t.TimeFormat)) + writer.WriteString("\"") + + keys := make([]string, len(e.Data)) + i := 0 + + for k := range e.Data { + keys[i] = k + i++ + } + + for _, k := range keys { + v := e.Data[k] + + writer.WriteByte(' ') + if shouldQuote(k) { + writer.WriteString(fmt.Sprintf("%q", k)) + } else { + writer.WriteString(k) + } + + writer.WriteByte('=') + + switch v.(type) { + case string: + vs, _ := v.(string) + if shouldQuote(vs) { + fmt.Fprintf(&writer, "%q", vs) + } else { + writer.WriteString(vs) + } + case error: + tmperr, _ := v.(error) + es := tmperr.Error() + + if shouldQuote(es) { + fmt.Fprintf(&writer, "%q", es) + } else { + writer.WriteString(es) + } + case time.Time: + tmptime, _ := v.(time.Time) + writer.WriteString(tmptime.Format(time.RFC3339)) + default: + fmt.Fprint(&writer, v) + } + } + + if len(e.Message) > 0 { + fmt.Fprintf(&writer, " _msg=%q", e.Message) + } + + writer.WriteByte('\n') + return writer.Bytes(), nil +} + +func shouldQuote(s string) bool { + for _, b := range s { + if !((b >= 'A' && b <= 'Z') || + (b >= 'a' && b <= 'z') || + (b >= '0' && b <= '9') || + (b == '-' || b == '.' || b == '#' || + b == '/' || b == '_')) { + return true + } + } + return false +} diff --git a/vendor/github.com/Xe/ln/logger.go b/vendor/github.com/Xe/ln/logger.go new file mode 100644 index 0000000..cdfe89e --- /dev/null +++ b/vendor/github.com/Xe/ln/logger.go @@ -0,0 +1,141 @@ +package ln + +import ( + "fmt" + "os" + "time" + + "github.com/pkg/errors" +) + +// Logger holds the current priority and list of filters +type Logger struct { + Filters []Filter +} + +// DefaultLogger is the default implementation of Logger +var DefaultLogger *Logger + +func init() { + var defaultFilters []Filter + + // Default to STDOUT for logging, but allow LN_OUT to change it. + out := os.Stdout + if os.Getenv("LN_OUT") == "" { + out = os.Stderr + } + + defaultFilters = append(defaultFilters, NewWriterFilter(out, nil)) + + DefaultLogger = &Logger{ + Filters: defaultFilters, + } + +} + +// F is a key-value mapping for structured data. +type F map[string]interface{} + +type Fer interface { + F() map[string]interface{} +} + +// Event represents an event +type Event struct { + Time time.Time + Data F + Message string +} + +// Log is the generic logging method. +func (l *Logger) Log(xs ...interface{}) { + var bits []interface{} + event := Event{Time: time.Now()} + + addF := func(bf F) { + if event.Data == nil { + event.Data = bf + } else { + for k, v := range bf { + event.Data[k] = v + } + } + } + + // Assemble the event + for _, b := range xs { + if bf, ok := b.(F); ok { + addF(bf) + } else if fer, ok := b.(Fer); ok { + addF(F(fer.F())) + } else { + bits = append(bits, b) + } + } + + event.Message = fmt.Sprint(bits...) + + if os.Getenv("LN_DEBUG_ALL_EVENTS") == "1" { + frame := callersFrame() + if event.Data == nil { + event.Data = make(F) + } + event.Data["_lineno"] = frame.lineno + event.Data["_function"] = frame.function + event.Data["_filename"] = frame.filename + } + + l.filter(event) +} + +func (l *Logger) filter(e Event) { + for _, f := range l.Filters { + if !f.Apply(e) { + return + } + } +} + +// Error logs an error and information about the context of said error. +func (l *Logger) Error(err error, xs ...interface{}) { + data := F{} + frame := callersFrame() + + data["_lineno"] = frame.lineno + data["_function"] = frame.function + data["_filename"] = frame.filename + data["err"] = err + + cause := errors.Cause(err) + if cause != nil { + data["cause"] = cause.Error() + } + + xs = append(xs, data) + + l.Log(xs...) +} + +// Fatal logs this set of values, then exits with status code 1. +func (l *Logger) Fatal(xs ...interface{}) { + l.Log(xs...) + + os.Exit(1) +} + +// Default Implementation + +// Log is the generic logging method. +func Log(xs ...interface{}) { + DefaultLogger.Log(xs...) +} + +// Error logs an error and information about the context of said error. +func Error(err error, xs ...interface{}) { + DefaultLogger.Error(err, xs...) +} + +// Fatal logs this set of values, then exits with status code 1. +func Fatal(xs ...interface{}) { + DefaultLogger.Fatal(xs...) +} diff --git a/vendor/github.com/Xe/ln/stack.go b/vendor/github.com/Xe/ln/stack.go new file mode 100644 index 0000000..1cf1e7a --- /dev/null +++ b/vendor/github.com/Xe/ln/stack.go @@ -0,0 +1,44 @@ +package ln + +import ( + "os" + "runtime" + "strings" +) + +type frame struct { + filename string + function string + lineno int +} + +// skips 2 frames, since Caller returns the current frame, and we need +// the caller's caller. +func callersFrame() frame { + var out frame + pc, file, line, ok := runtime.Caller(3) + if !ok { + return out + } + srcLoc := strings.LastIndex(file, "/src/") + if srcLoc >= 0 { + file = file[srcLoc+5:] + } + out.filename = file + out.function = functionName(pc) + out.lineno = line + + return out +} + +func functionName(pc uintptr) string { + fn := runtime.FuncForPC(pc) + if fn == nil { + return "???" + } + name := fn.Name() + beg := strings.LastIndex(name, string(os.PathSeparator)) + return name[beg+1:] + // end := strings.LastIndex(name, string(os.PathSeparator)) + // return name[end+1 : len(name)] +} diff --git a/vendor/github.com/daaku/go.zipexe/zipexe.go b/vendor/github.com/daaku/go.zipexe/zipexe.go new file mode 100644 index 0000000..6004606 --- /dev/null +++ b/vendor/github.com/daaku/go.zipexe/zipexe.go @@ -0,0 +1,142 @@ +// Package zipexe attempts to open an executable binary file as a zip file. +package zipexe + +import ( + "archive/zip" + "debug/elf" + "debug/macho" + "debug/pe" + "errors" + "io" + "os" +) + +// Opens a zip file by path. +func Open(path string) (*zip.Reader, error) { + _, rd, err := OpenCloser(path) + return rd, err +} + +// OpenCloser is like Open but returns an additional Closer to avoid leaking open files. +func OpenCloser(path string) (io.Closer, *zip.Reader, error) { + file, err := os.Open(path) + if err != nil { + return nil, nil, err + } + finfo, err := file.Stat() + if err != nil { + return nil, nil, err + } + zr, err := NewReader(file, finfo.Size()) + if err != nil { + return nil, nil, err + } + return file, zr, nil +} + +// Open a zip file, specially handling various binaries that may have been +// augmented with zip data. +func NewReader(rda io.ReaderAt, size int64) (*zip.Reader, error) { + handlers := []func(io.ReaderAt, int64) (*zip.Reader, error){ + zip.NewReader, + zipExeReaderMacho, + zipExeReaderElf, + zipExeReaderPe, + } + + for _, handler := range handlers { + zfile, err := handler(rda, size) + if err == nil { + return zfile, nil + } + } + return nil, errors.New("Couldn't Open As Executable") +} + +// zipExeReaderMacho treats the file as a Mach-O binary +// (Mac OS X / Darwin executable) and attempts to find a zip archive. +func zipExeReaderMacho(rda io.ReaderAt, size int64) (*zip.Reader, error) { + file, err := macho.NewFile(rda) + if err != nil { + return nil, err + } + + var max int64 + for _, load := range file.Loads { + seg, ok := load.(*macho.Segment) + if ok { + // Check if the segment contains a zip file + if zfile, err := zip.NewReader(seg, int64(seg.Filesz)); err == nil { + return zfile, nil + } + + // Otherwise move end of file pointer + end := int64(seg.Offset + seg.Filesz) + if end > max { + max = end + } + } + } + + // No zip file within binary, try appended to end + section := io.NewSectionReader(rda, max, size-max) + return zip.NewReader(section, section.Size()) +} + +// zipExeReaderPe treats the file as a Portable Exectuable binary +// (Windows executable) and attempts to find a zip archive. +func zipExeReaderPe(rda io.ReaderAt, size int64) (*zip.Reader, error) { + file, err := pe.NewFile(rda) + if err != nil { + return nil, err + } + + var max int64 + for _, sec := range file.Sections { + // Check if this section has a zip file + if zfile, err := zip.NewReader(sec, int64(sec.Size)); err == nil { + return zfile, nil + } + + // Otherwise move end of file pointer + end := int64(sec.Offset + sec.Size) + if end > max { + max = end + } + } + + // No zip file within binary, try appended to end + section := io.NewSectionReader(rda, max, size-max) + return zip.NewReader(section, section.Size()) +} + +// zipExeReaderElf treats the file as a ELF binary +// (linux/BSD/etc... executable) and attempts to find a zip archive. +func zipExeReaderElf(rda io.ReaderAt, size int64) (*zip.Reader, error) { + file, err := elf.NewFile(rda) + if err != nil { + return nil, err + } + + var max int64 + for _, sect := range file.Sections { + if sect.Type == elf.SHT_NOBITS { + continue + } + + // Check if this section has a zip file + if zfile, err := zip.NewReader(sect, int64(sect.Size)); err == nil { + return zfile, nil + } + + // Otherwise move end of file pointer + end := int64(sect.Offset + sect.Size) + if end > max { + max = end + } + } + + // No zip file within binary, try appended to end + section := io.NewSectionReader(rda, max, size-max) + return zip.NewReader(section, section.Size()) +} diff --git a/vendor/github.com/google/gops/agent/agent.go b/vendor/github.com/google/gops/agent/agent.go new file mode 100644 index 0000000..5708391 --- /dev/null +++ b/vendor/github.com/google/gops/agent/agent.go @@ -0,0 +1,237 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package a