Skip to content

Commit 241b21b

Browse files
committed
Create a struct with all of Hugo's config options
Primary motivation is documentation, but it will also hopefully simplify the code. Also, * Lower case the default output format names; this is in line with the custom ones (map keys) and how it's treated all the places. This avoids doing `stringds.EqualFold` everywhere. Closes gohugoio#10896 Closes gohugoio#10620
1 parent 6aededf commit 241b21b

File tree

337 files changed

+13014
-14535
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

337 files changed

+13014
-14535
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11

2-
*.test
2+
*.test
3+
imports.*

cache/docs.go

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Package cache contains the differenct cache implementations.
2+
package cache

cache/filecache/filecache.go

+7-21
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
var ErrFatal = errors.New("fatal filecache error")
3636

3737
const (
38-
filecacheRootDirname = "filecache"
38+
FilecacheRootDirname = "filecache"
3939
)
4040

4141
// Cache caches a set of files in a directory. This is usually a file on
@@ -301,7 +301,7 @@ func (c *Cache) isExpired(modTime time.Time) bool {
301301
}
302302

303303
// For testing
304-
func (c *Cache) getString(id string) string {
304+
func (c *Cache) GetString(id string) string {
305305
id = cleanID(id)
306306

307307
c.nlocker.Lock(id)
@@ -328,38 +328,24 @@ func (f Caches) Get(name string) *Cache {
328328
// NewCaches creates a new set of file caches from the given
329329
// configuration.
330330
func NewCaches(p *helpers.PathSpec) (Caches, error) {
331-
var dcfg Configs
332-
if c, ok := p.Cfg.Get("filecacheConfigs").(Configs); ok {
333-
dcfg = c
334-
} else {
335-
var err error
336-
dcfg, err = DecodeConfig(p.Fs.Source, p.Cfg)
337-
if err != nil {
338-
return nil, err
339-
}
340-
}
341-
331+
dcfg := p.Cfg.GetConfigSection("caches").(Configs)
342332
fs := p.Fs.Source
343333

344334
m := make(Caches)
345335
for k, v := range dcfg {
346336
var cfs afero.Fs
347337

348-
if v.isResourceDir {
338+
if v.IsResourceDir {
349339
cfs = p.BaseFs.ResourcesCache
350340
} else {
351341
cfs = fs
352342
}
353343

354344
if cfs == nil {
355-
// TODO(bep) we still have some places that do not initialize the
356-
// full dependencies of a site, e.g. the import Jekyll command.
357-
// That command does not need these caches, so let us just continue
358-
// for now.
359-
continue
345+
panic("nil fs")
360346
}
361347

362-
baseDir := v.Dir
348+
baseDir := v.DirCompiled
363349

364350
if err := cfs.MkdirAll(baseDir, 0777); err != nil && !os.IsExist(err) {
365351
return nil, err
@@ -368,7 +354,7 @@ func NewCaches(p *helpers.PathSpec) (Caches, error) {
368354
bfs := afero.NewBasePathFs(cfs, baseDir)
369355

370356
var pruneAllRootDir string
371-
if k == cacheKeyModules {
357+
if k == CacheKeyModules {
372358
pruneAllRootDir = "pkg"
373359
}
374360

cache/filecache/filecache_config.go

+47-56
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14+
// Package filecache provides a file based cache for Hugo.
1415
package filecache
1516

1617
import (
@@ -21,110 +22,111 @@ import (
2122
"time"
2223

2324
"github.com/gohugoio/hugo/common/maps"
24-
2525
"github.com/gohugoio/hugo/config"
2626

27-
"github.com/gohugoio/hugo/helpers"
28-
2927
"errors"
3028

3129
"github.com/mitchellh/mapstructure"
3230
"github.com/spf13/afero"
3331
)
3432

3533
const (
36-
cachesConfigKey = "caches"
37-
3834
resourcesGenDir = ":resourceDir/_gen"
3935
cacheDirProject = ":cacheDir/:project"
4036
)
4137

42-
var defaultCacheConfig = Config{
38+
var defaultCacheConfig = FileCacheConfig{
4339
MaxAge: -1, // Never expire
4440
Dir: cacheDirProject,
4541
}
4642

4743
const (
48-
cacheKeyGetJSON = "getjson"
49-
cacheKeyGetCSV = "getcsv"
50-
cacheKeyImages = "images"
51-
cacheKeyAssets = "assets"
52-
cacheKeyModules = "modules"
53-
cacheKeyGetResource = "getresource"
44+
CacheKeyGetJSON = "getjson"
45+
CacheKeyGetCSV = "getcsv"
46+
CacheKeyImages = "images"
47+
CacheKeyAssets = "assets"
48+
CacheKeyModules = "modules"
49+
CacheKeyGetResource = "getresource"
5450
)
5551

56-
type Configs map[string]Config
52+
type Configs map[string]FileCacheConfig
5753

54+
// For internal use.
5855
func (c Configs) CacheDirModules() string {
59-
return c[cacheKeyModules].Dir
56+
return c[CacheKeyModules].DirCompiled
6057
}
6158

6259
var defaultCacheConfigs = Configs{
63-
cacheKeyModules: {
60+
CacheKeyModules: {
6461
MaxAge: -1,
6562
Dir: ":cacheDir/modules",
6663
},
67-
cacheKeyGetJSON: defaultCacheConfig,
68-
cacheKeyGetCSV: defaultCacheConfig,
69-
cacheKeyImages: {
64+
CacheKeyGetJSON: defaultCacheConfig,
65+
CacheKeyGetCSV: defaultCacheConfig,
66+
CacheKeyImages: {
7067
MaxAge: -1,
7168
Dir: resourcesGenDir,
7269
},
73-
cacheKeyAssets: {
70+
CacheKeyAssets: {
7471
MaxAge: -1,
7572
Dir: resourcesGenDir,
7673
},
77-
cacheKeyGetResource: Config{
74+
CacheKeyGetResource: FileCacheConfig{
7875
MaxAge: -1, // Never expire
7976
Dir: cacheDirProject,
8077
},
8178
}
8279

83-
type Config struct {
80+
type FileCacheConfig struct {
8481
// Max age of cache entries in this cache. Any items older than this will
8582
// be removed and not returned from the cache.
86-
// a negative value means forever, 0 means cache is disabled.
83+
// A negative value means forever, 0 means cache is disabled.
84+
// Hugo is leninent with what types it accepts here, but we recommend using
85+
// a duration string, a sequence of decimal numbers, each with optional fraction and a unit suffix,
86+
// such as "300ms", "1.5h" or "2h45m".
87+
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
8788
MaxAge time.Duration
8889

8990
// The directory where files are stored.
90-
Dir string
91+
Dir string
92+
DirCompiled string `json:"-"`
9193

9294
// Will resources/_gen will get its own composite filesystem that
9395
// also checks any theme.
94-
isResourceDir bool
96+
IsResourceDir bool
9597
}
9698

9799
// GetJSONCache gets the file cache for getJSON.
98100
func (f Caches) GetJSONCache() *Cache {
99-
return f[cacheKeyGetJSON]
101+
return f[CacheKeyGetJSON]
100102
}
101103

102104
// GetCSVCache gets the file cache for getCSV.
103105
func (f Caches) GetCSVCache() *Cache {
104-
return f[cacheKeyGetCSV]
106+
return f[CacheKeyGetCSV]
105107
}
106108

107109
// ImageCache gets the file cache for processed images.
108110
func (f Caches) ImageCache() *Cache {
109-
return f[cacheKeyImages]
111+
return f[CacheKeyImages]
110112
}
111113

112114
// ModulesCache gets the file cache for Hugo Modules.
113115
func (f Caches) ModulesCache() *Cache {
114-
return f[cacheKeyModules]
116+
return f[CacheKeyModules]
115117
}
116118

117119
// AssetsCache gets the file cache for assets (processed resources, SCSS etc.).
118120
func (f Caches) AssetsCache() *Cache {
119-
return f[cacheKeyAssets]
121+
return f[CacheKeyAssets]
120122
}
121123

122124
// GetResourceCache gets the file cache for remote resources.
123125
func (f Caches) GetResourceCache() *Cache {
124-
return f[cacheKeyGetResource]
126+
return f[CacheKeyGetResource]
125127
}
126128

127-
func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
129+
func DecodeConfig(fs afero.Fs, bcfg config.BaseConfig, m map[string]any) (Configs, error) {
128130
c := make(Configs)
129131
valid := make(map[string]bool)
130132
// Add defaults
@@ -133,8 +135,6 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
133135
valid[k] = true
134136
}
135137

136-
m := cfg.GetStringMap(cachesConfigKey)
137-
138138
_, isOsFs := fs.(*afero.OsFs)
139139

140140
for k, v := range m {
@@ -170,22 +170,19 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
170170
c[name] = cc
171171
}
172172

173-
// This is a very old flag in Hugo, but we need to respect it.
174-
disabled := cfg.GetBool("ignoreCache")
175-
176173
for k, v := range c {
177174
dir := filepath.ToSlash(filepath.Clean(v.Dir))
178175
hadSlash := strings.HasPrefix(dir, "/")
179176
parts := strings.Split(dir, "/")
180177

181178
for i, part := range parts {
182179
if strings.HasPrefix(part, ":") {
183-
resolved, isResource, err := resolveDirPlaceholder(fs, cfg, part)
180+
resolved, isResource, err := resolveDirPlaceholder(fs, bcfg, part)
184181
if err != nil {
185182
return c, err
186183
}
187184
if isResource {
188-
v.isResourceDir = true
185+
v.IsResourceDir = true
189186
}
190187
parts[i] = resolved
191188
}
@@ -195,33 +192,29 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
195192
if hadSlash {
196193
dir = "/" + dir
197194
}
198-
v.Dir = filepath.Clean(filepath.FromSlash(dir))
195+
v.DirCompiled = filepath.Clean(filepath.FromSlash(dir))
199196

200-
if !v.isResourceDir {
201-
if isOsFs && !filepath.IsAbs(v.Dir) {
202-
return c, fmt.Errorf("%q must resolve to an absolute directory", v.Dir)
197+
if !v.IsResourceDir {
198+
if isOsFs && !filepath.IsAbs(v.DirCompiled) {
199+
return c, fmt.Errorf("%q must resolve to an absolute directory", v.DirCompiled)
203200
}
204201

205202
// Avoid cache in root, e.g. / (Unix) or c:\ (Windows)
206-
if len(strings.TrimPrefix(v.Dir, filepath.VolumeName(v.Dir))) == 1 {
207-
return c, fmt.Errorf("%q is a root folder and not allowed as cache dir", v.Dir)
203+
if len(strings.TrimPrefix(v.DirCompiled, filepath.VolumeName(v.DirCompiled))) == 1 {
204+
return c, fmt.Errorf("%q is a root folder and not allowed as cache dir", v.DirCompiled)
208205
}
209206
}
210207

211-
if !strings.HasPrefix(v.Dir, "_gen") {
208+
if !strings.HasPrefix(v.DirCompiled, "_gen") {
212209
// We do cache eviction (file removes) and since the user can set
213210
// his/hers own cache directory, we really want to make sure
214211
// we do not delete any files that do not belong to this cache.
215212
// We do add the cache name as the root, but this is an extra safe
216213
// guard. We skip the files inside /resources/_gen/ because
217214
// that would be breaking.
218-
v.Dir = filepath.Join(v.Dir, filecacheRootDirname, k)
215+
v.DirCompiled = filepath.Join(v.DirCompiled, FilecacheRootDirname, k)
219216
} else {
220-
v.Dir = filepath.Join(v.Dir, k)
221-
}
222-
223-
if disabled {
224-
v.MaxAge = 0
217+
v.DirCompiled = filepath.Join(v.DirCompiled, k)
225218
}
226219

227220
c[k] = v
@@ -231,17 +224,15 @@ func DecodeConfig(fs afero.Fs, cfg config.Provider) (Configs, error) {
231224
}
232225

233226
// Resolves :resourceDir => /myproject/resources etc., :cacheDir => ...
234-
func resolveDirPlaceholder(fs afero.Fs, cfg config.Provider, placeholder string) (cacheDir string, isResource bool, err error) {
235-
workingDir := cfg.GetString("workingDir")
227+
func resolveDirPlaceholder(fs afero.Fs, bcfg config.BaseConfig, placeholder string) (cacheDir string, isResource bool, err error) {
236228

237229
switch strings.ToLower(placeholder) {
238230
case ":resourcedir":
239231
return "", true, nil
240232
case ":cachedir":
241-
d, err := helpers.GetCacheDir(fs, cfg)
242-
return d, false, err
233+
return bcfg.CacheDir, false, nil
243234
case ":project":
244-
return filepath.Base(workingDir), false, nil
235+
return filepath.Base(bcfg.WorkingDir), false, nil
245236
}
246237

247238
return "", false, fmt.Errorf("%q is not a valid placeholder (valid values are :cacheDir or :resourceDir)", placeholder)

0 commit comments

Comments
 (0)