repo_cache.go

  1package cache
  2
  3import (
  4	"fmt"
  5	"io"
  6	"strings"
  7
  8	"github.com/MichaelMure/git-bug/bug"
  9	"github.com/MichaelMure/git-bug/bug/operations"
 10	"github.com/MichaelMure/git-bug/repository"
 11	"github.com/MichaelMure/git-bug/util"
 12)
 13
 14type RepoCacher interface {
 15	Repository() repository.Repo
 16	ResolveBug(id string) (BugCacher, error)
 17	ResolveBugPrefix(prefix string) (BugCacher, error)
 18	AllBugIds() ([]string, error)
 19	ClearAllBugs()
 20
 21	// Mutations
 22	NewBug(title string, message string) (BugCacher, error)
 23	NewBugWithFiles(title string, message string, files []util.Hash) (BugCacher, error)
 24	Fetch(remote string) (string, error)
 25	MergeAll(remote string) <-chan bug.MergeResult
 26	Pull(remote string, out io.Writer) error
 27	Push(remote string) (string, error)
 28}
 29
 30type RepoCache struct {
 31	repo repository.Repo
 32	bugs map[string]BugCacher
 33}
 34
 35func NewRepoCache(r repository.Repo) RepoCacher {
 36	return &RepoCache{
 37		repo: r,
 38		bugs: make(map[string]BugCacher),
 39	}
 40}
 41
 42func (c *RepoCache) Repository() repository.Repo {
 43	return c.repo
 44}
 45
 46func (c *RepoCache) ResolveBug(id string) (BugCacher, error) {
 47	cached, ok := c.bugs[id]
 48	if ok {
 49		return cached, nil
 50	}
 51
 52	b, err := bug.ReadLocalBug(c.repo, id)
 53	if err != nil {
 54		return nil, err
 55	}
 56
 57	cached = NewBugCache(c.repo, b)
 58	c.bugs[id] = cached
 59
 60	return cached, nil
 61}
 62
 63func (c *RepoCache) ResolveBugPrefix(prefix string) (BugCacher, error) {
 64	// preallocate but empty
 65	matching := make([]string, 0, 5)
 66
 67	for id := range c.bugs {
 68		if strings.HasPrefix(id, prefix) {
 69			matching = append(matching, id)
 70		}
 71	}
 72
 73	// TODO: should check matching bug in the repo as well
 74
 75	if len(matching) > 1 {
 76		return nil, fmt.Errorf("Multiple matching bug found:\n%s", strings.Join(matching, "\n"))
 77	}
 78
 79	if len(matching) == 1 {
 80		b := c.bugs[matching[0]]
 81		return b, nil
 82	}
 83
 84	b, err := bug.FindLocalBug(c.repo, prefix)
 85
 86	if err != nil {
 87		return nil, err
 88	}
 89
 90	cached := NewBugCache(c.repo, b)
 91	c.bugs[b.Id()] = cached
 92
 93	return cached, nil
 94}
 95
 96func (c *RepoCache) AllBugIds() ([]string, error) {
 97	return bug.ListLocalIds(c.repo)
 98}
 99
100func (c *RepoCache) ClearAllBugs() {
101	c.bugs = make(map[string]BugCacher)
102}
103
104func (c *RepoCache) NewBug(title string, message string) (BugCacher, error) {
105	return c.NewBugWithFiles(title, message, nil)
106}
107
108func (c *RepoCache) NewBugWithFiles(title string, message string, files []util.Hash) (BugCacher, error) {
109	author, err := bug.GetUser(c.repo)
110	if err != nil {
111		return nil, err
112	}
113
114	b, err := operations.CreateWithFiles(author, title, message, files)
115	if err != nil {
116		return nil, err
117	}
118
119	err = b.Commit(c.repo)
120	if err != nil {
121		return nil, err
122	}
123
124	cached := NewBugCache(c.repo, b)
125	c.bugs[b.Id()] = cached
126
127	return cached, nil
128}
129
130func (c *RepoCache) Fetch(remote string) (string, error) {
131	return bug.Fetch(c.repo, remote)
132}
133
134func (c *RepoCache) MergeAll(remote string) <-chan bug.MergeResult {
135	return bug.MergeAll(c.repo, remote)
136}
137
138func (c *RepoCache) Pull(remote string, out io.Writer) error {
139	return bug.Pull(c.repo, out, remote)
140}
141
142func (c *RepoCache) Push(remote string) (string, error) {
143	return bug.Push(c.repo, remote)
144}