aboutsummaryrefslogtreecommitdiffstats
path: root/cache/repo_cache_identity.go
diff options
context:
space:
mode:
Diffstat (limited to 'cache/repo_cache_identity.go')
-rw-r--r--cache/repo_cache_identity.go222
1 files changed, 15 insertions, 207 deletions
diff --git a/cache/repo_cache_identity.go b/cache/repo_cache_identity.go
index 4f612280..a99c7687 100644
--- a/cache/repo_cache_identity.go
+++ b/cache/repo_cache_identity.go
@@ -1,220 +1,28 @@
package cache
import (
- "bytes"
- "encoding/gob"
"fmt"
"github.com/MichaelMure/git-bug/entities/identity"
- "github.com/MichaelMure/git-bug/entity"
)
-const identityCacheFile = "identity-cache"
-
-// identityUpdated is a callback to trigger when the excerpt of an identity
-// changed, that is each time an identity is updated
-func (c *RepoCache) identityUpdated(id entity.Id) error {
- c.muIdentity.Lock()
-
- i, ok := c.identities[id]
- if !ok {
- c.muIdentity.Unlock()
- panic("missing identity in the cache")
- }
-
- c.identitiesExcerpts[id] = NewIdentityExcerpt(i.Identity)
- c.muIdentity.Unlock()
-
- // we only need to write the identity cache
- return c.writeIdentityCache()
-}
-
-// load will try to read from the disk the identity cache file
-func (c *RepoCache) loadIdentityCache() error {
- c.muIdentity.Lock()
- defer c.muIdentity.Unlock()
-
- f, err := c.repo.LocalStorage().Open(identityCacheFile)
- if err != nil {
- return err
- }
-
- decoder := gob.NewDecoder(f)
-
- aux := struct {
- Version uint
- Excerpts map[entity.Id]*IdentityExcerpt
- }{}
-
- err = decoder.Decode(&aux)
- if err != nil {
- return err
- }
-
- if aux.Version != formatVersion {
- return fmt.Errorf("unknown cache format version %v", aux.Version)
- }
-
- c.identitiesExcerpts = aux.Excerpts
- return nil
-}
-
-// write will serialize on disk the identity cache file
-func (c *RepoCache) writeIdentityCache() error {
- c.muIdentity.RLock()
- defer c.muIdentity.RUnlock()
-
- var data bytes.Buffer
-
- aux := struct {
- Version uint
- Excerpts map[entity.Id]*IdentityExcerpt
- }{
- Version: formatVersion,
- Excerpts: c.identitiesExcerpts,
- }
-
- encoder := gob.NewEncoder(&data)
-
- err := encoder.Encode(aux)
- if err != nil {
- return err
- }
-
- f, err := c.repo.LocalStorage().Create(identityCacheFile)
- if err != nil {
- return err
- }
-
- _, err = f.Write(data.Bytes())
- if err != nil {
- return err
- }
-
- return f.Close()
-}
-
-// ResolveIdentityExcerpt retrieve a IdentityExcerpt matching the exact given id
-func (c *RepoCache) ResolveIdentityExcerpt(id entity.Id) (*IdentityExcerpt, error) {
- c.muIdentity.RLock()
- defer c.muIdentity.RUnlock()
-
- e, ok := c.identitiesExcerpts[id]
- if !ok {
- return nil, identity.ErrIdentityNotExist
- }
-
- return e, nil
-}
-
-// ResolveIdentity retrieve an identity matching the exact given id
-func (c *RepoCache) ResolveIdentity(id entity.Id) (*IdentityCache, error) {
- c.muIdentity.RLock()
- cached, ok := c.identities[id]
- c.muIdentity.RUnlock()
- if ok {
- return cached, nil
- }
-
- i, err := identity.ReadLocal(c.repo, id)
- if err != nil {
- return nil, err
- }
-
- cached = NewIdentityCache(c, i)
-
- c.muIdentity.Lock()
- c.identities[id] = cached
- c.muIdentity.Unlock()
-
- return cached, nil
-}
-
-// ResolveIdentityExcerptPrefix retrieve a IdentityExcerpt matching an id prefix.
-// It fails if multiple identities match.
-func (c *RepoCache) ResolveIdentityExcerptPrefix(prefix string) (*IdentityExcerpt, error) {
- return c.ResolveIdentityExcerptMatcher(func(excerpt *IdentityExcerpt) bool {
- return excerpt.Id.HasPrefix(prefix)
- })
-}
-
-// ResolveIdentityPrefix retrieve an Identity matching an id prefix.
-// It fails if multiple identities match.
-func (c *RepoCache) ResolveIdentityPrefix(prefix string) (*IdentityCache, error) {
- return c.ResolveIdentityMatcher(func(excerpt *IdentityExcerpt) bool {
- return excerpt.Id.HasPrefix(prefix)
- })
+type RepoCacheIdentity struct {
+ SubCache[*IdentityExcerpt, *IdentityCache]
}
// ResolveIdentityImmutableMetadata retrieve an Identity that has the exact given metadata on
// one of its version. If multiple version have the same key, the first defined take precedence.
-func (c *RepoCache) ResolveIdentityImmutableMetadata(key string, value string) (*IdentityCache, error) {
- return c.ResolveIdentityMatcher(func(excerpt *IdentityExcerpt) bool {
+func (c *RepoCacheIdentity) ResolveIdentityImmutableMetadata(key string, value string) (*IdentityCache, error) {
+ return c.ResolveMatcher(func(excerpt *IdentityExcerpt) bool {
return excerpt.ImmutableMetadata[key] == value
})
}
-func (c *RepoCache) ResolveIdentityExcerptMatcher(f func(*IdentityExcerpt) bool) (*IdentityExcerpt, error) {
- id, err := c.resolveIdentityMatcher(f)
- if err != nil {
- return nil, err
- }
- return c.ResolveIdentityExcerpt(id)
-}
-
-func (c *RepoCache) ResolveIdentityMatcher(f func(*IdentityExcerpt) bool) (*IdentityCache, error) {
- id, err := c.resolveIdentityMatcher(f)
- if err != nil {
- return nil, err
- }
- return c.ResolveIdentity(id)
-}
-
-func (c *RepoCache) resolveIdentityMatcher(f func(*IdentityExcerpt) bool) (entity.Id, error) {
- c.muIdentity.RLock()
- defer c.muIdentity.RUnlock()
-
- // preallocate but empty
- matching := make([]entity.Id, 0, 5)
-
- for _, excerpt := range c.identitiesExcerpts {
- if f(excerpt) {
- matching = append(matching, excerpt.Id)
- }
- }
-
- if len(matching) > 1 {
- return entity.UnsetId, identity.NewErrMultipleMatch(matching)
- }
-
- if len(matching) == 0 {
- return entity.UnsetId, identity.ErrIdentityNotExist
- }
-
- return matching[0], nil
-}
-
-// AllIdentityIds return all known identity ids
-func (c *RepoCache) AllIdentityIds() []entity.Id {
- c.muIdentity.RLock()
- defer c.muIdentity.RUnlock()
-
- result := make([]entity.Id, len(c.identitiesExcerpts))
-
- i := 0
- for _, excerpt := range c.identitiesExcerpts {
- result[i] = excerpt.Id
- i++
- }
-
- return result
-}
-
-func (c *RepoCache) NewIdentityFromGitUser() (*IdentityCache, error) {
+func (c *RepoCacheIdentity) NewIdentityFromGitUser() (*IdentityCache, error) {
return c.NewIdentityFromGitUserRaw(nil)
}
-func (c *RepoCache) NewIdentityFromGitUserRaw(metadata map[string]string) (*IdentityCache, error) {
+func (c *RepoCacheIdentity) NewIdentityFromGitUserRaw(metadata map[string]string) (*IdentityCache, error) {
i, err := identity.NewFromGitUser(c.repo)
if err != nil {
return nil, err
@@ -224,17 +32,17 @@ func (c *RepoCache) NewIdentityFromGitUserRaw(metadata map[string]string) (*Iden
// NewIdentity create a new identity
// The new identity is written in the repository (commit)
-func (c *RepoCache) NewIdentity(name string, email string) (*IdentityCache, error) {
+func (c *RepoCacheIdentity) NewIdentity(name string, email string) (*IdentityCache, error) {
return c.NewIdentityRaw(name, email, "", "", nil, nil)
}
// NewIdentityFull create a new identity
// The new identity is written in the repository (commit)
-func (c *RepoCache) NewIdentityFull(name string, email string, login string, avatarUrl string, keys []*identity.Key) (*IdentityCache, error) {
+func (c *RepoCacheIdentity) NewIdentityFull(name string, email string, login string, avatarUrl string, keys []*identity.Key) (*IdentityCache, error) {
return c.NewIdentityRaw(name, email, login, avatarUrl, keys, nil)
}
-func (c *RepoCache) NewIdentityRaw(name string, email string, login string, avatarUrl string, keys []*identity.Key, metadata map[string]string) (*IdentityCache, error) {
+func (c *RepoCacheIdentity) NewIdentityRaw(name string, email string, login string, avatarUrl string, keys []*identity.Key, metadata map[string]string) (*IdentityCache, error) {
i, err := identity.NewIdentityFull(c.repo, name, email, login, avatarUrl, keys)
if err != nil {
return nil, err
@@ -242,7 +50,7 @@ func (c *RepoCache) NewIdentityRaw(name string, email string, login string, avat
return c.finishIdentity(i, metadata)
}
-func (c *RepoCache) finishIdentity(i *identity.Identity, metadata map[string]string) (*IdentityCache, error) {
+func (c *RepoCacheIdentity) finishIdentity(i *identity.Identity, metadata map[string]string) (*IdentityCache, error) {
for key, value := range metadata {
i.SetMetadata(key, value)
}
@@ -252,17 +60,17 @@ func (c *RepoCache) finishIdentity(i *identity.Identity, metadata map[string]str
return nil, err
}
- c.muIdentity.Lock()
- if _, has := c.identities[i.Id()]; has {
+ c.mu.Lock()
+ if _, has := c.cached[i.Id()]; has {
return nil, fmt.Errorf("identity %s already exist in the cache", i.Id())
}
cached := NewIdentityCache(c, i)
- c.identities[i.Id()] = cached
- c.muIdentity.Unlock()
+ c.cached[i.Id()] = cached
+ c.mu.Unlock()
// force the write of the excerpt
- err = c.identityUpdated(i.Id())
+ err = c.entityUpdated(i.Id())
if err != nil {
return nil, err
}