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 }