create.go (4746B)
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 // Copy copies r to the new targetPath. 55 func (c *Client) Copy(r resource.Resource, targetPath string) (resource.Resource, error) { 56 return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(targetPath), func() (resource.Resource, error) { 57 return resources.Copy(r, targetPath), nil 58 }) 59 } 60 61 // Get creates a new Resource by opening the given filename in the assets filesystem. 62 func (c *Client) Get(filename string) (resource.Resource, error) { 63 filename = filepath.Clean(filename) 64 return c.rs.ResourceCache.GetOrCreate(resources.ResourceCacheKey(filename), func() (resource.Resource, error) { 65 return c.rs.New(resources.ResourceSourceDescriptor{ 66 Fs: c.rs.BaseFs.Assets.Fs, 67 LazyPublish: true, 68 SourceFilename: filename, 69 }) 70 }) 71 } 72 73 // Match gets the resources matching the given pattern from the assets filesystem. 74 func (c *Client) Match(pattern string) (resource.Resources, error) { 75 return c.match("__match", pattern, nil, false) 76 } 77 78 func (c *Client) ByType(tp string) resource.Resources { 79 res, err := c.match(path.Join("_byType", tp), "**", func(r resource.Resource) bool { return r.ResourceType() == tp }, false) 80 if err != nil { 81 panic(err) 82 } 83 return res 84 } 85 86 // GetMatch gets first resource matching the given pattern from the assets filesystem. 87 func (c *Client) GetMatch(pattern string) (resource.Resource, error) { 88 res, err := c.match("__get-match", pattern, nil, true) 89 if err != nil || len(res) == 0 { 90 return nil, err 91 } 92 return res[0], err 93 } 94 95 func (c *Client) match(name, pattern string, matchFunc func(r resource.Resource) bool, firstOnly bool) (resource.Resources, error) { 96 pattern = glob.NormalizePath(pattern) 97 partitions := glob.FilterGlobParts(strings.Split(pattern, "/")) 98 if len(partitions) == 0 { 99 partitions = []string{resources.CACHE_OTHER} 100 } 101 key := path.Join(name, path.Join(partitions...)) 102 key = path.Join(key, pattern) 103 104 return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) { 105 var res resource.Resources 106 107 handle := func(info hugofs.FileMetaInfo) (bool, error) { 108 meta := info.Meta() 109 r, err := c.rs.New(resources.ResourceSourceDescriptor{ 110 LazyPublish: true, 111 FileInfo: info, 112 OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { 113 return meta.Open() 114 }, 115 RelTargetFilename: meta.Path, 116 }) 117 if err != nil { 118 return true, err 119 } 120 121 if matchFunc != nil && !matchFunc(r) { 122 return false, nil 123 } 124 125 res = append(res, r) 126 127 return firstOnly, nil 128 } 129 130 if err := hugofs.Glob(c.rs.BaseFs.Assets.Fs, pattern, handle); err != nil { 131 return nil, err 132 } 133 134 return res, nil 135 }) 136 } 137 138 // FromString creates a new Resource from a string with the given relative target path. 139 func (c *Client) FromString(targetPath, content string) (resource.Resource, error) { 140 return c.rs.ResourceCache.GetOrCreate(path.Join(resources.CACHE_OTHER, targetPath), func() (resource.Resource, error) { 141 return c.rs.New( 142 resources.ResourceSourceDescriptor{ 143 Fs: c.rs.FileCaches.AssetsCache().Fs, 144 LazyPublish: true, 145 OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { 146 return hugio.NewReadSeekerNoOpCloserFromString(content), nil 147 }, 148 RelTargetFilename: filepath.Clean(targetPath), 149 }) 150 }) 151 }