aboutsummaryrefslogtreecommitdiffhomepage
path: root/cache/filecache/filecache.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2023-08-30 11:05:15 +0200
committerBjørn Erik Pedersen <[email protected]>2023-08-30 16:39:06 +0300
commit94fbab2a8865737c8fb7fe1469215a688ba21314 (patch)
tree3ca1a9b6f9cfa7360842633e905f69a7c39b70ea /cache/filecache/filecache.go
parentc3f273b2d7b18f921410cde6e01442694cda5fe7 (diff)
downloadhugo-94fbab2a8865737c8fb7fe1469215a688ba21314.tar.gz
hugo-94fbab2a8865737c8fb7fe1469215a688ba21314.zip
Delay the creation of cache directories until they're used
Fixes #11390
Diffstat (limited to 'cache/filecache/filecache.go')
-rw-r--r--cache/filecache/filecache.go37
1 files changed, 33 insertions, 4 deletions
diff --git a/cache/filecache/filecache.go b/cache/filecache/filecache.go
index 05d9379b4..414478ee2 100644
--- a/cache/filecache/filecache.go
+++ b/cache/filecache/filecache.go
@@ -51,6 +51,9 @@ type Cache struct {
pruneAllRootDir string
nlocker *lockTracker
+
+ initOnce sync.Once
+ initErr error
}
type lockTracker struct {
@@ -103,9 +106,23 @@ func (l *lockedFile) Close() error {
return l.File.Close()
}
+func (c *Cache) init() error {
+ c.initOnce.Do(func() {
+ // Create the base dir if it does not exist.
+ if err := c.Fs.MkdirAll("", 0777); err != nil && !os.IsExist(err) {
+ c.initErr = err
+ }
+ })
+ return c.initErr
+}
+
// WriteCloser returns a transactional writer into the cache.
// It's important that it's closed when done.
func (c *Cache) WriteCloser(id string) (ItemInfo, io.WriteCloser, error) {
+ if err := c.init(); err != nil {
+ return ItemInfo{}, nil, err
+ }
+
id = cleanID(id)
c.nlocker.Lock(id)
@@ -130,6 +147,10 @@ func (c *Cache) WriteCloser(id string) (ItemInfo, io.WriteCloser, error) {
func (c *Cache) ReadOrCreate(id string,
read func(info ItemInfo, r io.ReadSeeker) error,
create func(info ItemInfo, w io.WriteCloser) error) (info ItemInfo, err error) {
+ if err := c.init(); err != nil {
+ return ItemInfo{}, err
+ }
+
id = cleanID(id)
c.nlocker.Lock(id)
@@ -163,6 +184,9 @@ func (c *Cache) ReadOrCreate(id string,
// be invoked and the result cached.
// This method is protected by a named lock using the given id as identifier.
func (c *Cache) GetOrCreate(id string, create func() (io.ReadCloser, error)) (ItemInfo, io.ReadCloser, error) {
+ if err := c.init(); err != nil {
+ return ItemInfo{}, nil, err
+ }
id = cleanID(id)
c.nlocker.Lock(id)
@@ -197,6 +221,9 @@ func (c *Cache) GetOrCreate(id string, create func() (io.ReadCloser, error)) (It
// GetOrCreateBytes is the same as GetOrCreate, but produces a byte slice.
func (c *Cache) GetOrCreateBytes(id string, create func() ([]byte, error)) (ItemInfo, []byte, error) {
+ if err := c.init(); err != nil {
+ return ItemInfo{}, nil, err
+ }
id = cleanID(id)
c.nlocker.Lock(id)
@@ -232,6 +259,9 @@ func (c *Cache) GetOrCreateBytes(id string, create func() ([]byte, error)) (Item
// GetBytes gets the file content with the given id from the cache, nil if none found.
func (c *Cache) GetBytes(id string) (ItemInfo, []byte, error) {
+ if err := c.init(); err != nil {
+ return ItemInfo{}, nil, err
+ }
id = cleanID(id)
c.nlocker.Lock(id)
@@ -250,6 +280,9 @@ func (c *Cache) GetBytes(id string) (ItemInfo, []byte, error) {
// Get gets the file with the given id from the cache, nil if none found.
func (c *Cache) Get(id string) (ItemInfo, io.ReadCloser, error) {
+ if err := c.init(); err != nil {
+ return ItemInfo{}, nil, err
+ }
id = cleanID(id)
c.nlocker.Lock(id)
@@ -347,10 +380,6 @@ func NewCaches(p *helpers.PathSpec) (Caches, error) {
baseDir := v.DirCompiled
- if err := cfs.MkdirAll(baseDir, 0777); err != nil && !os.IsExist(err) {
- return nil, err
- }
-
bfs := afero.NewBasePathFs(cfs, baseDir)
var pruneAllRootDir string