code: func NewCaches(p *helpers.PathSpec) (Caches, error) {
  	dcfg, err := decodeConfig(p)
  	if err != nil {
  		return nil, err
  	}
  
  	fs := p.Fs.Source
  
  	m := make(Caches)
  	for k, v := range dcfg {
  		var cfs afero.Fs
  
  		if v.isResourceDir {
  			cfs = p.BaseFs.Resources.Fs
  		} else {
  			cfs = fs
  		}
  
  		var baseDir string
  		if !strings.HasPrefix(v.Dir, "_gen") {
  			// We do cache eviction (file removes) and since the user can set
  			// his/hers own cache directory, we really want to make sure
  			// we do not delete any files that do not belong to this cache.
  			// We do add the cache name as the root, but this is an extra safe
  			// guard. We skip the files inside /resources/_gen/ because
  			// that would be breaking.
  			baseDir = filepath.Join(v.Dir, filecacheRootDirname, k)
  		} else {
  			baseDir = filepath.Join(v.Dir, k)
  		}
  		if err = cfs.MkdirAll(baseDir, 0777); err != nil && !os.IsExist(err) {
  			return nil, err
  		}
  
  		bfs := afero.NewBasePathFs(cfs, baseDir)
  
  		m[k] = NewCache(bfs, v.MaxAge)
  	}
  
  	return m, nil
  }
docs: // NewCaches creates a new set of file caches from the given
  // configuration.