github.com/lenfree/buffalo@v0.7.3-0.20170207163156-891616ea4064/render/resolvers/recursive.go (about)

     1  package resolvers
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  )
    10  
    11  // RecursiveResolver will walk the tree of the specified RootPath
    12  // to resolve the given file name to the a path on disk. It is recommended
    13  // to scope this as tight as possible as it is possibly quite slow
    14  // the first time a file is requested. Once a file is found it's resolved
    15  // path is cached to prevent further slow resolutions.
    16  type RecursiveResolver struct {
    17  	Path  string
    18  	cache map[string]string
    19  }
    20  
    21  // Resolve will walk the tree of the specified RootPath
    22  // to resolve the given file name to the a path on disk. It is recommended
    23  // to scope this as tight as possible as it is possibly quite slow
    24  // the first time a file is requested. Once a file is found it's resolved
    25  // path is cached to prevent further slow resolutions.
    26  func (r *RecursiveResolver) Resolve(name string) (string, error) {
    27  	if r.cache == nil {
    28  		r.cache = map[string]string{}
    29  	}
    30  	if p, ok := r.cache[name]; ok {
    31  		return p, nil
    32  	}
    33  	var p string
    34  	var err error
    35  	var found bool
    36  	err = filepath.Walk(r.Path, func(path string, info os.FileInfo, err error) error {
    37  		if strings.HasSuffix(path, name) {
    38  			found = true
    39  			r.cache[name] = path
    40  			p = path
    41  			return err
    42  		}
    43  		return nil
    44  	})
    45  	if err != nil {
    46  		return p, err
    47  	}
    48  	if !found {
    49  		return p, fmt.Errorf("could not find file %s", name)
    50  	}
    51  	return p, nil
    52  }
    53  
    54  // Read will walk the tree of the specified RootPath
    55  // to resolve the given file name to the a path on disk. It is recommended
    56  // to scope this as tight as possible as it is possibly quite slow
    57  // the first time a file is requested. Once a file is found it's resolved
    58  // path is cached to prevent further slow resolutions.
    59  func (r *RecursiveResolver) Read(name string) ([]byte, error) {
    60  	p, err := r.Resolve(name)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	return ioutil.ReadFile(p)
    65  }