1package cache
2
3import (
4 "fmt"
5
6 "github.com/MichaelMure/git-bug/entities/identity"
7 "github.com/MichaelMure/git-bug/entity"
8 "github.com/MichaelMure/git-bug/repository"
9)
10
11type RepoCacheIdentity struct {
12 *SubCache[*identity.Identity, *IdentityExcerpt, *IdentityCache]
13}
14
15func NewRepoCacheIdentity(repo repository.ClockedRepo,
16 resolvers func() entity.Resolvers,
17 getUserIdentity getUserIdentityFunc) *RepoCacheIdentity {
18
19 makeCached := func(i *identity.Identity, entityUpdated func(id entity.Id) error) *IdentityCache {
20 return NewIdentityCache(i, repo, entityUpdated)
21 }
22
23 makeExcerpt := func(i *identity.Identity) *IdentityExcerpt {
24 return NewIdentityExcerpt(i)
25 }
26
27 makeIndex := func(i *IdentityCache) []string {
28 // no indexing
29 return nil
30 }
31
32 sc := NewSubCache[*identity.Identity, *IdentityExcerpt, *IdentityCache](
33 repo, resolvers, getUserIdentity,
34 makeCached, makeExcerpt, makeIndex,
35 "identity", "identities",
36 formatVersion, defaultMaxLoadedBugs,
37 )
38
39 return &RepoCacheIdentity{SubCache: sc}
40}
41
42// ResolveIdentityImmutableMetadata retrieve an Identity that has the exact given metadata on
43// one of its version. If multiple version have the same key, the first defined take precedence.
44func (c *RepoCacheIdentity) ResolveIdentityImmutableMetadata(key string, value string) (*IdentityCache, error) {
45 return c.ResolveMatcher(func(excerpt *IdentityExcerpt) bool {
46 return excerpt.ImmutableMetadata[key] == value
47 })
48}
49
50func (c *RepoCacheIdentity) NewIdentityFromGitUser() (*IdentityCache, error) {
51 return c.NewIdentityFromGitUserRaw(nil)
52}
53
54func (c *RepoCacheIdentity) NewIdentityFromGitUserRaw(metadata map[string]string) (*IdentityCache, error) {
55 i, err := identity.NewFromGitUser(c.repo)
56 if err != nil {
57 return nil, err
58 }
59 return c.finishIdentity(i, metadata)
60}
61
62// NewIdentity create a new identity
63// The new identity is written in the repository (commit)
64func (c *RepoCacheIdentity) NewIdentity(name string, email string) (*IdentityCache, error) {
65 return c.NewIdentityRaw(name, email, "", "", nil, nil)
66}
67
68// NewIdentityFull create a new identity
69// The new identity is written in the repository (commit)
70func (c *RepoCacheIdentity) NewIdentityFull(name string, email string, login string, avatarUrl string, keys []*identity.Key) (*IdentityCache, error) {
71 return c.NewIdentityRaw(name, email, login, avatarUrl, keys, nil)
72}
73
74func (c *RepoCacheIdentity) NewIdentityRaw(name string, email string, login string, avatarUrl string, keys []*identity.Key, metadata map[string]string) (*IdentityCache, error) {
75 i, err := identity.NewIdentityFull(c.repo, name, email, login, avatarUrl, keys)
76 if err != nil {
77 return nil, err
78 }
79 return c.finishIdentity(i, metadata)
80}
81
82func (c *RepoCacheIdentity) finishIdentity(i *identity.Identity, metadata map[string]string) (*IdentityCache, error) {
83 for key, value := range metadata {
84 i.SetMetadata(key, value)
85 }
86
87 err := i.Commit(c.repo)
88 if err != nil {
89 return nil, err
90 }
91
92 c.mu.Lock()
93 if _, has := c.cached[i.Id()]; has {
94 return nil, fmt.Errorf("identity %s already exist in the cache", i.Id())
95 }
96
97 cached := NewIdentityCache(i, c.repo, c.entityUpdated)
98 c.cached[i.Id()] = cached
99 c.mu.Unlock()
100
101 // force the write of the excerpt
102 err = c.entityUpdated(i.Id())
103 if err != nil {
104 return nil, err
105 }
106
107 return cached, nil
108}