2018-07-25 22:26:25 +03:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/MichaelMure/git-bug/bug"
|
2018-07-30 02:08:45 +03:00
|
|
|
"github.com/MichaelMure/git-bug/bug/operations"
|
2018-07-25 22:26:25 +03:00
|
|
|
"github.com/MichaelMure/git-bug/repository"
|
2018-08-03 00:37:49 +03:00
|
|
|
"github.com/MichaelMure/git-bug/util"
|
2018-07-25 22:26:25 +03:00
|
|
|
)
|
|
|
|
|
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:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-27 02:58:38 +03:00
|
|
|
type RepoCacher interface {
|
2018-07-31 17:43:43 +03:00
|
|
|
Repository() repository.Repo
|
2018-07-27 02:58:38 +03:00
|
|
|
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-30 02:08:45 +03:00
|
|
|
|
|
|
|
// Mutations
|
|
|
|
NewBug(title string, message string) (BugCacher, error)
|
2018-08-03 00:37:49 +03:00
|
|
|
NewBugWithFiles(title string, message string, files []util.Hash) (BugCacher, error)
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
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-08-02 15:56:50 +03:00
|
|
|
|
|
|
|
// Mutations
|
2018-08-02 17:35:13 +03:00
|
|
|
AddComment(message string) error
|
2018-08-03 00:37:49 +03:00
|
|
|
AddCommentWithFiles(message string, files []util.Hash) error
|
2018-08-02 17:35:13 +03:00
|
|
|
ChangeLabels(added []string, removed []string) error
|
|
|
|
Open() error
|
|
|
|
Close() error
|
|
|
|
SetTitle(title string) error
|
2018-08-02 15:56:50 +03:00
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
Commit() error
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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-31 17:43:43 +03:00
|
|
|
func (c *RepoCache) Repository() repository.Repo {
|
|
|
|
return c.repo
|
|
|
|
}
|
|
|
|
|
|
|
|
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-08-02 15:56:50 +03:00
|
|
|
cached = NewBugCache(c.repo, b)
|
2018-07-25 22:26:25 +03:00
|
|
|
c.bugs[id] = cached
|
|
|
|
|
|
|
|
return cached, nil
|
|
|
|
}
|
|
|
|
|
2018-07-31 17:43:43 +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-08-02 15:56:50 +03:00
|
|
|
cached := NewBugCache(c.repo, b)
|
2018-07-25 22:26:25 +03:00
|
|
|
c.bugs[b.Id()] = cached
|
|
|
|
|
|
|
|
return cached, nil
|
|
|
|
}
|
|
|
|
|
2018-07-31 17:43:43 +03:00
|
|
|
func (c *RepoCache) AllBugIds() ([]string, error) {
|
2018-07-29 21:58:22 +03:00
|
|
|
return bug.ListLocalIds(c.repo)
|
|
|
|
}
|
|
|
|
|
2018-07-31 17:43:43 +03:00
|
|
|
func (c *RepoCache) ClearAllBugs() {
|
2018-07-27 02:58:38 +03:00
|
|
|
c.bugs = make(map[string]BugCacher)
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-07-31 17:43:43 +03:00
|
|
|
func (c *RepoCache) NewBug(title string, message string) (BugCacher, error) {
|
2018-08-03 00:37:49 +03:00
|
|
|
return c.NewBugWithFiles(title, message, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *RepoCache) NewBugWithFiles(title string, message string, files []util.Hash) (BugCacher, error) {
|
2018-07-30 02:08:45 +03:00
|
|
|
author, err := bug.GetUser(c.repo)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-08-03 00:37:49 +03:00
|
|
|
b, err := operations.CreateWithFiles(author, title, message, files)
|
2018-07-30 02:08:45 +03:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = b.Commit(c.repo)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
cached := NewBugCache(c.repo, b)
|
2018-07-30 02:08:45 +03:00
|
|
|
c.bugs[b.Id()] = cached
|
|
|
|
|
|
|
|
return cached, nil
|
|
|
|
}
|
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
// Bug ------------------------
|
|
|
|
|
|
|
|
type BugCache struct {
|
|
|
|
repo repository.Repo
|
|
|
|
bug *bug.Bug
|
|
|
|
snap *bug.Snapshot
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewBugCache(repo repository.Repo, b *bug.Bug) BugCacher {
|
|
|
|
return &BugCache{
|
|
|
|
repo: repo,
|
|
|
|
bug: b,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *BugCache) Snapshot() *bug.Snapshot {
|
|
|
|
if c.snap == nil {
|
|
|
|
snap := c.bug.Compile()
|
|
|
|
c.snap = &snap
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
2018-08-02 15:56:50 +03:00
|
|
|
return c.snap
|
|
|
|
}
|
2018-08-01 22:57:12 +03:00
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
func (c *BugCache) ClearSnapshot() {
|
|
|
|
c.snap = nil
|
|
|
|
}
|
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
func (c *BugCache) AddComment(message string) error {
|
2018-08-03 00:37:49 +03:00
|
|
|
return c.AddCommentWithFiles(message, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *BugCache) AddCommentWithFiles(message string, files []util.Hash) error {
|
2018-08-02 15:56:50 +03:00
|
|
|
author, err := bug.GetUser(c.repo)
|
2018-08-01 22:57:12 +03:00
|
|
|
if err != nil {
|
2018-08-02 17:35:13 +03:00
|
|
|
return err
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-03 00:37:49 +03:00
|
|
|
operations.CommentWithFiles(c.bug, author, message, files)
|
2018-08-01 22:57:12 +03:00
|
|
|
|
|
|
|
// TODO: perf --> the snapshot could simply be updated with the new op
|
2018-08-02 15:56:50 +03:00
|
|
|
c.ClearSnapshot()
|
2018-08-01 22:57:12 +03:00
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
return nil
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
func (c *BugCache) ChangeLabels(added []string, removed []string) error {
|
2018-08-01 22:57:12 +03:00
|
|
|
author, err := bug.GetUser(c.repo)
|
|
|
|
if err != nil {
|
2018-08-02 17:35:13 +03:00
|
|
|
return err
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
err = operations.ChangeLabels(nil, c.bug, author, added, removed)
|
2018-08-01 22:57:12 +03:00
|
|
|
if err != nil {
|
2018-08-02 17:35:13 +03:00
|
|
|
return err
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: perf --> the snapshot could simply be updated with the new op
|
2018-08-02 15:56:50 +03:00
|
|
|
c.ClearSnapshot()
|
2018-08-01 22:57:12 +03:00
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
return nil
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
func (c *BugCache) Open() error {
|
2018-08-01 22:57:12 +03:00
|
|
|
author, err := bug.GetUser(c.repo)
|
|
|
|
if err != nil {
|
2018-08-02 17:35:13 +03:00
|
|
|
return err
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
operations.Open(c.bug, author)
|
2018-08-01 22:57:12 +03:00
|
|
|
|
|
|
|
// TODO: perf --> the snapshot could simply be updated with the new op
|
2018-08-02 15:56:50 +03:00
|
|
|
c.ClearSnapshot()
|
2018-08-01 22:57:12 +03:00
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
return nil
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
func (c *BugCache) Close() error {
|
2018-08-01 22:57:12 +03:00
|
|
|
author, err := bug.GetUser(c.repo)
|
|
|
|
if err != nil {
|
2018-08-02 17:35:13 +03:00
|
|
|
return err
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
operations.Close(c.bug, author)
|
2018-08-01 22:57:12 +03:00
|
|
|
|
|
|
|
// TODO: perf --> the snapshot could simply be updated with the new op
|
2018-08-02 15:56:50 +03:00
|
|
|
c.ClearSnapshot()
|
2018-08-01 22:57:12 +03:00
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
return nil
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
func (c *BugCache) SetTitle(title string) error {
|
2018-08-01 22:57:12 +03:00
|
|
|
author, err := bug.GetUser(c.repo)
|
|
|
|
if err != nil {
|
2018-08-02 17:35:13 +03:00
|
|
|
return err
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 15:56:50 +03:00
|
|
|
operations.SetTitle(c.bug, author, title)
|
2018-08-01 22:57:12 +03:00
|
|
|
|
|
|
|
// TODO: perf --> the snapshot could simply be updated with the new op
|
2018-08-02 15:56:50 +03:00
|
|
|
c.ClearSnapshot()
|
2018-07-25 22:26:25 +03:00
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
return nil
|
2018-07-25 22:26:25 +03:00
|
|
|
}
|
|
|
|
|
2018-08-02 17:35:13 +03:00
|
|
|
func (c *BugCache) Commit() error {
|
|
|
|
return c.bug.Commit(c.repo)
|
2018-08-01 22:57:12 +03:00
|
|
|
}
|