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/go.rice/box.go | |
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/go.rice/box.go')
-rw-r--r-- | vendor/github.com/GeertJohan/go.rice/box.go | 337 |
1 files changed, 337 insertions, 0 deletions
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 +} |