]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Delay the creation of cache directories until they're used
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 30 Aug 2023 09:05:15 +0000 (11:05 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 30 Aug 2023 13:39:06 +0000 (16:39 +0300)
Fixes #11390

cache/filecache/filecache.go
cache/filecache/filecache_pruner.go
testscripts/commands/new_content.txt [new file with mode: 0644]

index 05d9379b49ba9d7115964223341a8c523c98207e..414478ee2ec46764bed348011ad1ac8789aa0c4e 100644 (file)
@@ -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
index e1b7f1947e1c14a6945ce3b5ba3e31cfefc0017b..2ad6c0bb7e05927db78fd7dd279898d2e9c60dc7 100644 (file)
@@ -53,6 +53,9 @@ func (c *Cache) Prune(force bool) (int, error) {
        if c.pruneAllRootDir != "" {
                return c.pruneRootDir(force)
        }
+       if err := c.init(); err != nil {
+               return 0, err
+       }
 
        counter := 0
 
@@ -117,6 +120,9 @@ func (c *Cache) Prune(force bool) (int, error) {
 }
 
 func (c *Cache) pruneRootDir(force bool) (int, error) {
+       if err := c.init(); err != nil {
+               return 0, err
+       }
        info, err := c.Fs.Stat(c.pruneAllRootDir)
        if err != nil {
                if herrors.IsNotExist(err) {
diff --git a/testscripts/commands/new_content.txt b/testscripts/commands/new_content.txt
new file mode 100644 (file)
index 0000000..2170583
--- /dev/null
@@ -0,0 +1,7 @@
+hugo new site myblog
+cd myblog
+hugo new content --kind post post/first-post.md
+! exists resources
+grep 'draft = true' content/post/first-post.md
+
+