aboutsummaryrefslogtreecommitdiffstats
path: root/cache
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2019-01-19 16:01:06 +0100
committerMichael Muré <batolettre@gmail.com>2019-03-01 22:40:21 +0100
commit844616baf8dc628360942d57fd69f24e298e08da (patch)
tree3fd635e08a06de60618d47ab022554a1f78364de /cache
parentbdbe9e7e8256fff820efe1ce707e7154d517ecb3 (diff)
downloadgit-bug-844616baf8dc628360942d57fd69f24e298e08da.tar.gz
identity: more progress and fixes
Diffstat (limited to 'cache')
-rw-r--r--cache/bug_cache.go4
-rw-r--r--cache/multi_repo_cache.go1
-rw-r--r--cache/repo_cache.go138
3 files changed, 98 insertions, 45 deletions
diff --git a/cache/bug_cache.go b/cache/bug_cache.go
index 25ff000c..53c5c7d9 100644
--- a/cache/bug_cache.go
+++ b/cache/bug_cache.go
@@ -11,6 +11,10 @@ import (
"github.com/MichaelMure/git-bug/util/git"
)
+// BugCache is a wrapper around a Bug. It provide multiple functions:
+//
+// 1. Provide a higher level API to use than the raw API from Bug.
+// 2. Maintain an up to date Snapshot available.
type BugCache struct {
repoCache *RepoCache
bug *bug.WithSnapshot
diff --git a/cache/multi_repo_cache.go b/cache/multi_repo_cache.go
index ec435ff2..da1c26bd 100644
--- a/cache/multi_repo_cache.go
+++ b/cache/multi_repo_cache.go
@@ -8,6 +8,7 @@ import (
const lockfile = "lock"
+// MultiRepoCache is the root cache, holding multiple RepoCache.
type MultiRepoCache struct {
repos map[string]*RepoCache
}
diff --git a/cache/repo_cache.go b/cache/repo_cache.go
index 7d3e7d1d..e1a3d8f8 100644
--- a/cache/repo_cache.go
+++ b/cache/repo_cache.go
@@ -23,6 +23,20 @@ import (
const cacheFile = "cache"
const formatVersion = 1
+// RepoCache is a cache for a Repository. This cache has multiple functions:
+//
+// 1. After being loaded, a Bug is kept in memory in the cache, allowing for fast
+// access later.
+// 2. The cache maintain on memory and on disk a pre-digested excerpt for each bug,
+// allowing for fast querying the whole set of bugs without having to load
+// them individually.
+// 3. The cache guarantee that a single instance of a Bug is loaded at once, avoiding
+// loss of data that we could have with multiple copies in the same process.
+// 4. The same way, the cache maintain in memory a single copy of the loaded identities.
+//
+// The cache also protect the on-disk data by locking the git repository for its
+// own usage, by writing a lock file. Of course, normal git operations are not
+// affected, only git-bug related one.
type RepoCache struct {
// the underlying repo
repo repository.ClockedRepo
@@ -406,9 +420,14 @@ func (c *RepoCache) NewBugRaw(author *identity.Identity, unixTime int64, title s
return nil, err
}
+ if _, has := c.bugs[b.Id()]; has {
+ return nil, fmt.Errorf("bug %s already exist in the cache", b.Id())
+ }
+
cached := NewBugCache(c, b)
c.bugs[b.Id()] = cached
+ // force the write of the excerpt
err = c.bugUpdated(b.Id())
if err != nil {
return nil, err
@@ -546,52 +565,81 @@ func (c *RepoCache) ResolveIdentity(id string) (*identity.Identity, error) {
return i, nil
}
-// ResolveIdentityPrefix retrieve an Identity matching an id prefix. It fails if multiple
-// bugs match.
-// func (c *RepoCache) ResolveIdentityPrefix(prefix string) (*BugCache, error) {
-// // preallocate but empty
-// matching := make([]string, 0, 5)
-//
-// for id := range c.excerpts {
-// if strings.HasPrefix(id, prefix) {
-// matching = append(matching, id)
-// }
-// }
-//
-// if len(matching) > 1 {
-// return nil, bug.ErrMultipleMatch{Matching: matching}
-// }
-//
-// if len(matching) == 0 {
-// return nil, bug.ErrBugNotExist
-// }
-//
-// return c.ResolveBug(matching[0])
-// }
+// ResolveIdentityPrefix retrieve an Identity matching an id prefix.
+// It fails if multiple identities match.
+func (c *RepoCache) ResolveIdentityPrefix(prefix string) (*identity.Identity, error) {
+ // preallocate but empty
+ matching := make([]string, 0, 5)
+
+ for id := range c.identities {
+ if strings.HasPrefix(id, prefix) {
+ matching = append(matching, id)
+ }
+ }
+
+ if len(matching) > 1 {
+ return nil, identity.ErrMultipleMatch{Matching: matching}
+ }
+
+ if len(matching) == 0 {
+ return nil, identity.ErrIdentityNotExist
+ }
+
+ return c.ResolveIdentity(matching[0])
+}
// ResolveIdentityImmutableMetadata retrieve an Identity that has the exact given metadata on
// one of it's version. If multiple version have the same key, the first defined take precedence.
-func (c *RepoCache) ResolveIdentityImmutableMetadata(key string, value string) (*BugCache, error) {
- // // preallocate but empty
- // matching := make([]string, 0, 5)
- //
- // for id, excerpt := range c.excerpts {
- // if excerpt.CreateMetadata[key] == value {
- // matching = append(matching, id)
- // }
- // }
- //
- // if len(matching) > 1 {
- // return nil, bug.ErrMultipleMatch{Matching: matching}
- // }
- //
- // if len(matching) == 0 {
- // return nil, bug.ErrBugNotExist
- // }
- //
- // return c.ResolveBug(matching[0])
-
- // TODO
-
- return nil, nil
+func (c *RepoCache) ResolveIdentityImmutableMetadata(key string, value string) (*identity.Identity, error) {
+ // preallocate but empty
+ matching := make([]string, 0, 5)
+
+ for id, i := range c.identities {
+ if i.ImmutableMetadata()[key] == value {
+ matching = append(matching, id)
+ }
+ }
+
+ if len(matching) > 1 {
+ return nil, identity.ErrMultipleMatch{Matching: matching}
+ }
+
+ if len(matching) == 0 {
+ return nil, identity.ErrIdentityNotExist
+ }
+
+ return c.ResolveIdentity(matching[0])
+}
+
+// NewIdentity create a new identity
+// The new identity is written in the repository (commit)
+func (c *RepoCache) NewIdentity(name string, email string) (*identity.Identity, error) {
+ return c.NewIdentityRaw(name, email, "", "", 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) (*identity.Identity, error) {
+ return c.NewIdentityRaw(name, email, login, avatarUrl, nil)
+}
+
+func (c *RepoCache) NewIdentityRaw(name string, email string, login string, avatarUrl string, metadata map[string]string) (*identity.Identity, error) {
+ i := identity.NewIdentityFull(name, email, login, avatarUrl)
+
+ for key, value := range metadata {
+ i.SetMetadata(key, value)
+ }
+
+ err := i.Commit(c.repo)
+ if err != nil {
+ return nil, err
+ }
+
+ if _, has := c.identities[i.Id()]; has {
+ return nil, fmt.Errorf("identity %s already exist in the cache", i.Id())
+ }
+
+ c.identities[i.Id()] = i
+
+ return i, nil
}