mirror of
https://github.com/gohugoio/hugo.git
synced 2025-04-26 13:40:38 +03:00
Fix same resource file published more than once
This may still happen, though, in low memory situations or very big sites, but I'm not sure it's worth spending time on fixing that. Writing the same file more than once isn't harmful, the negative effect is the false path warning. We may find a way to detect that situation if this becomes a real problem. Fixes #13164
This commit is contained in:
parent
ec0caaec7c
commit
77824d704c
4 changed files with 48 additions and 27 deletions
|
@ -311,12 +311,13 @@ func (fs *RootMappingFs) Open(name string) (afero.File, error) {
|
||||||
|
|
||||||
// Stat returns the os.FileInfo structure describing a given file. If there is
|
// Stat returns the os.FileInfo structure describing a given file. If there is
|
||||||
// an error, it will be of type *os.PathError.
|
// an error, it will be of type *os.PathError.
|
||||||
|
// If multiple roots are found, the last one will be used.
|
||||||
func (fs *RootMappingFs) Stat(name string) (os.FileInfo, error) {
|
func (fs *RootMappingFs) Stat(name string) (os.FileInfo, error) {
|
||||||
fis, err := fs.doStat(name)
|
fis, err := fs.doStat(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return fis[0], nil
|
return fis[len(fis)-1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ComponentPath struct {
|
type ComponentPath struct {
|
||||||
|
|
|
@ -36,6 +36,11 @@ func newResourceCache(rs *Spec, memCache *dynacache.Cache) *ResourceCache {
|
||||||
"/res1",
|
"/res1",
|
||||||
dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
|
dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
|
||||||
),
|
),
|
||||||
|
cacheResourceFile: dynacache.GetOrCreatePartition[string, resource.Resource](
|
||||||
|
memCache,
|
||||||
|
"/res2",
|
||||||
|
dynacache.OptionsPartition{ClearWhen: dynacache.ClearOnChange, Weight: 40},
|
||||||
|
),
|
||||||
CacheResourceRemote: dynacache.GetOrCreatePartition[string, resource.Resource](
|
CacheResourceRemote: dynacache.GetOrCreatePartition[string, resource.Resource](
|
||||||
memCache,
|
memCache,
|
||||||
"/resr",
|
"/resr",
|
||||||
|
@ -58,6 +63,7 @@ type ResourceCache struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
cacheResource *dynacache.Partition[string, resource.Resource]
|
cacheResource *dynacache.Partition[string, resource.Resource]
|
||||||
|
cacheResourceFile *dynacache.Partition[string, resource.Resource]
|
||||||
CacheResourceRemote *dynacache.Partition[string, resource.Resource]
|
CacheResourceRemote *dynacache.Partition[string, resource.Resource]
|
||||||
cacheResources *dynacache.Partition[string, resource.Resources]
|
cacheResources *dynacache.Partition[string, resource.Resources]
|
||||||
cacheResourceTransformation *dynacache.Partition[string, *resourceAdapterInner]
|
cacheResourceTransformation *dynacache.Partition[string, *resourceAdapterInner]
|
||||||
|
@ -79,6 +85,12 @@ func (c *ResourceCache) GetOrCreate(key string, f func() (resource.Resource, err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ResourceCache) GetOrCreateFile(key string, f func() (resource.Resource, error)) (resource.Resource, error) {
|
||||||
|
return c.cacheResourceFile.GetOrCreate(key, func(key string) (resource.Resource, error) {
|
||||||
|
return f()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ResourceCache) GetOrCreateResources(key string, f func() (resource.Resources, error)) (resource.Resources, error) {
|
func (c *ResourceCache) GetOrCreateResources(key string, f func() (resource.Resources, error)) (resource.Resources, error) {
|
||||||
return c.cacheResources.GetOrCreate(key, func(key string) (resource.Resources, error) {
|
return c.cacheResources.GetOrCreate(key, func(key string) (resource.Resources, error) {
|
||||||
return f()
|
return f()
|
||||||
|
|
|
@ -143,19 +143,7 @@ func (c *Client) Get(pathname string) (resource.Resource, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := fi.(hugofs.FileMetaInfo).Meta()
|
return c.getOrCreateFileResource(fi.(hugofs.FileMetaInfo))
|
||||||
pi := meta.PathInfo
|
|
||||||
|
|
||||||
return c.rs.NewResource(resources.ResourceSourceDescriptor{
|
|
||||||
LazyPublish: true,
|
|
||||||
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
|
|
||||||
return c.rs.BaseFs.Assets.Fs.Open(filename)
|
|
||||||
},
|
|
||||||
Path: pi,
|
|
||||||
GroupIdentity: pi,
|
|
||||||
TargetPath: pathname,
|
|
||||||
SourceFilenameOrPath: meta.Filename,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,19 +169,10 @@ func (c *Client) GetMatch(pattern string) (resource.Resource, error) {
|
||||||
return res[0], err
|
return res[0], err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) match(name, pattern string, matchFunc func(r resource.Resource) bool, firstOnly bool) (resource.Resources, error) {
|
func (c *Client) getOrCreateFileResource(info hugofs.FileMetaInfo) (resource.Resource, error) {
|
||||||
pattern = glob.NormalizePath(pattern)
|
|
||||||
partitions := glob.FilterGlobParts(strings.Split(pattern, "/"))
|
|
||||||
key := path.Join(name, path.Join(partitions...))
|
|
||||||
key = path.Join(key, pattern)
|
|
||||||
|
|
||||||
return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) {
|
|
||||||
var res resource.Resources
|
|
||||||
|
|
||||||
handle := func(info hugofs.FileMetaInfo) (bool, error) {
|
|
||||||
meta := info.Meta()
|
meta := info.Meta()
|
||||||
|
return c.rs.ResourceCache.GetOrCreateFile(filepath.ToSlash(meta.Filename), func() (resource.Resource, error) {
|
||||||
r, err := c.rs.NewResource(resources.ResourceSourceDescriptor{
|
return c.rs.NewResource(resources.ResourceSourceDescriptor{
|
||||||
LazyPublish: true,
|
LazyPublish: true,
|
||||||
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
|
OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) {
|
||||||
return meta.Open()
|
return meta.Open()
|
||||||
|
@ -204,6 +183,20 @@ func (c *Client) match(name, pattern string, matchFunc func(r resource.Resource)
|
||||||
TargetPath: meta.PathInfo.Unnormalized().Path(),
|
TargetPath: meta.PathInfo.Unnormalized().Path(),
|
||||||
SourceFilenameOrPath: meta.Filename,
|
SourceFilenameOrPath: meta.Filename,
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) match(name, pattern string, matchFunc func(r resource.Resource) bool, firstOnly bool) (resource.Resources, error) {
|
||||||
|
pattern = glob.NormalizePath(pattern)
|
||||||
|
partitions := glob.FilterGlobParts(strings.Split(pattern, "/"))
|
||||||
|
key := path.Join(name, path.Join(partitions...))
|
||||||
|
key = path.Join(key, pattern)
|
||||||
|
|
||||||
|
return c.rs.ResourceCache.GetOrCreateResources(key, func() (resource.Resources, error) {
|
||||||
|
var res resource.Resources
|
||||||
|
|
||||||
|
handle := func(info hugofs.FileMetaInfo) (bool, error) {
|
||||||
|
r, err := c.getOrCreateFileResource(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
15
testscripts/commands/hugo__path-warnings_issue13164.txt
Normal file
15
testscripts/commands/hugo__path-warnings_issue13164.txt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
hugo --printPathWarnings
|
||||||
|
|
||||||
|
! stderr 'Duplicate target paths'
|
||||||
|
|
||||||
|
-- hugo.toml --
|
||||||
|
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||||
|
-- assets/foo.txt --
|
||||||
|
foo
|
||||||
|
-- layouts/index.html --
|
||||||
|
A: {{ (resources.Get "foo.txt").RelPermalink }}
|
||||||
|
B: {{ (resources.GetMatch "foo.txt").RelPermalink }}
|
||||||
|
C: {{ (index (resources.Match "foo.txt") 0).RelPermalink }}
|
||||||
|
D: {{ (index (resources.ByType "text") 0).RelPermalink }}
|
||||||
|
-- layouts/unused/single.html --
|
||||||
|
{{ .Title }}
|
Loading…
Add table
Add a link
Reference in a new issue