diff options
author | Bjørn Erik Pedersen <[email protected]> | 2024-02-09 13:52:36 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2024-02-16 13:17:53 +0100 |
commit | 639073e4fee8fd4235c1002b076e110fad4c82f2 (patch) | |
tree | 55f4c392bc4f156f8605993d3d416bd5b105cc40 /identity | |
parent | 21d9057dbfe64f668d5fc6a7f458e0984fbf7e56 (diff) | |
download | hugo-639073e4fee8fd4235c1002b076e110fad4c82f2.tar.gz hugo-639073e4fee8fd4235c1002b076e110fad4c82f2.zip |
Fix rebuild with resources.Concat
Fixes #12017
Diffstat (limited to 'identity')
-rw-r--r-- | identity/finder.go | 44 | ||||
-rw-r--r-- | identity/identity.go | 83 |
2 files changed, 68 insertions, 59 deletions
diff --git a/identity/finder.go b/identity/finder.go index bd23d698e..91fac7237 100644 --- a/identity/finder.go +++ b/identity/finder.go @@ -169,12 +169,7 @@ func (f *Finder) checkManager(sid *searchID, m Manager, level int) FinderResult return r } - ids := m.getIdentities() - if len(ids) == 0 { - r = FinderNotFound - } else { - r = f.search(sid, ids, level) - } + r = f.search(sid, m, level) if r == FinderFoundOneOfMany { // Don't cache this one. @@ -270,11 +265,7 @@ func (f *Finder) doCheckOne(sid *searchID, v Identity, depth int) FinderResult { } // search searches for id in ids. -func (f *Finder) search(sid *searchID, ids Identities, depth int) FinderResult { - if len(ids) == 0 { - return FinderNotFound - } - +func (f *Finder) search(sid *searchID, m Manager, depth int) FinderResult { id := sid.id if id == Anonymous { @@ -285,19 +276,24 @@ func (f *Finder) search(sid *searchID, ids Identities, depth int) FinderResult { return FinderNotFound } - for v := range ids { - r := f.checkOne(sid, v, depth) - if r > 0 { - return r - } - - m := GetDependencyManager(v) - if r := f.checkManager(sid, m, depth+1); r > 0 { - return r - } - } - - return FinderNotFound + var r FinderResult + m.forEeachIdentity( + func(v Identity) bool { + if r > 0 { + panic("should be terminated") + } + r = f.checkOne(sid, v, depth) + if r > 0 { + return true + } + m := GetDependencyManager(v) + if r = f.checkManager(sid, m, depth+1); r > 0 { + return true + } + return false + }, + ) + return r } // FinderConfig provides configuration for the Finder. diff --git a/identity/identity.go b/identity/identity.go index ccb2f6e79..c799759df 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -55,8 +55,8 @@ func NewManager(name string, opts ...ManagerOption) Manager { // CleanString cleans s to be suitable as an identifier. func CleanString(s string) string { s = strings.ToLower(s) - s = strings.TrimPrefix(filepath.ToSlash(s), "/") - return path.Clean(s) + s = strings.Trim(filepath.ToSlash(s), "/") + return "/" + path.Clean(s) } // CleanStringIdentity cleans s to be suitable as an identifier and wraps it in a StringIdentity. @@ -77,23 +77,6 @@ func GetDependencyManager(v any) Manager { return nil } -// GetDependencyManagerForScope returns the DependencyManager for the given scope from v or nil if none found. -// Note that it will fall back to an unscoped manager if none found for the given scope. -func GetDependencyManagerForScope(v any, scope int) Manager { - switch vv := v.(type) { - case DependencyManagerScopedProvider: - return vv.GetDependencyManagerForScope(scope) - case types.Unwrapper: - return GetDependencyManagerForScope(vv.Unwrapv(), scope) - case Manager: - return vv - case DependencyManagerProvider: - return vv.GetDependencyManager() - - } - return nil -} - // FirstIdentity returns the first Identity in v, Anonymous if none found func FirstIdentity(v any) Identity { var result Identity = Anonymous @@ -169,7 +152,15 @@ type DependencyManagerScopedProvider interface { type ForEeachIdentityProvider interface { // ForEeachIdentityProvider calls cb for each Identity. // If cb returns true, the iteration is terminated. - ForEeachIdentity(cb func(id Identity) bool) + // The return value is whether the iteration was terminated. + ForEeachIdentity(cb func(id Identity) bool) bool +} + +// ForEeachIdentityProviderFunc is a function that implements the ForEeachIdentityProvider interface. +type ForEeachIdentityProviderFunc func(func(id Identity) bool) bool + +func (f ForEeachIdentityProviderFunc) ForEeachIdentity(cb func(id Identity) bool) bool { + return f(cb) } // ForEeachIdentityByNameProvider provides a way to look up identities by name. @@ -279,9 +270,10 @@ type IsProbablyDependencyProvider interface { type Manager interface { Identity AddIdentity(ids ...Identity) + AddIdentityForEach(ids ...ForEeachIdentityProvider) GetIdentity() Identity Reset() - getIdentities() Identities + forEeachIdentity(func(id Identity) bool) bool } type ManagerOption func(m *identityManager) @@ -301,8 +293,9 @@ type identityManager struct { // mu protects _changes_ to this manager, // reads currently assumes no concurrent writes. - mu sync.RWMutex - ids Identities + mu sync.RWMutex + ids Identities + forEachIds []ForEeachIdentityProvider // Hooks used in debugging. onAddIdentity func(id Identity) @@ -312,7 +305,7 @@ func (im *identityManager) AddIdentity(ids ...Identity) { im.mu.Lock() for _, id := range ids { - if id == Anonymous { + if id == nil || id == Anonymous { continue } if _, found := im.ids[id]; !found { @@ -325,6 +318,12 @@ func (im *identityManager) AddIdentity(ids ...Identity) { im.mu.Unlock() } +func (im *identityManager) AddIdentityForEach(ids ...ForEeachIdentityProvider) { + im.mu.Lock() + im.forEachIds = append(im.forEachIds, ids...) + im.mu.Unlock() +} + func (im *identityManager) ContainsIdentity(id Identity) FinderResult { if im.Identity != Anonymous && id == im.Identity { return FinderFound @@ -355,10 +354,20 @@ func (im *identityManager) String() string { return fmt.Sprintf("IdentityManager(%s)", im.name) } -// TODO(bep) these identities are currently only read on server reloads -// so there should be no concurrency issues, but that may change. -func (im *identityManager) getIdentities() Identities { - return im.ids +func (im *identityManager) forEeachIdentity(fn func(id Identity) bool) bool { + // The absense of a lock here is debliberate. This is currently opnly used on server reloads + // in a single-threaded context. + for id := range im.ids { + if fn(id) { + return true + } + } + for _, fe := range im.forEachIds { + if fe.ForEeachIdentity(fn) { + return true + } + } + return false } type nopManager int @@ -366,6 +375,9 @@ type nopManager int func (m *nopManager) AddIdentity(ids ...Identity) { } +func (m *nopManager) AddIdentityForEach(ids ...ForEeachIdentityProvider) { +} + func (m *nopManager) IdentifierBase() string { return "" } @@ -377,8 +389,8 @@ func (m *nopManager) GetIdentity() Identity { func (m *nopManager) Reset() { } -func (m *nopManager) getIdentities() Identities { - return nil +func (m *nopManager) forEeachIdentity(func(id Identity) bool) bool { + return false } // returns whether further walking should be terminated. @@ -401,11 +413,9 @@ func walkIdentities(v any, level int, deep bool, seen map[Identity]bool, cb func if deep { if m := GetDependencyManager(id); m != nil { - for id2 := range m.getIdentities() { - if walkIdentitiesShallow(id2, level+1, cbRecursive) { - return true - } - } + m.forEeachIdentity(func(id2 Identity) bool { + return walkIdentitiesShallow(id2, level+1, cbRecursive) + }) } } return false @@ -420,6 +430,9 @@ func walkIdentitiesShallow(v any, level int, cb func(level int, id Identity) boo if id == Anonymous { return false } + if id == nil { + return false + } return cb(level, id) } |