github.com/kovansky/hugo@v0.92.3-0.20220224232819-63076e4ff19f/resources/resource_factories/create/create.go (about)

     1  // Copyright 2019 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  // Package create contains functions for to create Resource objects. This will
    15  // typically non-files.
    16  package create
    17  
    18  import (
    19  	"net/http"
    20  	"path"
    21  	"path/filepath"
    22  	"strings"
    23  	"time"
    24  
    25  	"github.com/gohugoio/hugo/hugofs/glob"
    26  
    27  	"github.com/gohugoio/hugo/hugofs"
    28  
    29  	"github.com/gohugoio/hugo/cache/filecache"
    30  	"github.com/gohugoio/hugo/common/hugio"
    31  	"github.com/gohugoio/hugo/resources"
    32  	"github.com/gohugoio/hugo/resources/resource"
    33  )
    34  
    35  // Client contains methods to create Resource objects.
    36  // tasks to Resource objects.
    37  type Client struct {
    38  	rs               *resources.Spec
    39  	httpClient       *http.Client
    40  	cacheGetResource *filecache.Cache
    41  }
    42  
    43  // New creates a new Client with the given specification.
    44  func New(rs *resources.Spec) *Client {
    45  	return &Client{
    46  		rs: rs,
    47  		httpClient: &http.Client{
    48  			Timeout: 10 * time.Second,
    49  		},
    50  		cacheGetResource: rs.FileCaches.GetResourceCache(),
    51  	}
    52  }
    53  
    54  // Get creates a new Resource by opening the given filename in the assets filesystem.
    55  func (c *Client) Get(filename string) (resource.Resource, error) {
    56  	filename = filepath.Clean(filename)
    57  	return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(filename), func() (resource.Resource, error) {
    58  		return c.rs.New(resources.ResourceSourceDescriptor{
    59  			Fs:             c.rs.BaseFs.Assets.Fs,
    60  			LazyPublish:    true,
    61  			SourceFilename: filename,
    62  		})
    63  	})
    64  }
    65  
    66  // Match gets the resources matching the given pattern from the assets filesystem.
    67  func (c *Client) Match(pattern string) (resource.Resources, error) {
    68  	return c.match(pattern, false)
    69  }
    70  
    71  // GetMatch gets first resource matching the given pattern from the assets filesystem.
    72  func (c *Client) GetMatch(pattern string) (resource.Resource, error) {
    73  	res, err := c.match(pattern, true)
    74  	if err != nil || len(res) == 0 {
    75  		return nil, err
    76  	}
    77  	return res[0], err
    78  }
    79  
    80  func (c *Client) match(pattern string, firstOnly bool) (resource.Resources, error) {
    81  	var name string
    82  	if firstOnly {
    83  		name = "__get-match"
    84  	} else {
    85  		name = "__match"
    86  	}
    87  
    88  	pattern = glob.NormalizePath(pattern)
    89  	partitions := glob.FilterGlobParts(strings.Split(pattern, "/"))
    90  	if len(partitions) == 0 {
    91  		partitions = []string{resources.CACHE_OTHER}
    92  	}
    93  	key := path.Join(name, path.Join(partitions...))
    94  	key = path.Join(key, pattern)
    95  
    96  	return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) {
    97  		var res resource.Resources
    98  
    99  		handle := func(info hugofs.FileMetaInfo) (bool, error) {
   100  			meta := info.Meta()
   101  			r, err := c.rs.New(resources.ResourceSourceDescriptor{
   102  				LazyPublish: true,
   103  				FileInfo:    info,
   104  				OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
   105  					return meta.Open()
   106  				},
   107  				RelTargetFilename: meta.Path,
   108  			})
   109  			if err != nil {
   110  				return true, err
   111  			}
   112  
   113  			res = append(res, r)
   114  
   115  			return firstOnly, nil
   116  		}
   117  
   118  		if err := hugofs.Glob(c.rs.BaseFs.Assets.Fs, pattern, handle); err != nil {
   119  			return nil, err
   120  		}
   121  
   122  		return res, nil
   123  	})
   124  }
   125  
   126  // FromString creates a new Resource from a string with the given relative target path.
   127  func (c *Client) FromString(targetPath, content string) (resource.Resource, error) {
   128  	return c.rs.ResourceCache.GetOrCreate(path.Join(resources.CACHE_OTHER, targetPath), func() (resource.Resource, error) {
   129  		return c.rs.New(
   130  			resources.ResourceSourceDescriptor{
   131  				Fs:          c.rs.FileCaches.AssetsCache().Fs,
   132  				LazyPublish: true,
   133  				OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
   134  					return hugio.NewReadSeekerNoOpCloserFromString(content), nil
   135  				},
   136  				RelTargetFilename: filepath.Clean(targetPath),
   137  			})
   138  	})
   139  }