Skip to content

Commit f9b4eb4

Browse files
committed
Handle themes in the new file cache (for images, assets)
In the newly consolidated file cache implementation, we forgot that we also look in the theme(s) for assets (SCSS transformations etc.), which is not good for Netlify and the demo sites. Fixes #5460
1 parent e82b2dc commit f9b4eb4

File tree

11 files changed

+206
-96
lines changed

11 files changed

+206
-96
lines changed

‎cache/filecache/filecache.go‎

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"bytes"
1818
"io"
1919
"io/ioutil"
20+
"os"
2021
"path/filepath"
2122
"strings"
2223
"sync"
@@ -26,8 +27,6 @@ import (
2627

2728
"github.com/gohugoio/hugo/helpers"
2829

29-
"github.com/gohugoio/hugo/hugolib/paths"
30-
3130
"github.com/BurntSushi/locker"
3231
"github.com/spf13/afero"
3332
)
@@ -305,22 +304,28 @@ func (f Caches) Get(name string) *Cache {
305304
return f[strings.ToLower(name)]
306305
}
307306

308-
// NewCachesFromPaths creates a new set of file caches from the given
307+
// NewCaches creates a new set of file caches from the given
309308
// configuration.
310-
func NewCachesFromPaths(p *paths.Paths) (Caches, error) {
309+
func NewCaches(p *helpers.PathSpec) (Caches, error) {
311310
dcfg, err := decodeConfig(p)
312311
if err != nil {
313312
return nil, err
314313
}
315314

316-
genDir := filepath.FromSlash("/_gen")
317-
318315
fs := p.Fs.Source
319316

320317
m := make(Caches)
321318
for k, v := range dcfg {
319+
var cfs afero.Fs
320+
321+
if v.isResourceDir {
322+
cfs = p.BaseFs.Resources.Fs
323+
} else {
324+
cfs = fs
325+
}
326+
322327
var baseDir string
323-
if !strings.Contains(v.Dir, genDir) {
328+
if !strings.HasPrefix(v.Dir, "_gen") {
324329
// We do cache eviction (file removes) and since the user can set
325330
// his/hers own cache directory, we really want to make sure
326331
// we do not delete any files that do not belong to this cache.
@@ -331,10 +336,12 @@ func NewCachesFromPaths(p *paths.Paths) (Caches, error) {
331336
} else {
332337
baseDir = filepath.Join(v.Dir, k)
333338
}
334-
if err = fs.MkdirAll(baseDir, 0777); err != nil {
339+
if err = cfs.MkdirAll(baseDir, 0777); err != nil && !os.IsExist(err) {
335340
return nil, err
336341
}
337-
bfs := afero.NewBasePathFs(fs, baseDir)
342+
343+
bfs := afero.NewBasePathFs(cfs, baseDir)
344+
338345
m[k] = NewCache(bfs, v.MaxAge)
339346
}
340347

‎cache/filecache/filecache_config.go‎

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"time"
2121

2222
"github.com/gohugoio/hugo/helpers"
23-
"github.com/gohugoio/hugo/hugolib/paths"
2423

2524
"github.com/bep/mapstructure"
2625
"github.com/pkg/errors"
@@ -68,6 +67,10 @@ type cacheConfig struct {
6867

6968
// The directory where files are stored.
7069
Dir string
70+
71+
// Will resources/_gen will get its own composite filesystem that
72+
// also checks any theme.
73+
isResourceDir bool
7174
}
7275

7376
// GetJSONCache gets the file cache for getJSON.
@@ -90,7 +93,7 @@ func (f Caches) AssetsCache() *Cache {
9093
return f[cacheKeyAssets]
9194
}
9295

93-
func decodeConfig(p *paths.Paths) (cachesConfig, error) {
96+
func decodeConfig(p *helpers.PathSpec) (cachesConfig, error) {
9497
c := make(cachesConfig)
9598
valid := make(map[string]bool)
9699
// Add defaults
@@ -145,10 +148,13 @@ func decodeConfig(p *paths.Paths) (cachesConfig, error) {
145148

146149
for i, part := range parts {
147150
if strings.HasPrefix(part, ":") {
148-
resolved, err := resolveDirPlaceholder(p, part)
151+
resolved, isResource, err := resolveDirPlaceholder(p, part)
149152
if err != nil {
150153
return c, err
151154
}
155+
if isResource {
156+
v.isResourceDir = true
157+
}
152158
parts[i] = resolved
153159
}
154160
}
@@ -159,13 +165,15 @@ func decodeConfig(p *paths.Paths) (cachesConfig, error) {
159165
}
160166
v.Dir = filepath.Clean(filepath.FromSlash(dir))
161167

162-
if isOsFs && !filepath.IsAbs(v.Dir) {
163-
return c, errors.Errorf("%q must resolve to an absolute directory", v.Dir)
164-
}
168+
if !v.isResourceDir {
169+
if isOsFs && !filepath.IsAbs(v.Dir) {
170+
return c, errors.Errorf("%q must resolve to an absolute directory", v.Dir)
171+
}
165172

166-
// Avoid cache in root, e.g. / (Unix) or c:\ (Windows)
167-
if len(strings.TrimPrefix(v.Dir, filepath.VolumeName(v.Dir))) == 1 {
168-
return c, errors.Errorf("%q is a root folder and not allowed as cache dir", v.Dir)
173+
// Avoid cache in root, e.g. / (Unix) or c:\ (Windows)
174+
if len(strings.TrimPrefix(v.Dir, filepath.VolumeName(v.Dir))) == 1 {
175+
return c, errors.Errorf("%q is a root folder and not allowed as cache dir", v.Dir)
176+
}
169177
}
170178

171179
if disabled {
@@ -179,15 +187,16 @@ func decodeConfig(p *paths.Paths) (cachesConfig, error) {
179187
}
180188

181189
// Resolves :resourceDir => /myproject/resources etc., :cacheDir => ...
182-
func resolveDirPlaceholder(p *paths.Paths, placeholder string) (string, error) {
190+
func resolveDirPlaceholder(p *helpers.PathSpec, placeholder string) (cacheDir string, isResource bool, err error) {
183191
switch strings.ToLower(placeholder) {
184192
case ":resourcedir":
185-
return p.AbsResourcesDir, nil
193+
return "", true, nil
186194
case ":cachedir":
187-
return helpers.GetCacheDir(p.Fs.Source, p.Cfg)
195+
d, err := helpers.GetCacheDir(p.Fs.Source, p.Cfg)
196+
return d, false, err
188197
case ":project":
189-
return filepath.Base(p.WorkingDir), nil
198+
return filepath.Base(p.WorkingDir), false, nil
190199
}
191200

192-
return "", errors.Errorf("%q is not a valid placeholder (valid values are :cacheDir or :resourceDir)", placeholder)
201+
return "", false, errors.Errorf("%q is not a valid placeholder (valid values are :cacheDir or :resourceDir)", placeholder)
193202
}

‎cache/filecache/filecache_config_test.go‎

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import (
2020
"testing"
2121
"time"
2222

23+
"github.com/gohugoio/hugo/helpers"
24+
2325
"github.com/gohugoio/hugo/config"
2426
"github.com/gohugoio/hugo/hugofs"
25-
"github.com/gohugoio/hugo/hugolib/paths"
2627

2728
"github.com/spf13/viper"
2829
"github.com/stretchr/testify/require"
@@ -35,6 +36,13 @@ func TestDecodeConfig(t *testing.T) {
3536

3637
configStr := `
3738
resourceDir = "myresources"
39+
contentDir = "content"
40+
dataDir = "data"
41+
i18nDir = "i18n"
42+
layoutDir = "layouts"
43+
assetDir = "assets"
44+
archetypeDir = "archetypes"
45+
3846
[caches]
3947
[caches.getJSON]
4048
maxAge = "10m"
@@ -50,7 +58,7 @@ dir = "/path/to/c3"
5058
cfg, err := config.FromConfigString(configStr, "toml")
5159
assert.NoError(err)
5260
fs := hugofs.NewMem(cfg)
53-
p, err := paths.New(fs, cfg)
61+
p, err := helpers.NewPathSpec(fs, cfg)
5462
assert.NoError(err)
5563

5664
decoded, err := decodeConfig(p)
@@ -75,6 +83,13 @@ func TestDecodeConfigIgnoreCache(t *testing.T) {
7583

7684
configStr := `
7785
resourceDir = "myresources"
86+
contentDir = "content"
87+
dataDir = "data"
88+
i18nDir = "i18n"
89+
layoutDir = "layouts"
90+
assetDir = "assets"
91+
archeTypedir = "archetypes"
92+
7893
ignoreCache = true
7994
[caches]
8095
[caches.getJSON]
@@ -91,7 +106,7 @@ dir = "/path/to/c3"
91106
cfg, err := config.FromConfigString(configStr, "toml")
92107
assert.NoError(err)
93108
fs := hugofs.NewMem(cfg)
94-
p, err := paths.New(fs, cfg)
109+
p, err := helpers.NewPathSpec(fs, cfg)
95110
assert.NoError(err)
96111

97112
decoded, err := decodeConfig(p)
@@ -107,8 +122,7 @@ dir = "/path/to/c3"
107122

108123
func TestDecodeConfigDefault(t *testing.T) {
109124
assert := require.New(t)
110-
cfg := viper.New()
111-
cfg.Set("workingDir", filepath.FromSlash("/my/cool/hugoproject"))
125+
cfg := newTestConfig()
112126

113127
if runtime.GOOS == "windows" {
114128
cfg.Set("resourceDir", "c:\\cache\\resources")
@@ -120,7 +134,7 @@ func TestDecodeConfigDefault(t *testing.T) {
120134
}
121135

122136
fs := hugofs.NewMem(cfg)
123-
p, err := paths.New(fs, cfg)
137+
p, err := helpers.NewPathSpec(fs, cfg)
124138
assert.NoError(err)
125139

126140
decoded, err := decodeConfig(p)
@@ -129,12 +143,18 @@ func TestDecodeConfigDefault(t *testing.T) {
129143

130144
assert.Equal(4, len(decoded))
131145

146+
imgConfig := decoded[cacheKeyImages]
147+
jsonConfig := decoded[cacheKeyGetJSON]
148+
132149
if runtime.GOOS == "windows" {
133-
assert.Equal("c:\\cache\\resources\\_gen", decoded[cacheKeyImages].Dir)
150+
assert.Equal("_gen", imgConfig.Dir)
134151
} else {
135-
assert.Equal("/cache/resources/_gen", decoded[cacheKeyImages].Dir)
136-
assert.Equal("/cache/thecache/hugoproject", decoded[cacheKeyGetJSON].Dir)
152+
assert.Equal("_gen", imgConfig.Dir)
153+
assert.Equal("/cache/thecache/hugoproject", jsonConfig.Dir)
137154
}
155+
156+
assert.True(imgConfig.isResourceDir)
157+
assert.False(jsonConfig.isResourceDir)
138158
}
139159

140160
func TestDecodeConfigInvalidDir(t *testing.T) {
@@ -144,6 +164,13 @@ func TestDecodeConfigInvalidDir(t *testing.T) {
144164

145165
configStr := `
146166
resourceDir = "myresources"
167+
contentDir = "content"
168+
dataDir = "data"
169+
i18nDir = "i18n"
170+
layoutDir = "layouts"
171+
assetDir = "assets"
172+
archeTypedir = "archetypes"
173+
147174
[caches]
148175
[caches.getJSON]
149176
maxAge = "10m"
@@ -157,10 +184,24 @@ dir = "/"
157184
cfg, err := config.FromConfigString(configStr, "toml")
158185
assert.NoError(err)
159186
fs := hugofs.NewMem(cfg)
160-
p, err := paths.New(fs, cfg)
187+
p, err := helpers.NewPathSpec(fs, cfg)
161188
assert.NoError(err)
162189

163190
_, err = decodeConfig(p)
164191
assert.Error(err)
165192

166193
}
194+
195+
func newTestConfig() *viper.Viper {
196+
cfg := viper.New()
197+
cfg.Set("workingDir", filepath.FromSlash("/my/cool/hugoproject"))
198+
cfg.Set("contentDir", "content")
199+
cfg.Set("dataDir", "data")
200+
cfg.Set("resourceDir", "resources")
201+
cfg.Set("i18nDir", "i18n")
202+
cfg.Set("layoutDir", "layouts")
203+
cfg.Set("archetypeDir", "archetypes")
204+
cfg.Set("assetDir", "assets")
205+
206+
return cfg
207+
}

0 commit comments

Comments
 (0)