2018-07-25 22:26:25 +03:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/MichaelMure/git-bug/bug"
|
|
|
|
"github.com/MichaelMure/git-bug/repository"
|
|
|
|
)
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type Cacher interface {
|
2018-07-25 22:26:25 +03:00
|
|
|
RegisterRepository(ref string, repo repository.Repo)
|
|
|
|
RegisterDefaultRepository(repo repository.Repo)
|
2018-07-25 22:49:32 +03:00
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
ResolveRepo(ref string) (RepoCacher, error)
|
|
|
|
DefaultRepo() (RepoCacher, error)
|
2018-07-25 22:49:32 +03:00
|
|
|
|
|
|
|
// Shortcut to resolve on the default repo for convenience
|
2018-07-27 02:58:38 +03:00
|
|
|
DefaultResolveBug(id string) (BugCacher, error)
|
|
|
|
DefaultResolveBugPrefix(prefix string) (BugCacher, error)
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type RepoCacher interface {
|
|
|
|
ResolveBug(id string) (BugCacher, error)
|
|
|
|
ResolveBugPrefix(prefix string) (BugCacher, error)
|
2018-07-29 21:58:22 +03:00
|
|
|
AllBugIds() ([]string, error)
|
2018-07-25 22:26:25 +03:00
|
|
|
ClearAllBugs()
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type BugCacher interface {
|
2018-07-29 19:11:33 +03:00
|
|
|
Snapshot() *bug.Snapshot
|
2018-07-25 22:26:25 +03:00
|
|
|
ClearSnapshot()
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
// Cacher ------------------------
|
2018-07-25 22:26:25 +03:00
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type RootCache struct {
|
|
|
|
repos map[string]RepoCacher
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-29 19:11:33 +03:00
|
|
|
func NewCache() RootCache {
|
|
|
|
return RootCache{
|
2018-07-27 02:58:38 +03:00
|
|
|
repos: make(map[string]RepoCacher),
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c *RootCache) RegisterRepository(ref string, repo repository.Repo) {
|
|
|
|
c.repos[ref] = NewRepoCache(repo)
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c *RootCache) RegisterDefaultRepository(repo repository.Repo) {
|
|
|
|
c.repos[""] = NewRepoCache(repo)
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c *RootCache) DefaultRepo() (RepoCacher, error) {
|
2018-07-25 22:26:25 +03:00
|
|
|
if len(c.repos) != 1 {
|
|
|
|
return nil, fmt.Errorf("repository is not unique")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range c.repos {
|
|
|
|
return r, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c *RootCache) ResolveRepo(ref string) (RepoCacher, error) {
|
2018-07-25 22:26:25 +03:00
|
|
|
r, ok := c.repos[ref]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("unknown repo")
|
|
|
|
}
|
|
|
|
return r, nil
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c *RootCache) DefaultResolveBug(id string) (BugCacher, error) {
|
2018-07-25 22:49:32 +03:00
|
|
|
repo, err := c.DefaultRepo()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return repo.ResolveBug(id)
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c *RootCache) DefaultResolveBugPrefix(prefix string) (BugCacher, error) {
|
2018-07-25 22:49:32 +03:00
|
|
|
repo, err := c.DefaultRepo()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return repo.ResolveBugPrefix(prefix)
|
|
|
|
}
|
|
|
|
|
2018-07-25 22:26:25 +03:00
|
|
|
// Repo ------------------------
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type RepoCache struct {
|
2018-07-25 22:26:25 +03:00
|
|
|
repo repository.Repo
|
2018-07-27 02:58:38 +03:00
|
|
|
bugs map[string]BugCacher
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func NewRepoCache(r repository.Repo) RepoCacher {
|
|
|
|
return &RepoCache{
|
2018-07-25 22:26:25 +03:00
|
|
|
repo: r,
|
2018-07-27 02:58:38 +03:00
|
|
|
bugs: make(map[string]BugCacher),
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c RepoCache) ResolveBug(id string) (BugCacher, error) {
|
2018-07-25 22:26:25 +03:00
|
|
|
cached, ok := c.bugs[id]
|
|
|
|
if ok {
|
|
|
|
return cached, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := bug.ReadLocalBug(c.repo, id)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
cached = NewBugCache(b)
|
2018-07-25 22:26:25 +03:00
|
|
|
c.bugs[id] = cached
|
|
|
|
|
|
|
|
return cached, nil
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c RepoCache) ResolveBugPrefix(prefix string) (BugCacher, error) {
|
2018-07-25 22:26:25 +03:00
|
|
|
// preallocate but empty
|
|
|
|
matching := make([]string, 0, 5)
|
|
|
|
|
|
|
|
for id := range c.bugs {
|
|
|
|
if strings.HasPrefix(id, prefix) {
|
|
|
|
matching = append(matching, id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: should check matching bug in the repo as well
|
|
|
|
|
|
|
|
if len(matching) > 1 {
|
|
|
|
return nil, fmt.Errorf("Multiple matching bug found:\n%s", strings.Join(matching, "\n"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(matching) == 1 {
|
|
|
|
b := c.bugs[matching[0]]
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := bug.FindLocalBug(c.repo, prefix)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
cached := NewBugCache(b)
|
2018-07-25 22:26:25 +03:00
|
|
|
c.bugs[b.Id()] = cached
|
|
|
|
|
|
|
|
return cached, nil
|
|
|
|
}
|
|
|
|
|
2018-07-29 21:58:22 +03:00
|
|
|
func (c RepoCache) AllBugIds() ([]string, error) {
|
|
|
|
return bug.ListLocalIds(c.repo)
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c RepoCache) ClearAllBugs() {
|
|
|
|
c.bugs = make(map[string]BugCacher)
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Bug ------------------------
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type BugCache struct {
|
2018-07-25 22:26:25 +03:00
|
|
|
bug *bug.Bug
|
|
|
|
snap *bug.Snapshot
|
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func NewBugCache(b *bug.Bug) BugCacher {
|
|
|
|
return &BugCache{
|
2018-07-25 22:26:25 +03:00
|
|
|
bug: b,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-29 19:11:33 +03:00
|
|
|
func (c BugCache) Snapshot() *bug.Snapshot {
|
2018-07-25 22:26:25 +03:00
|
|
|
if c.snap == nil {
|
|
|
|
snap := c.bug.Compile()
|
|
|
|
c.snap = &snap
|
|
|
|
}
|
2018-07-29 19:11:33 +03:00
|
|
|
return c.snap
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
func (c BugCache) ClearSnapshot() {
|
2018-07-25 22:26:25 +03:00
|
|
|
c.snap = nil
|
|
|
|
}
|