aboutsummaryrefslogtreecommitdiffhomepage
path: root/identity
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2024-02-09 13:52:36 +0200
committerBjørn Erik Pedersen <[email protected]>2024-02-16 13:17:53 +0100
commit639073e4fee8fd4235c1002b076e110fad4c82f2 (patch)
tree55f4c392bc4f156f8605993d3d416bd5b105cc40 /identity
parent21d9057dbfe64f668d5fc6a7f458e0984fbf7e56 (diff)
downloadhugo-639073e4fee8fd4235c1002b076e110fad4c82f2.tar.gz
hugo-639073e4fee8fd4235c1002b076e110fad4c82f2.zip
Fix rebuild with resources.Concat
Fixes #12017
Diffstat (limited to 'identity')
-rw-r--r--identity/finder.go44
-rw-r--r--identity/identity.go83
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)
}